Exposing some services and keeping others private reddit / selfhosted ---------------------------------------------------------------------- frank20a · 2023-12-16 01:56 I am running a self hosted server using docker containers and NPM as a reverse proxy. I have some web servers that I want exposed to the internet and I want of course my Portainer, Dashboard, etc. only accessible from the internal network. My setup right now includes Cloudflare as a DNS service where I have * An A and AAAA record pointing at my static home ip proxied through cloudflare * Multiple CNAME records on 3rd level domains for my web servers pointing at my domain name (e.g. [website1.mydomain.com](https://website1.mydomain.com)) proxied through cloudflare * Multiple A records pointing at the local ip of my server on my home network for different services (e.g. [dashboard.mydomain.com](https://dashboard.mydomain.com) points to 192.168.1.69) NPM functions as a reverse proxy, routing traffic to each service. I am forwarding ports 80 and 443 on my router. With this setup I only have access to my services from inside my network where the domain points to a local IP. Outside my network the same local IP is not reachable. My question is: Is this safe? A possible solution I was thinking about would be to route traffic from my web servers to a different port, e.g. 8080 which would be forwarded to 80 on WAN through my router. Port 80 would be kept closed internally and used only for local services. But I do not know how to do this using NPM. ---------------------------------------------------------------------- thekrautboy · 2023-12-16 01:58 > My question is: Is this safe? Yes. ---------------------------------------------------------------------- frank20a · 2023-12-16 02:01 That was easy... ---------------------------------------------------------------------- thekrautboy · 2023-12-16 02:05 Okay? ---------------------------------------------------------------------- frank20a · 2023-12-16 02:10 Appologies... Reddit for some reason only showed me "Yes" as your answer. Since you argue my setup is solid there's no real reason for me to explain the logic behind my suggestion but let's do it anyway. * Router forwards LAN port 8080 to WAN port 80 * NPM proxies services to LAN port 80 which does not get exposed * NPM proxies webservers to LAN port 8080 which gets exposed to WAN port 80 I am in no way a network expert my logic might actually make zero sense. ---------------------------------------------------------------------- thekrautboy · 2023-12-16 02:49 > Router forwards LAN port 8080 to WAN port 80 Probably the outer way around, forwarding incoming (WAN) to LAN > NPM proxies services to LAN port 80 which does not get exposed > NPM proxies webservers to LAN port 8080 which gets exposed to WAN port 80 Why are you trying to seperate internal/external services by their ports? Youre making it much more complicated and harder on yourself. Let your DNS records decide if someone can reach your proxy for that service or not. External services get a DNS record that can be reached from the outside, like a `A` record pointing to your WAN IP. Internal services get a DNS record that can only be reached from the inside, like a `A` record pointing to a LAN IP, like `192.168.x.x` as basic example. If someone requests a internal subdomain from the outside, they receive a internal IP but if that IP is not routed, they fail to connect. If someone requests a external subdomain from the outside, they receive a valid external IP and they might be able to connec to that (if there is a server responding etc). Its not that complicated, and again, tons of discussions about exactly this exist already, use the search function. ---------------------------------------------------------------------- Cirx0808 · 2023-12-16 09:47 If a person scans their domain for common subdomains and gets a mix of internal and external IPs it's not going to take them long to figure out they can set a host entry to hit the domain from the external IP and reach all the internal services. OP - Either set up 2 NPMs. One for internal, one for external or use the access list feature to lock internal services down to private IP ranges. ---------------------------------------------------------------------- thekrautboy · 2023-12-16 09:57 Thats not how it works. ---------------------------------------------------------------------- Cirx0808 · 2023-12-16 11:30 How does it work then? A reverse proxy simply takes a DNS entry and forwards it to a backend server. If I create my own DNS host entry pointing to a reverse proxy that is configured to route that DNS entry it will do so. ---------------------------------------------------------------------- Trixster82 · 2023-12-16 11:47 So if this is mainly docker based, your localhost access versus external access for internet based VPS hosting is *if I recall* the publish command. The publish (-p 8080:80) will then automatically open the port up for external access on the given port binding, etc. (This causes a lot of confusion when it punches holes in the localhosts firewall automatically). Otherwise docker assigns an internal "docker network" IP (as in only available between docker containers) and exposes the ORIGINAL container port, but only on that private docker network. What this means is something like a proxy (NPM, etc) you can expose purely the external port (80, 443, binded, mapped, etc) and have it use its internal docker IP to access your internal docker network. This means only one published port is exposed to anything outside the localhost. You can also do this with things like a wireguard server (as an example) which exposes only the inbound port, 51821 or whatever it is setup for. And it gives you access to the internal services via the internal "docker network". Good for hostile LAN environments (but that's another story). Option A: With that information you can adapt it to your server behind your firewall. Firewall: Forward port XYZ to the published port on your NPM container. NPM for internal and externally accessible containers: Create entries that can be accessed on the same host via internal "docker network" Internal only accessible containers: Use the publish (-p) to expose your containers on the relevant ports on an internal IP address. To be able to forget everything after: Create a homer/Heimdall/whatever dashboard container with all your addresses and ports logged. Option B: Burn it with fire and do it one of the other million ways you'll get told are far better because... Everyone has favourites... Everyone knows their favourite is better... no one's favourites are the same... and... Well... You can. :) ---------------------------------------------------------------------- revereddesecration · 2023-12-16 12:50 You can point your domain name to my reverse proxy, but my reverse proxy won’t route your traffic because I haven’t told it to. ---------------------------------------------------------------------- Cirx0808 · 2023-12-16 13:23 Exactly, but I can point your domain to your reverse proxy and it will route the traffic. The above user is telling OP his private services will remain private because he set up DNS with an un-routable private IP. But if I know your domain name and I know your IP that I've taken from one of your other DNS records I can now access your private services. ---------------------------------------------------------------------- frank20a · 2023-12-16 14:09 That was exactly what i thought could be a vulnerability to my setup. Cloudflare masks my WAN ip on DNS records but this is not the only way to get one's IP address. ---------------------------------------------------------------------- Cirx0808 · 2023-12-16 14:34 If you're using CF proxying you should be fairly safe from this. It is still a weak point but as far as targeted attacks it would be far more difficult to get a hold of your masked IP unless you leak it somehow via another DNS record. The only thing I would be weary of is bots scanning IP ranges but the chances are they won't know or spend the time looking for the domain name combination to use. This type of attack would be more targeted and personal but very possible with the setup suggested above. I'm seem to be getting downvoted but I personally won't be hosting my personal password vault on a setup like this. Completely segregated from my public points of access. If I need access I can VPN to it. ---------------------------------------------------------------------- frank20a · 2023-12-16 14:45 Docker indeed uses internal networks and forwards ports to the host using the ports command. My setup right now uses a network called "proxied" shared by NPM, my services and webservers so the only ports exposed from docker to my host are 80, 443, 81 (in case NPM fails) and the portainer port (in case NPM fails). All other services are exposed through NPM and accessed in the internal "proxied" network After reading your comment and other suggestions I will change my setup to the following which I think is very secure but anyone please feel free to correct me. 2 NPM installations: * NPM\_internal forwarding host port 80, 443 to docker port 80, 443 on the docker network "proxied\_internal" * NPM\_external forwarding host port 8080, 8443 to docker port 80 on the docker network "proxied\_external" Router forwards only WAN ports 80, 443 to LAN ports 8080, 8443 on my servers LAN IP DNS stays as it is (read OP) Docker: * No ports are forwarded from host to docker containers (with the exception of portainer for debug reasons). * Services that I want kept private are on the "proxied\_internal" docker network and are proxied through NPM\_internal using DNS A records that point to local IP and with access rules that only allow local ips. * Web servers that I want exposed to the internet are on the "proxied\_external" docker network, proxied through NPM\_external using DNS CNAME records that point to DNS A records that (throght Cloudflare) points to my public IP. ---------------------------------------------------------------------- revereddesecration · 2023-12-16 15:00 What do you mean by “get my IP address”? Your services should not be accessible via your public WAN IP. Most internet hosts don’t even offer those any more, see [CG- NAT](https://en.m.wikipedia.org/wiki/Carrier-grade_NAT). ---------------------------------------------------------------------- frank20a · 2023-12-16 15:04 I understand why one think that but my ISP not only does not use CG- NAT (at least at my connection) but my IP is also static by default. My services are very much accessible from my WAN IP. The easiest way for someone to get my IP would be from me accidentally leaking it. Which knowing how clumpsy I am is a solid possibility ---------------------------------------------------------------------- frank20a · 2023-12-16 15:06 I undestand and agree with your points. Ideally I would only expose a VPN and access everything from there but I do need public access to my webserver. Check my [other comment](https://www.reddit.com/r/selfhoste d/comments/18jgdx8/comment/kdm83mf/?utm_source=share&utm_medium=web3x& utm_name=web3xcss&utm_term=1&utm_content=share_button) for the new setup I am thinking about and tell me your opinion! ---------------------------------------------------------------------- sk1nT7 · 2023-12-16 15:07 Question: Does NPM have a proxy host entry for dashboard.mydomain.com too? If so, an attacker may be able to access your internal service if he can manage to guess or obtain your real WAN IP behind cloudflare. He would then directly talk to your NPM instance which will proxy to the service as you have not configured an access list to allow local lan access only. You mach check censys search with your domain name and see whether your real WAN IP is already leaked. ---------------------------------------------------------------------- revereddesecration · 2023-12-16 15:09 That’s fine, but if you don’t forward ports on your router, there’s no issue with anybody “having your IP”. ---------------------------------------------------------------------- frank20a · 2023-12-16 15:16 Answer to your question: Yes This is the type of vulnerability I was thinking about. I think I found a solution described on [another comment](https://www.reddit.com /r/selfhosted/comments/18jgdx8/comment/kdm83mf/?utm_source=share&utm_m edium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button). Read and let me know if you want. ---------------------------------------------------------------------- frank20a · 2023-12-16 15:45 The whole discussion is happening because I need to forward port on my router to expose some web servers to the internet ---------------------------------------------------------------------- revereddesecration · 2023-12-16 16:45 No, you don’t need to. There are other options. One that everybody recommends is TailScale, or CloudFlare Tunnels. I use a VPN and a small VPS and forward ports to the VPS which runs a reverse proxy. ---------------------------------------------------------------------- frank20a · 2023-12-16 16:50 I was not aware of such services. I will have a look, thank you! ---------------------------------------------------------------------- revereddesecration · 2023-12-16 16:52 The general thing they do is this: your machine has a connection with an external service that handles the connection and authentication, and then the external service forwards the traffic through to your machine. Safe, secure, simple. ---------------------------------------------------------------------- Trixster82 · 2023-12-16 20:56 Sounds like it'll make a cool setup. Let us know how you get on with it and if it works as expected. ---------------------------------------------------------------------- 83736294827 · 2023-12-17 01:07 Lots of ways to do this but I found the most straightforward way was to setup a wildcard cert on my reverse proxy and then have that forward to any servers/containers I have set up. I then restrict any internal services by telling the reverse proxy to only serve my internal subnet for those services. There are pros and cons, but it is simple as it only requires a single dns record and no separate internal dns. It also keeps my internal subdomains from being listed in dns records or ssl certs. This does rely on an external dns record so I could add a separate internal dns cache/server but it’s not required.