IPTables gotcha

Device name with negation

IPTables will happily create a rule for an interface with a name that starts with an exclamation mark like !docker0. But if you want to match traffic on any interface except docker0, then you must put the exclamation mark before the option and not before the name. So ! -o docker0 instead of -o !docker0.

This is documented in the manual but it's an easy mistake to make and it cost me a bunch of time today!

Wrong:

iptables -t nat -A POSTROUTING -o !docker0 -j MASQUERADE

Right:

iptables -t nat -A POSTROUTING ! -o docker0 -j MASQUERADE

Note both these rules will appear exactly the same when listing the rules:

$ iptables -t nat -A POSTROUTING -o \!docker0 -j MASQUERADE
$ iptables -t nat -A POSTROUTING \! -o docker0 -j MASQUERADE
$ iptables -vt nat -L POSTROUTING
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 MASQUERADE  all  --  any    !docker0  anywhere             anywhere
    0     0 MASQUERADE  all  --  any    !docker0  anywhere             anywhere