NAT (Network Address Translation)
There are only about 4.3 billion IPv4 addresses, and the internet has far more devices than that. NAT is the workaround that let IPv4 survive: a whole network of private hosts shares a small number of public addresses - often just one.
Why NAT exists
Most devices sit behind a router using private addresses from the RFC 1918 ranges, which are never routable on the public internet:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
These ranges are reused in every home and office, so they cannot appear as a source address on the public internet. NAT translates them to a real public address on the way out, and back again on the way in.
How the translation works
When a private host sends a packet toward the internet, the NAT router:
- Rewrites the packet's source IP from the private address to its own public address.
- Rewrites the source port to a port it allocates.
- Records the mapping in a translation table so replies can be reversed.
When a reply comes back addressed to publicIP:allocatedPort, the router looks up
the table, rewrites the destination back to the original private host and port,
and forwards it inward. A reply that matches no table entry is simply dropped -
which is why NAT also acts as a crude firewall.
PAT - one public IP for many hosts
Rewriting the port (not just the IP) is called PAT (Port Address Translation), and it is what lets many hosts share a single public IP. Even if two private hosts happen to use the same source port, NAT hands each a distinct public port, so their flows never collide in the table.
Step through an outbound packet and its reply below. Watch the source get rewritten as it crosses the NAT box, a row appear in the translation table, and the reply map back to the correct private host:
| Private IP:port | Public IP:port | Destination |
|---|---|---|
| empty - step through to add mappings | ||
Both hosts in the demo use private port 6000. The NAT router gives them different
public ports (40000, 40001), so when replies arrive it can tell them apart and
route each back to the right machine. That disambiguation is the whole point of PAT.
Because inbound packets with no existing mapping are dropped, an outside host cannot freely initiate a connection to a host behind NAT. This is why services like peer-to-peer apps and inbound servers need port forwarding, hole punching, or (better) IPv6, which has enough addresses that NAT is unnecessary.
Worked example: a PAT translation table with three connections
A small office shares one public IP, 203.0.113.5, behind its NAT router. Three
connections are open at once, from two internal hosts:
| Internal address:port | Public address:port | Destination | Protocol |
|---|---|---|---|
| 192.168.1.10:51000 | 203.0.113.5:40000 | 93.184.216.34:443 | TCP |
| 192.168.1.11:51000 | 203.0.113.5:40001 | 93.184.216.34:443 | TCP |
| 192.168.1.10:51500 | 203.0.113.5:40002 | 172.217.0.4:443 | TCP |
Notice row 1 and row 2 use the same internal source port (51000) on two
different hosts, and rows 1 and 3 use the same internal host for two different
destinations. Neither collides, because the router keys the table on the full
4-tuple and hands out a fresh public port (40000, 40001, 40002) per
connection. A reply arriving at 203.0.113.5:40002 unambiguously maps back to
192.168.1.10:51500, so the router knows both which internal host to forward to
and which of that host's own connections the packet belongs to.
Many ISPs run carrier-grade NAT (CGNAT) on top of the subscriber's own home router, so traffic crosses two NAT layers: home router (private -> ISP-assigned address) then ISP CGNAT (ISP-assigned address -> real public IP). Port forwarding configured on the home router only opens a hole in the first layer - the ISP's CGNAT layer still has no mapping for unsolicited inbound traffic, so it drops it anyway. This shows up as consoles reporting "NAT Type: Strict" or "double NAT detected," voice chat and peer-to-peer game lobbies failing to connect even though port forwarding "looks right," and VoIP or video calls that connect but carry no audio because the media stream (separate from call setup) can't punch through the second layer. The only real fixes are getting a real public IP from the ISP, using IPv6 (no NAT needed), or relying on a relay/TURN server that both sides can reach outbound.