I have some subdomains that go to my home address (I know I should put it through a VPS first but I’ll get to that when I have time).
If I connect to example.domain.tld and DNS records point back to my own IP, where does that data go to reach back to my device?
You can see every hop an IP packet takes at IP level with
tracerouteormtr.Depends, you can set it up a few different ways.
-
you can set the dns so each subdomain resolves to a different port with your ip, in which case your router can forward that port to any local address on your network with port forwarding rules.
-
reverse proxy, this is most common. You use a service to do the translating for you. Your router forwards all requests on port 80 and 443 to your reverse proxy. The reverse proxy takes requests for subdomain1 and forwards it to the associated ip/port locally.
I have a reverse proxy set up already. The path from the outside goes:
DNS -> my IP -> reverse proxy -> server
I’m just wondering what happens when my own devices on the same network go to the domain.
Devices on your domain will typically do a DNS lookup, which gets your public IP. Then they connect to that public IP, which your router recognises and redirects back into your network. The router then forwards that to your reverse proxy.
If your router isnt doing that properly (timing out usually), look up a setting usually called “NAT loopback” or “NAT hairpinning”. Thats the setting that detects your public IP, and redirects it back inward.
Also if you have your own net filter like PiHole or AdGuard Home with DNS rewrites set up, and you use it as a DNS server in WiFi settings, then it works a small bit differently. (I need to do this because my current ISP removed their DNS settings page for the new model). A public IP and NAT routing is never needed, as the device contacts the DNS server via the router Access Point, and the DNS server translates the service’s FQDN into its internal IP. Aside from that, provided everything is set up correctly, all actual data packets go from device ←→ router ←→ service. If the router lost connection to the Internet this wouldn’t break communications.
I had issues with that recently, I had a few of my internal services set to resolve internally, but pihole was making a mess of them and returning IPv6 addresses in addition to the IPv4 internal addresses. And then browsers would try use the broken ipv6 address and fail. I just happily rely on hairpinning now, it hardly makes a difference in the scheme of things.
Your diagram is almost right, but I think it will help to understand more of the details. It’s important to understand the difference between DNS (domain name lookup) and IP routing.
To break your diagram down more, this is what happens when any computer looks up your website:
- The device does a DNS lookup of “example.com” using their name server, which may forward it to another DNS server (most home routers do this). I won’t go into the multiple levels of DNS lookups and caching here.
- Through looking it up by DNS, the device now has the final IP. DNS is now out of the picture and we’re doing IP routing.
- The device tries to make an HTTP connection to your external IP. HTTP is a protocol that runs over TCP/IP (UDP is used for QUIC/HTTP3). To keep things simple I’ll stick with old fashioned HTTP over TCP without SSL. I am also skipping over NAT.
- For TCP, it performs a handshake, which the reverse proxy will negotiate. Once the connection is established, the browser speaks HTTP to the reverse proxy. It looks something like:
GET / HTTP/1.1 Host: example.com ...lots more headers... <blank line>- The reverse proxy then takes that request, maps it to an upstream (if any), and makes another request to it via the configured transport. If that part falls down, you will see a 503 error. Otherwise, you will see the response from the upstream, possibly with some modifications made by the reverse proxy (some will rewrite links and cookie paths, for example)
- The reverse proxy sends that response back to the client.
That’s all very simplified, of course.
As others pointed out, things may seem to work differently from the “inside”, if hairpinning is not available or enabled. This is not related to DNS, but to IP routing. The firewall doing NAT can get confused and not know what to do when an internal request goes to an external IP that it itself has. When it turns that around and routes it back to the internal network, that’s called hairpinning.
One “fix” for this, often used in enterprises, is to use so-called split DNS. All that means is that if you’re asking your internal DNS server for an internal name, it will give you the internal address (192.168.1.123 for example), but an external client would get an external IP.
TL;DR: DNS and IP routing are separate concerns and happen at different parts of the TCP/IP stack.
https://en.wikipedia.org/wiki/Network_address_translation#NAT_hairpinning
TL;DR Your router sees you trying to reach your external address and routes the connection back to your LAN without leaving the network.
This does still depend on a functional internet connection however, as your client gets your public IP from a public DNS server over the Internet.
If you were to run a DNS server locally (I use pihole for this), you could have that DNS respond with your local IP, allowing clients within your LAN to resolve the name without needing to reach out to public DNS. This means your local connections will still work when your internet is down; it also provides more privacy by keeping those requests local and can let you make local-only names that aren’t publicly listed.
Of the ~28 FQDNs in my setup, only 4 are public. The rest is local/vpn only and not publicly listed due the above. The reverse proxy then drops all connections that don’t use one of those recognised names, before even completing the TLS handshake. (So direct connections from someone port scanning my IP or using a domain name someone else has pointed at my IP are completely ignored/dropped without response. The server doesn’t even send the TLS cert so as to not expose the names defined in it.)
-
This is something you can easily do from the command terminal. For Windows, use Tracert. Linux and Mac, maybe even iPhone and Android have their own commands to run a trace route, too (I don’t know them off the top of my head).
It’s called “traceroute” on Linux and Mac because there was never a 8.3 filename limitation on them.
Microsoft had to put it on a diet. It was getting a little FAT.
Take my upvote and get out.
With IPv4, assuming you have a residential contract without cgnat, your router has your ip. Loosely your device calls your public ip, realizes it is not on your local network, and sends it to your router. The router will nat it, and send it to its own internet-facing networking side, where the same router will realize that the target ip is the ip of it’s own interface and will immediately accept it. Then it is handled like any other packet arriving from the internet, presumably port forwarded to some internal machine.
So we expect one hop to the router, then one internal hop from the private to the internet-facing interface of the router, and then presumably another internal hop back to the private network interface and another proper hop to the server on your lan.





