2026-11-02·by Sijie Wang#fundamentals#networking#nat

how-nat-works

How NAT works: a rewrite ledger on the gateway

NAT exists because IPv4 addresses ran out: a whole household or office of private addresses (192.168.x.x) must share one public address. The mechanism is a dynamic rewrite ledger kept by the gateway. When an inside device sends a packet out — say 192.168.0.21, port 51234, headed for some server — the gateway rewrites the source to its own public address and a port it picks (99.236.1.10, port 62001) and writes one ledger row: public 62001 ↔ 192.168.0.21:51234, for this destination. Replies arriving at 62001 are looked up in the ledger, rewritten back, and delivered inside. It works exactly like a mail room with extension numbers: outsiders see one street address; the room knows which extension each parcel belongs to.

A side effect falls out for free: a packet arriving from outside with no ledger row is dropped. Unsolicited inbound traffic has nowhere to go — NAT gateways are accidental firewalls.

Ports are a pooled resource. The gateway allocates and releases them like connections from a pool, per public IP and per protocol. Allocation strategy matters: sequential ports are guessable, so random allocation is preferred; port preservation (keep the inside port if free) helps some protocols. Under carrier-grade NAT, one public address is shared by many subscribers, so ports are handed out in per-subscriber blocks. Ledger rows expire after inactivity, which is why long-lived UDP flows send keepalives (WireGuard's is 25 seconds) — the sender is not checking on the peer, it is keeping its own ledger row alive.

The four types are two independent behaviours. Mapping behaviour: when the same inside socket talks to a different destination, does it reuse the same public port (endpoint-independent — the friendly case, historically "full cone"), or get a fresh port per destination address, or per address-and-port pair? Filtering behaviour: once a row exists, who may use it to come back in — anyone, only addresses the insider sent to, or only the exact address-and-port? The hostile corner is symmetric NAT: a fresh public port for every destination, plus strict filtering.

Why symmetric NAT breaks hole punching. Peer-to-peer traversal (STUN) works by each side learning its own public address-and-port and telling the other where to send. Under symmetric NAT, the port a peer learns via STUN was allocated for the STUN server — the port allocated for the actual peer is a different one. The address you advertise is not the address that works, so direct connection fails and traffic must fall back to a relay. This is why mesh VPNs ship relays at all (Tailscale's DERP is one): not as the design, but as the fallback for the NAT type that defeats traversal.

Port forwarding is the manual exception: a permanent, hand-written ledger row — public port X always maps to this inside device — for when a service inside must be reachable from outside without having spoken first.

about this entry

One of sijie's wiki entries. The AI on this site is grounded in the same corpus and answers in sijie's voice, with citations back to entries like this one — answering costs sijie money, so it waits behind a code: enter an access code →