Chapter 08 · Part III · NAT

Double NAT, CGNAT & port mapping

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.

4,194,304addresses in 100.64.0.0/10, set aside in 2012 for carriers' own NAT (RFC 6598)
UDP 5351the port NAT-PMP and PCP requests go to, and only ever on your default gateway
~128 show long a NAT-PMP client keeps retrying, doubling the wait each time, before giving up (RFC 6886)

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.

Router, meet router

NAT behind NAT

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.

192.168.86.23 → 192.168.1.45 → 203.0.113.7
The same laptop, as seen by its own LAN, by the outer gateway's LAN, and by the internet. Each arrow is one NAT, and each NAT keeps its own table.
Go deeper: the subnet that must never overlap

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.

NAT at the ISP

Carrier-grade NAT

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.

How to tell

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.

  • If the WAN address is in 100.64.0.0/10, you're behind CGNAT.
  • If the WAN address is private (10.x, 172.16–31.x, 192.168.x), there's another router between yours and the internet: double NAT at home, or a provider using private space for its CGNAT.
  • If the WAN address is public but doesn't match what the website sees, something further out is translating: a CGNAT using public addresses, or a VPN or proxy you forgot was on.
  • If the WAN address is public and matches, you have exactly one NAT, yours, and full control of it.

Instrument 2 below does this reasoning for you.

Go deeper: why 100.64/10, and who else borrows it

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.

The damage report

What double NAT breaks

Nothing that only connects outward. Everything that needs to be reached.

  • Port forwarding. Needs a matching forward on every layer. Behind CGNAT it's impossible, because you can't configure the ISP's NAT.
  • Hosting anything. A game server, a home camera, a Plex server, Remote Desktop from outside: all are inbound connections.
  • Online games and consoles. Consoles grade their connection with labels like Open, Moderate and Strict (the names vary by platform). Double NAT or CGNAT usually pushes them to Strict, which limits who they can join and host.
  • Peer-to-peer and calls. Direct connections between two NATed devices depend on how each NAT behaves (Chapter 9). Two layers mean two chances to get a strict one, and the shortest UDP timeout of the two layers wins. More traffic ends up going through relay servers.
  • Some VPNs. Classic IPsec sends ESP packets, which have no ports for a NAPT to rewrite. NAT traversal for IPsec (RFC 3947 and RFC 3948) wraps ESP in UDP port 4500 to get through. Most modern VPNs, WireGuard included, run over UDP and cross NAT outward fine, but a VPN server at home is an inbound service and inherits every problem above.
  • Automatic port mapping. UPnP, NAT-PMP and PCP all talk to one router: yours. The next section is about why that matters.
Instrument 1

Two layers, two tables

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.

Layers of NAT2
Internet sees you as–
NAT-PMP says your address isnot asked yet
Inbound to :41641not tried

Send a packet out to begin.

Asking politely

UPnP, NAT-PMP and PCP

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.

ProtocolFinds the router byTransportNotes
UPnP-IGDSSDP multicast, 239.255.255.250:1900HTTP + SOAP (XML)Widest support; no authentication; IPv4-centric (IGD:2 adds IPv6 pinholes)
NAT-PMPDefault gateway onlyUDP to port 5351RFC 6886; tiny; IPv4 only; reports the external address
PCPDefault gateway (or a configured server)UDP to port 5351RFC 6887; IPv4 and IPv6; nonces; usable by CGNATs
The heart of the problem

Why the request never reaches the outer box

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.

0.25 + 0.5 + 1 + 2 + 4 + 8 + 16 + 32 + 64 = 127.75 s
NAT-PMP's retransmission schedule from RFC 6886: nine tries, each wait twice the last, before a client decides the gateway doesn't support the protocol.
A real case

The laptop on 192.168.86.x

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.

Getting it down to one

The fixes

The goal is always the same: exactly one NAT between you and the internet, and it should be one you control.

  • Bridge mode on the ISP gateway. Also called modem mode or IP passthrough, depending on the vendor. The gateway stops routing and translating, and hands the public address straight to your router's WAN port. Your router becomes the only NAT, and its port forwarding and UPnP or NAT-PMP now work end to end. This is the cleanest fix, when the ISP allows it.
  • Bridge or access-point mode on your own router. The other way round: keep the ISP gateway as the only router and turn your mesh or Wi-Fi router into a plain access point. You lose its routing features but keep its Wi-Fi. Some mesh systems lose features in this mode, so check first.
  • DMZ on the outer router. If neither box can bridge, give the inner router a fixed WAN address (a DHCP reservation) and set it as the outer gateway's DMZ host. Every unsolicited packet the outer gateway receives goes to the inner router, which applies its own forwards and port mappings. The outer layer is still translating, but it no longer blocks anything, so the stack behaves almost like one NAT.
  • Matching forwards on both. For one or two fixed services, forward the port on the outer gateway to the inner router's WAN address, and on the inner router to the device. It works, but automatic port mapping still won't.
  • IPv6. With IPv6 there is no NAT at home: each device gets a global address, and reaching it is a firewall decision, not a translation problem. If both ends have IPv6, most of this chapter stops applying. Even behind CGNAT, many ISPs now provide native IPv6 alongside.
  • Behind CGNAT, ask. Some ISPs will move you off CGNAT for free on request, some charge for a static public address, and some can't. Overlay networks with relays, such as Tailscale, keep working regardless, at the cost described in Chapter 9.
Go deeper: why DMZ-to-a-router is safe and DMZ-to-a-PC isn't

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.

Instrument 2

Am I behind CGNAT or double NAT?

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.

NAT layers (at least)–
Gateway is–
WAN is–
Port forwarding–

    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.

    Cheat sheet

    Terms from this chapter

    Double NAT
    Two NAT routers in a row, each with its own private network and translation table.
    CGNAT
    Carrier-grade NAT: a large NAT run by an ISP and shared by many customers.
    100.64.0.0/10
    Shared address space (RFC 6598) for the link between a CGNAT and its customers. Also borrowed by Tailscale for tailnet addresses.
    NAT444
    Private IPv4 at home, shared IPv4 at the ISP, public IPv4 beyond: two layers of NAT.
    Port block
    A fixed range of public ports a CGNAT reserves for one customer.
    UPnP-IGD
    Universal Plug and Play's Internet Gateway Device service: lets LAN devices request port forwards via SSDP and SOAP.
    NAT-PMP
    NAT Port Mapping Protocol (RFC 6886): small UDP requests to the default gateway on port 5351.
    PCP
    Port Control Protocol (RFC 6887): NAT-PMP's successor, with IPv6, nonces and CGNAT support.
    Bridge mode
    A router setting that stops it routing and translating, so it passes the public address through.
    DMZ host
    The device a router sends all otherwise-unclaimed inbound traffic to.
    DERP
    Tailscale's relay servers, used when two devices can't connect directly.
    Where this comes from

    Sources