# NAT and PAT

Network Address Translation rewrote the internet's addressing model as a workaround for IPv4 exhaustion. It is everywhere, it is invisible when it works, and it breaks a specific set of protocols that expect end-to-end addressing.

## The three flavours

| Type | What changes | Typical use |
|---|---|---|
| **Static NAT** (1:1) | One private IP ↔ one public IP | Publishing an internal server |
| **Dynamic NAT** (pool) | Private IP ↔ any free public IP from a pool | Legacy outbound with a block of addresses |
| **PAT / NAT overload** (many:1) | Private IP:port ↔ public IP:unique port | Every home router and most corporate egress |

PAT is what almost everyone means by "NAT": thousands of internal hosts share one public address, distinguished by source port.

```text
Client 192.168.1.20:51234  →  203.0.113.5:41200  →  Server 198.51.100.10:443
```

The router keeps a translation table mapping the tuple back for the return packet. That table is state, so NAT is a stateful middlebox and inherits every stateful-middlebox problem.

## Why it exists, and what it costs

IPv4 has ~4.3 billion addresses. NAT let the world postpone renumbering for thirty years. The bill:

- **No inbound connections** without a forwarding rule or a tunnel.
- **No end-to-end addressing**, which breaks protocols that embed IPs or ports inside payloads.
- **State exhaustion** — every translation holds a table entry and a port.
- **Ambiguity in logs** — the server sees the NAT address, not the client, unless something forwards the original.

## Protocols that break, and why

| Protocol | Problem | Workaround |
|---|---|---|
| **FTP (active)** | Server connects back to a port the client did not open | Passive mode, or an ALG |
| **SIP / H.264** | Addresses embedded in the payload | ALG, STUN, TURN, ICE |
| **IPsec ESP** | No ports to translate | NAT-T (UDP 4500 encapsulation) |
| **ICMP** | No ports; identifier is translated instead | Handled by most NATs, not all |
| **DNS** | A records pointing at private IPs leak out | Split-horizon DNS, not NAT |
| **Peer-to-peer / WebRTC** | Direct connection impossible | STUN/TURN relay |

ALGs (application layer gateways) try to fix this by rewriting payloads. They are the reason "NAT works except for that one application", and they are frequently the bug rather than the fix.

## The table, and what exhaustion looks like

```bash
conntrack -L | wc -l
conntrack -S                       # insert_failed, drop counters
sysctl net.netfilter.nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count
```

Symptoms of a full table: new connections fail while established ones work, `insert_failed` climbs, and the failure looks random by client. Common in offices where everyone opens a video call at 9am.

Fixes in order: raise the limit (buys time), reduce connection churn (pooling, keep-alive), add more public IPs (more tuples), or move to IPv6.

## Hairpinning and the internal-then-external problem

A client inside the network resolves `api.example.com` to the public IP and tries to connect. The packet goes to the router, which must translate it back inside — **NAT hairpin / loopback**. Many routers do not support it by default, so internal clients cannot reach an internal service via its public name while external clients can. The usual fixes:

1. Split-horizon DNS returning the private address internally.
2. Explicit hairpin/NAT-loopback configuration.
3. Route internal clients to the internal load balancer directly.

This is one of the most common "it works from home but not from the office" causes, and it is a DNS problem wearing a NAT costume.

## IPv6 and the end of NAT (mostly)

IPv6 restores end-to-end addressing, so NAT is not required. What remains is a **stateful firewall** with the same job as NAT's side effect, and NAT66 exists for multihoming but is discouraged. The practical translation of skills: what you learned as "port forwarding" becomes "firewall policy", and what you learned as "no inbound" becomes "default deny inbound, which you configured deliberately".

## Where it goes wrong

- **Port forward to the wrong internal IP** after a DHCP lease changed. The fix is a static reservation, not a new rule.
- **Overlapping private ranges** across a VPN: both sides use `192.168.1.0/24`, so half the destinations are ambiguous. Renumber one side; there is no clean NAT fix.
- **Assuming the server logs the client IP.** Behind NAT it does not; you need `X-Forwarded-For` set by a proxy you trust, or PROXY protocol.
- **Hairpin missing**, as above.
- **ALG disabled** to fix one application and enabled to fix another, on the same gateway.
- **Conntrack full** during a traffic spike, misdiagnosed as an application bug.
- **NAT on the firewall and NAT on the router**, each translating, producing a double-NAT that is invisible in the config of either device alone.

## Teaching hook

**The office receptionist analogy.** Everyone inside has an extension; the outside world only knows the main number. The receptionist keeps a note of who is on which call, and can only pass a call inward if you told them in advance (a port forward). When two people are on hold, the note gets long — that is the conntrack table.

Demo: run a server on a laptop, `curl` it from another host on the LAN (works), then from outside (fails), then add a port forward (works). Then move the laptop to a different DHCP lease and watch the forward break.

## Related Notes

- [[Foundations/Addressing-Subnetting-CIDR.md]] — private ranges and overlap risk
- [[Network-Services/Firewalls-And-ACLs.md]] — the policy layer NAT is often confused with
- [[Network-Services/Load-Balancing.md]] — the modern alternative to port forwarding
- [[Security/VPNs-And-Tunnels.md]] — where overlapping ranges hurt most
