4 billion addresses was not enough
IPv4 has 2³² = 4,294,967,296 addresses. Subtract the reserved ranges from Lesson 4-2 and roughly 3.7 billion are usable. There are more than 5 billion internet users and tens of billions of connected devices, so the arithmetic never worked. The central pool ran dry in 2011.
Two responses happened. The long term fix is IPv6, which Lesson 8-4 covers. The immediate fix, deployed everywhere, is NAT (network address translation): let many devices share one public address by rewriting addresses in the packet as it crosses the boundary.
Your home network is the canonical example. Every device holds an RFC 1918 private address, and the router holds one public address from the ISP.
laptop 192.168.1.42 private phone 192.168.1.87 private TV 192.168.1.120 private router 192.168.1.1 private inside router 203.0.113.77 public outside, the only address the internet sees
Private addresses are not routable on the internet, so a packet with source 192.168.1.42 that reached a public router would be dropped, and a reply could never find its way back. The router has to rewrite the source address to its own public one on the way out, and rewrite it back on the way in. Doing that correctly requires remembering every conversation, which is why NAT is stateful and why it changes the character of the internet.
Source NAT, and why ports are involved
Source NAT rewrites the source address of outgoing packets. In its simplest form, one private address maps to one public address, which is called one to one or static NAT. That solves routability but saves no addresses at all.
The version that saves addresses is PAT (port address translation), also called NAPT or, in Linux, masquerading. It rewrites the source address and the source port, so a single public address can serve thousands of conversations at once. The port becomes the thing that distinguishes them.
Recall from Lesson 2-2 that a TCP or UDP connection is identified by four values, called the four tuple:
(source IP, source port, destination IP, destination port)
The router picks an unused source port on its public address for each outgoing conversation and records the mapping. Since port numbers are 16 bit, one public address offers about 64,000 usable ports per destination, which is plenty for a household and the reason PAT works so well.
| Term | Meaning |
|---|---|
| Inside local | the private address and port on your device |
| Inside global | the public address and port the router substituted |
| Outside global | the server's address and port, unchanged |
| Translation entry | one row tying those together, with a timer |
Following one packet through, both ways
Your laptop opens a connection to a web server. Watch each field change.
Outbound, as it leaves the laptop:
src 192.168.1.42:51514 -> dst 93.184.216.34:443
Outbound, after the router rewrites it:
src 203.0.113.77:40001 -> dst 93.184.216.34:443
The router writes the row into its translation table and starts a timer. The server has no idea a private network exists, and replies to what it saw.
Inbound, as the reply arrives at the router:
src 93.184.216.34:443 -> dst 203.0.113.77:40001
Inbound, after the router looks up port 40001 and rewrites it:
src 93.184.216.34:443 -> dst 192.168.1.42:51514
The laptop receives a packet addressed exactly the way it expected. Three mechanical details make this actually work:
1. Checksums are recomputed. The IP header checksum covers the addresses, and the TCP and UDP checksums cover a pseudo header that includes the addresses too, so both must be recalculated after every rewrite. 2. Entries expire. A TCP entry may live for hours while established and is removed shortly after the connection closes. A UDP entry has no close, so it is dropped after 30 to 120 seconds of silence. This timer is precisely why an idle SSH session dies behind NAT, and why applications send keepalives. 3. The table is finite. Every conversation is a row, and a device opening tens of thousands of connections can exhaust the table, at which point new connections simply fail.
You can watch the table on a Linux router:
sudo conntrack -L
tcp 6 431990 ESTABLISHED src=192.168.1.42 dst=93.184.216.34 sport=51514 dport=443 src=93.184.216.34 dst=203.0.113.77 sport=443 dport=40001 mark=0 use=1
One row, both directions, and the 431990 is the remaining lifetime in seconds.