Dynamically remove iptables policy by IP address

Scott Forsyth – MVP asked:

I would like to remove some NAT POSTROUTING rules in an automated fashion based on the source or destination IP address.

I know the source and destination IP but I don’t necessarily know which policies are already there.

For example, I may have this:

-A POSTROUTING -s -p tcp -m tcp --dport 80 -j SNAT --to-source
-A POSTROUTING -s -p tcp -m tcp --dport 443 -j SNAT --to-source

or I may just have this:

-A POSTROUTING -s -j SNAT --to-source

I want to unassign that NAT address from the old computer and assign it to a new computer. This is all automated so I can’t manually look for it.

What’s the best way to remove the old polices for just that IP? Could I use a list + grep command? I normally hang out in the Windows world so I’m not sure the best way to handle this here.

My answer:

You can match a rule for deletion by specifying it precisely and using -D (--delete) instead of -A. For instance:

iptables -t nat -D POSTROUTING -s -p tcp -m tcp --dport 80 -j SNAT --to-source

To script this, matching a specific IP address, and not losing any rules due to race conditions, let’s try something like this. This will delete any rule in the nat table containing a given IP address:

for rule in `iptables-save -t nat | grep -w $IP_ADDRESS | sed -e 's/-A/-D/'`; do
    echo $rule | xargs iptables -t nat

Some notes on this: We use grep -w to ensure that IP addresses match exactly, and e.g. a given address that ends in 25 doesn’t match 250. The transform from -A to -D is done by sed in the loop. And we use xargs to expand each rule into parameters.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.