What is the difference between MASQUERADE and SNAT, and when do you use each?
Show the answer
Say this first
Both rewrite the source address in nat POSTROUTING. SNAT uses the fixed address you give it with
--to-source. MASQUERADE looks up the outgoing interface's address for each new connection, so it suits
DHCP or PPPoE links whose address changes, and it drops the interface's connections when the interface
goes down. With a static public address, SNAT is the cleaner choice; it does the same work without the
lookup.
Go deeper
The two rules
iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o ens192 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 10.20.0.0/24 -o ens192 -j SNAT --to-source 198.51.100.10The nftables equivalents in an ip family nat table:
oifname "ens192" ip saddr 10.20.0.0/24 masquerade
oifname "ens192" ip saddr 10.20.0.0/24 snat to 198.51.100.10How the translation works
- Only the first packet of a connection goes through the nat table. The mapping is stored in conntrack and applied to every later packet in both directions.
- Linux keeps the original source port if it is free on the public address, and picks another if not.
--random-fullyrandomises port choice, which helps when many clients behind one IP hit the same server. -s 10.20.0.0/24 -o ens192keeps the rule from translating traffic that should stay internal, like traffic between two inside interfaces or to a VPN.
Seeing it
$ sudo conntrack -L -p tcp --dport 443
tcp 6 431998 ESTABLISHED src=10.20.0.15 dst=203.0.113.80 sport=40112 dport=443 src=203.0.113.80 dst=198.51.100.10 sport=443 dport=40112 [ASSURED] mark=0 use=1The reply tuple is addressed to 198.51.100.10: the NAT is visible there.
They will ask next
You change the NAT rule but some flows still use the old address. Why?
Existing conntrack entries keep their translation until they expire. Long-lived UDP flows (SIP, IPsec, DNS forwarders) are the classic case. Delete them with
conntrack -Dmatching the flow, or flush withconntrack -Fin a maintenance window.Do you need MASQUERADE for a container host?
Yes, unless the network routes the container subnet back to the host. Docker installs
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADEfor its default bridge.
Traps
- Writing MASQUERADE without
-oor-sand translating traffic that should stay internal. - Thinking the nat table is checked for every packet. Only the first one; conntrack does the rest.