Octet

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

Shell
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.10

The nftables equivalents in an ip family nat table:

Output
oifname "ens192" ip saddr 10.20.0.0/24 masquerade
oifname "ens192" ip saddr 10.20.0.0/24 snat to 198.51.100.10

How 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-fully randomises port choice, which helps when many clients behind one IP hit the same server.
  • -s 10.20.0.0/24 -o ens192 keeps the rule from translating traffic that should stay internal, like traffic between two inside interfaces or to a VPN.

Seeing it

Output
$ 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=1

The reply tuple is addressed to 198.51.100.10: the NAT is visible there.

Traps

  • Writing MASQUERADE without -o or -s and translating traffic that should stay internal.
  • Thinking the nat table is checked for every packet. Only the first one; conntrack does the rest.
How did you do?