Module 11 · Internet layer · Lesson 3 of 5
NAT and private networks
How thousands of private machines share a handful of public addresses: network address translation, port mapping and the connection table, why inbound connections fail by default, NAT gateways in the cloud.
Why it matters
Almost every server you deploy sits on a private address and reaches the internet through NAT, and almost every user's phone is behind several layers of it. NAT is why inbound connections to a laptop fail, why a busy service suddenly cannot open outbound connections to a payment provider, why an IP allow-list at a partner needs your NAT gateway's address and not your servers', and why peer-to-peer apps need relays. It is a small mechanism with a large footprint in production incidents.
The idea
Network address translation rewrites addresses in packet headers as they pass through a router. The common form, source NAT with port translation (also called PAT or masquerading), lets many private hosts share one public IP: on the way out, the NAT replaces the private source IP and port with its public IP and a free port, and records the mapping in a connection table; on the way back, it looks up the mapping and rewrites the destination back to the private host.
Kinds of NAT
| Kind | What is rewritten | Used for |
|---|---|---|
| Source NAT with port translation | Source IP and port on the way out | Private servers and home devices reaching the internet through one public IP |
| Destination NAT (port forwarding) | Destination IP and port on the way in | Exposing a private service on a public IP and port; load balancers |
| 1:1 static NAT | One private IP ↔ one public IP | Elastic or public IPs attached to cloud instances |
| Carrier-grade NAT | Source NAT at the ISP, on top of the home router's | Mobile networks and ISPs short of IPv4 addresses; users share public IPs |
Why inbound connections fail
A NAT only knows how to deliver packets that match an existing mapping, created by an outbound connection. An unsolicited inbound connection attempt to the public IP has no entry, so it is dropped. That makes NAT a de facto (though not a real) firewall, and it is why servers need destination NAT, a load balancer or a public IP to accept connections, and why two peers both behind NAT cannot connect directly without hole-punching tricks or a relay, which the network debugging module revisits.
Port exhaustion
One public IP has about 64,000 ports. A NAT uses one per active connection to a given destination, and each mapping lingers for a timeout after the connection closes. A service that opens many short-lived outbound connections to the same endpoint (a payment API, an object store, a third-party webhook) through a single NAT IP can exhaust that range: new connections fail with timeouts or resets while CPU and memory look fine. Cloud NAT gateways document exactly this limit per destination.
- 1
Reuse connections
HTTP keep-alive and connection pools turn thousands of connections into dozens. This is the main fix. - 2
Add public IPs to the NAT
Each extra IP adds another 64,000 ports per destination. - 3
Bypass NAT for cloud services
Private endpoints (VPC endpoints, private service connect) send traffic to the provider's services without passing the NAT at all. - 4
Watch the metric
NAT gateways expose dropped or failed connection counts; alert on them.
Practical consequences
Partners who allow-list your IPs need your NAT gateway's public addresses, which should be static and few. Logs at the destination see the NAT's address, not the original host, so use request IDs or headers to trace. Idle connections through NAT are silently dropped after the mapping times out (often 350 seconds in clouds, shorter on home routers); long-lived connections need keepalives shorter than that. Protocols that put IP addresses in their payload (old FTP, SIP) break through NAT without application-aware helpers.
Trade-offs
NAT stretched IPv4 for decades and hides internal addressing, at the cost of breaking end-to-end connectivity, adding state that can be exhausted or lost, obscuring source addresses and complicating peer-to-peer. IPv6's large address space removes the need for NAT, which is part of its argument, though many networks keep a stateful firewall in the same place for security.
In an interview
Raise it whenever a design has private services calling out: "Workers are in private subnets and reach the payment provider through a NAT gateway with two static IPs, which the provider allow-lists. The client keeps a pooled, keep-alive connection so we use a handful of ports, not one per request, and S3 traffic goes through a VPC endpoint so it never touches the NAT." That covers allow-listing, exhaustion and cost in one breath.
Check yourself
A batch job in a private subnet makes 3,000 new HTTPS connections per second to one third-party API through a single NAT gateway IP. After a minute, new connections start timing out while the job's CPU is idle. What is happening?