Put a router behind a router and every packet gets translated twice. Web pages still load, so nobody notices, until a game console, a remote desktop session or a VPN needs someone to reach in. This chapter is about the layers you can't see, and the protocols that try, and fail, to punch through them.
Common mix-up: a 100.x.y.z address on your computer doesn't prove you're behind carrier-grade NAT. Tailscale deliberately numbers its own virtual network out of the same 100.64.0.0/10 block. What matters is the address on your router's internet (WAN) port.
Double NAT almost always happens by accident. Your ISP installs a gateway: a modem with a router, Wi-Fi and NAT built in. Then you buy a mesh Wi-Fi system or a gaming router, plug it into the gateway, and follow its setup app. The new router asks the gateway for an address over DHCP, gets something like 192.168.1.45, and builds its own private network behind it, perhaps 192.168.86.0/24. Now there are two private networks stacked like boxes inside boxes, and two NATs between your laptop and the internet.
Follow a packet. The laptop, 192.168.86.23, sends to a web server. The inner router rewrites the source to its WAN address, 192.168.1.45, and writes a row in its table. The outer gateway receives a packet from 192.168.1.45, which to it is just another device on its LAN, rewrites the source again to the real public address, 203.0.113.7, and writes a row in its table. The reply comes back and is un-translated twice, outer table first, inner table second.
For anything the laptop starts, this works perfectly. Each NAT does exactly what Chapter 7 describes, and neither knows the other exists. The cost is a few microseconds of extra processing and one extra hop in traceroute. That's why double NAT can live in a house for years before anyone spots it.
The trouble is all inbound. For a packet from the internet to reach the laptop, both tables need a row that leads inward. A port forward on the inner router alone is useless: the packet dies at the outer gateway, which has never heard of it. A forward on the outer gateway alone delivers the packet to the inner router's WAN port, where it dies instead. Every inbound path has to be built twice, once per layer, and kept in step.
A stacked router has two interfaces: a WAN side on the outer network and a LAN side on its own. Those two networks must use different address ranges. If the outer gateway hands out 192.168.1.0/24 and the inner router also builds 192.168.1.0/24 behind itself, the inner router has two routes to the same addresses and no way to choose. Most routers detect this and quietly renumber their LAN, which is one reason mesh systems tend to default to unusual ranges like 192.168.86.0/24 or 10.0.0.0/24 in the first place.
You can spot a stack from any device by running traceroute (tracert on Windows) to anything on the internet. The first hop is your router. If the second hop is another private address, such as 192.168.1.1 or 10.0.0.1, there's a second router in the house. Chapter 13 walks through reading that output.
An ISP with more customers than IPv4 addresses has the same problem you do, at a larger scale, and reaches for the same fix. Instead of giving each customer's router a public address, it gives each one a private-looking address and runs an enormous NAT of its own, shared by hundreds or thousands of customers. That's carrier-grade NAT, CGNAT or CGN for short. Most mobile networks have worked this way for years; many fixed-line and satellite ISPs do too.
Which private addresses should the ISP use for that middle layer? Not the RFC 1918 ranges, because its customers already use those at home, and a customer whose LAN is 10.0.0.0/24 can't have a WAN address in 10.0.0.0/8 without exactly the overlap problem described above. So in 2012 the IETF set aside a fresh block for it, 100.64.0.0/10, in RFC 6598. It runs from 100.64.0.0 to 100.127.255.255, about four million addresses, and is called shared address space. It's meant to appear only between a provider's NAT and its customers' routers, never on the public internet and never inside a home.
A CGNAT stacked on your own router is double NAT again, with the outer layer in a building you can't visit. The operators sometimes call it NAT444: private IPv4 in your house, shared IPv4 in the middle, public IPv4 outside. And if you also have your own second router at home, that's three layers.
Big NATs have extra problems. Thousands of customers share each public address, so the ports have to be rationed. Many CGNATs give each customer a fixed port block, say 1,024 or 2,048 ports, which also makes logs manageable: when law enforcement asks who used 198.51.100.9 port 31337 at a particular moment, the ISP has to be able to answer. RFC 6888 lists the requirements for CGNATs, including endpoint-independent mapping and fair port sharing. Websites that block an abusive IP address end up blocking everyone behind it, which is why CGNAT customers see more CAPTCHAs.
Two numbers settle it. First, log in to your router and find the address on its WAN or internet port. Second, visit any "what is my IP" website, which reports the address your packets arrive from.
Instrument 2 below does this reasoning for you.
The block size was a compromise. A /10 is big enough for a large provider to number every customer router in a region without reuse, and small enough to be spared from a nearly empty IANA pool in 2012. RFC 6598 is explicit that the space is not for general private use: a device that sees it should treat it like a private address, not route it to the internet, and not assume it's globally unique.
Because it's reserved and almost never used inside homes, overlay networks have adopted it. Tailscale gives every device on a tailnet an address from 100.64.0.0/10, so your laptop may show both a 192.168.86.x address on Wi-Fi and a 100.x.y.z address on its Tailscale adapter. That 100.x address says nothing about your ISP.
Nothing that only connects outward. Everything that needs to be reached.
A laptop on 192.168.86.0/24 sits behind a mesh router, which sits behind the ISP's gateway on 192.168.1.0/24. Send a packet out and watch its source address get rewritten at each layer, with a row added to each table. Then have a peer on the internet try to reach UDP port 41641 (the port Tailscale's WireGuard listens on by default), ask the gateway for a mapping, and see which box hears the request. Toggle bridge mode on the outer gateway and one whole layer disappears.
Send a packet out to begin.
Port forwarding by hand is tedious, so routers learned to take requests. A program on the LAN that wants to be reachable asks the router: "please forward public port 41641 to me, for the next two hours." Three protocols do this.
UPnP Internet Gateway Device (UPnP-IGD) is the oldest and most widespread. A device finds the router by multicasting an SSDP search to 239.255.255.250 port 1900, fetches an XML description of the router's services, and then calls an AddPortMapping action over HTTP with a SOAP message. It works on most consumer routers and has a long history of security trouble, because it typically accepts requests from any device on the LAN without authentication. Many people turn it off on principle.
NAT-PMP, the NAT Port Mapping Protocol, came from Apple and was published as RFC 6886. It's tiny by comparison: a few bytes of UDP sent to port 5351 on the device's default gateway. Opcode 0 asks "what is your external address?"; opcodes 1 and 2 request a UDP or TCP mapping with a lifetime (the RFC recommends 7,200 seconds). The gateway answers with the public port it actually granted, which may differ from the one requested.
PCP, the Port Control Protocol, is NAT-PMP's successor, RFC 6887. It uses the same server port, 5351, and adds what NAT-PMP lacked: IPv6 support, firewall pinholes as well as NAT mappings, a random nonce so a mapping can't be hijacked by a guesser, and the ability for a carrier-grade NAT to accept requests from its customers. A CGNAT that supports PCP can, in principle, give you a forwarded port through the ISP's layer. Support in the wild is still thin.
| Protocol | Finds the router by | Transport | Notes |
|---|---|---|---|
| UPnP-IGD | SSDP multicast, 239.255.255.250:1900 | HTTP + SOAP (XML) | Widest support; no authentication; IPv4-centric (IGD:2 adds IPv6 pinholes) |
| NAT-PMP | Default gateway only | UDP to port 5351 | RFC 6886; tiny; IPv4 only; reports the external address |
| PCP | Default gateway (or a configured server) | UDP to port 5351 | RFC 6887; IPv4 and IPv6; nonces; usable by CGNATs |
Every one of these protocols talks to one router: the one the device can see. NAT-PMP and PCP go to the default gateway by definition. UPnP's multicast search doesn't cross routers, because multicast to 239.255.255.250 is scoped to the local network. So in a double NAT, the request lands on the inner router and stops there.
If the inner router supports the protocol, it happily creates a mapping: public port 41641 on its WAN address, 192.168.1.45, forwarded to the laptop. It replies with success. NAT-PMP even tells the client its external address, and that's the giveaway: the "external" address is 192.168.1.45, a private address. The mapping is real but sits one layer too deep. Packets from the internet still die at the outer gateway, which never received a request and has no row.
The inner router could, in theory, turn around and ask the outer one for a matching mapping. Nothing in UPnP-IGD or NAT-PMP says it should, and almost no consumer router does. PCP does define a way to chain requests through a stack, a PCP proxy (RFC 7648), but you would need it on the inner box and PCP on the outer one, and that pairing is rare in homes.
What the client sees depends on the details, and none of the outcomes is good. If the inner router doesn't speak the protocol, requests go unanswered. NAT-PMP's retry rule is to wait 250 ms, then resend and wait twice as long, nine attempts in all, which adds up to about 128 seconds before the client concludes there's no NAT-PMP here. Software that wants a mapping badly tends to start over later, so in the logs it looks like a client retrying forever. If the inner router does answer, the client gets a mapping that reports a private external address, which careful software discards and sloppy software advertises to peers who can never use it.
This site exists because of one Windows laptop. Its Wi-Fi address was on 192.168.86.0/24, the default range of a popular mesh Wi-Fi system. Its default gateway, 192.168.86.1, was that mesh router. The mesh router's own WAN address was on 192.168.1.0/24, handed out by the ISP's gateway. Two private networks, two NATs: a textbook double NAT nobody had set up on purpose.
The laptop also ran Tailscale, an overlay VPN that tries hard to connect devices directly, peer to peer, and uses port mapping to help. Its logs showed the double NAT in action. Port-mapping probes kept repeating. And when a NAT-PMP answer did come back, it came from the outer box, the 192.168.1.x gateway. That sounds like progress, but think about which table it wrote to. A mapping on the outer gateway forwards a public port to a device on its LAN, which is the mesh router's WAN address. The mesh router never got a request, has no row, and drops whatever arrives. One layer mapped, the other not: still no way in.
With no reliable inbound path, the overlay did what it is designed to do when direct paths fail: it fell back to a relay. Tailscale's relays are called DERP servers, and the connection to the remote machine showed as going via DERP rather than directly. Remote Desktop still worked, because relays always work. But every screen update now traveled from the laptop out to a relay server, and back again, instead of across the room. The machine also had a dozen network adapters, including a Hyper-V virtual switch, a network bridge and dead VPN adapters, which gave the overlay more candidate paths to try and more ways to pick a bad one; Chapter 12 untangles that part.
The cure for the NAT half is to remove a layer. Put either box into bridge mode, so only one router translates, and the port mapping, inbound reachability and direct connections all have a single table to deal with. Chapter 9 explains how the direct path gets found once the way is clear, and Chapter 13 works through the commands that diagnosed it.
The goal is always the same: exactly one NAT between you and the internet, and it should be one you control.
The DMZ host on a consumer router receives every inbound packet that doesn't match another rule. Point it at a laptop and the laptop is exposed to the whole internet on every port, with only its own firewall in the way. Point it at another router and the inner router is the one exposed, and routers are built for exactly that: their WAN side drops unsolicited traffic unless a forward or mapping says otherwise. The DMZ simply hands the job of deciding to the inner box.
Two details make it reliable. The inner router's WAN address must not change, or the DMZ points at nothing after a reboot, hence the DHCP reservation. And the outer box's own management services, its web interface, for example, should not be exposed on its WAN side, which is the default on nearly all of them.
Type three addresses: your default gateway (from ipconfig or your network settings), the WAN or internet address on your router's status page, and the address a "what is my IP" website reports. The checker classifies each one and reasons its way to how many NATs are in your path. Nothing you type leaves this page.
Example addresses in 192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24 are documentation ranges; the checker treats them as public so the examples work.