Why NAT exists
The main reason NAT exists is IPv4 address exhaustion. Private ranges (10.x, 172.16-31.x, 192.168.x) are not routed on the internet (see ipv4-addressing). To get a host on a private network onto the internet, you need NAT at the network boundary (the router).
Types
-
SNAT (source NAT) rewrites the src address of an outgoing packet. Applied at the outbound boundary; most often as MASQUERADE, which dynamically picks the IP of the outgoing interface.
-
DNAT (destination NAT) rewrites the dst address/port of an incoming packet. Also called "port forwarding":
public_IP:80 -> 10.0.0.5:8080. Used to expose internal services to the outside world. -
PAT/NAT44/NAPT is the same as masquerade but also rewrites the src port, letting one public IP hide many internal hosts. This is what a home router does by default.
-
Hairpin NAT is when a client inside the private network connects to its own public IP. The packet arrives at the router, must pass through NAT, and return into the LAN. Not all routers support this.
How it works
When a connection is established through NAT:
Client 10.0.0.10:54321 --> Router (NAT) --> Server 1.2.3.4:443
|
| rewrites src to 203.0.113.5:54321
| records in conntrack table:
| 10.0.0.10:54321 <-> 203.0.113.5:54321
|
v
Server sees connection from 203.0.113.5:54321
When the server replies, the router finds the conntrack entry and rewrites the addresses back.
The conntrack table (/proc/net/nf_conntrack) holds the state of every
passing connection. Its size is capped by nf_conntrack_max. Overflow is
rare but painful on high-traffic routers.
Where to configure it
On a modern Linux system, use [[#cmd-nft|nftables]]:
sudo nft add table inet nat
sudo nft 'add chain inet nat postrouting { type nat hook postrouting priority 100; }'sudo nft add rule inet nat postrouting ip saddr 10.0.0.0/24 oifname "eth1" masquerade
postroutingis the last stage before a packet is sent outoifname "eth1"selects which interface the rule applies tomasqueradereplaces src with the IP of eth1
The older iptables syntax still works on many systems:
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth1 -j MASQUERADE
You also need net.ipv4.ip_forward=1 for the router to forward packets at all.
NAT problems
- Broken peer-to-peer: two hosts behind separate NATs cannot open a direct connection to each other. Workarounds: STUN, TURN, port forwarding, hole-punching.
- Asymmetric routing: a packet leaves through one NAT device and the reply arrives through another; conntrack has no record of the flow and drops it.
- Conntrack overflow: traffic grows faster than
nf_conntrack_maxallows; packets are dropped. - IPv6 and NAT: an antipattern. In IPv6 every device has a public IP, so NAT is not needed.