Frontend Labs
⋯

12. Special-use addresses, private space, and NAT/PAT

12.1 Ranges you must recognize

Range Name Meaning
10.0.0.0/8 Private (RFC 1918) Not routed on the internet
172.16.0.0/12 Private (RFC 1918) 172.16.0.0–172.31.255.255
192.168.0.0/16 Private (RFC 1918) Home/office LANs
100.64.0.0/10 CGNAT (RFC 6598) Carrier-grade NAT shared space
127.0.0.0/8 Loopback 127.0.0.1 = this host; whole /8 is local
169.254.0.0/16 Link-local (APIPA) Self-assigned when DHCP fails; not routed
0.0.0.0/8 "This network" 0.0.0.0 = "any"/unspecified/default route
255.255.255.255 Limited broadcast This subnet only, never forwarded
224.0.0.0/4 Multicast 224.0.0.1 all-hosts, 224.0.0.251 mDNS
240.0.0.0/4 Reserved (experimental) Mostly unusable
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 Documentation (TEST-NET) Safe to use in docs/examples
198.18.0.0/15 Benchmarking Lab/testing only

12.2 Why NAT exists

IPv4 has ~3.7 billion usable addresses; there are ~15 billion connected devices. NAT (Network Address Translation) lets many private hosts share one public address. It also became a de-facto firewall (unsolicited inbound has nowhere to go) — which is both a feature and the reason peer-to-peer is hard (Ch. 46).

12.3 The kind you actually use: PAT / NAPT / "masquerade"

Port Address Translation (one public IP, many hosts) maps the full 4-tuple:

NAT table entry (conntrack):
  inside:  192.168.1.50 : 51000  <->  8.8.8.8 : 53
  outside: 203.0.113.7  : 62000  <->  8.8.8.8 : 53

Outbound: rewrite src 192.168.1.50:51000 -> 203.0.113.7:62000, fix checksums
Inbound:  match dst 203.0.113.7:62000    -> rewrite dst 192.168.1.50:51000

The router allocates a unique outside port per flow, so two inside hosts both using source port 51000 to the same server get different outside ports. State times out (TCP established ~5 days on Linux conntrack default, UDP ~30 s, TCP after FIN ~1 min).

12.4 NAT variants (and why P2P cares — see Ch. 46)

  • Full-cone: once inside:port → outside:port exists, any external host can send to outside:port. Easiest to traverse.
  • Restricted-cone: external host may reply only if the inside host sent to that host's IP first.
  • Port-restricted-cone: … that host's IP and port.
  • Symmetric: a different outside port per destination. Two different servers see two different source ports for the same inside socket. Hardest to traverse; needs TURN relay.
  • Static NAT / port forwarding: fixed outside:port → inside:host:port for hosting a server behind NAT.
  • 1:1 NAT (NAT44) / hairpin NAT: map a whole public IP to a private host; hairpin = inside host reaching the public IP of another inside host.
  • CGNAT (RFC 6598): your ISP NATs you inside 100.64.0.0/10, so you're behind two layers of NAT. Breaks port forwarding entirely; this is why IPv6 or services like Tailscale matter.

12.5 What NAT breaks

  • Embedded addresses: protocols that put IPs inside the payload — FTP active mode, SIP, H.323, PPTP GRE — need an ALG (Application Layer Gateway) on the router to rewrite them, and ALGs are famously buggy.
  • End-to-end IPsec AH (authenticates the IP header → NAT invalidates it); needs NAT-T (UDP/4500 encapsulation).
  • Inbound connections without explicit port forwarding.
  • Address-based logging/geo/abuse — thousands of users behind one IP.
  • Connection count limits — a busy office can exhaust ~64k ports to a single popular destination IP.

12.6 War story

A SaaS provider IP-allowlisted a customer's office "public IP." It worked for a week, then broke randomly. The ISP had moved the customer to CGNAT, so their public IP now changed hourly and was shared with strangers. Allowlisting became impossible; the fix was a site-to-site VPN with a stable tunnel IP. Lesson: never assume a client's source IP is stable or unique — NAT, CGNAT, mobile networks, and proxies all break that assumption.

Try it yourself

curl -s https://api.ipify.org ; echo          # your public (post-NAT) IP
ip route get 8.8.8.8                            # which src IP/interface is used
sudo conntrack -L | head                        # Linux NAT/state table (conntrack-tools)
sudo iptables -t nat -L -n -v                   # NAT rules
# On a Linux router, classic masquerade:
sudo iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.0/24 -j MASQUERADE

Generated from real-life-example.md · 8 Oct 2026 16:36