1

I need to script some Iptables rule changes involving NAT rules (-t nat) on Ubuntu 16 servers. It seems like the common way to drop a rule using -D [rule here] does not work with the -t identifier... I really do not want to complicate the scripting by having to identify which rule in my chain I'm looking for and get its associated line number... Any ideas?

In case it helps, the purpose of the below rules is to redirect traffic both localhost and external from 1 server to a backup, during a crash or restart of a local MySQL database (basically).

My Rules:

iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to-destination RMT_IP:3306
iptables -t nat -I OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to-destination RMT_IP:3306

My Attempt to Drop (Works):

iptables -t nat -D POSTROUTING -j MASQUERADE
iptables -t nat -D PREROUTING -p tcp --dport 3306 -j DNAT --to-destination RMT_IP:3306

Can not figure out how to drop this rule without using --line-number:

iptables -t nat -I OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to-destination RMT_IP:3306
3
  • Any advise if this would be better for server fault would be helpful...
    – MadHatter
    Aug 26, 2020 at 17:35
  • Somehow I did not try that? It did not logically make sense that -I was -A (Add)
    – MadHatter
    Aug 27, 2020 at 21:49
  • @roaima You are correct, Please make an answer :)
    – MadHatter
    Aug 27, 2020 at 21:52

2 Answers 2

1

Given any rule with -I (insert) or -A (append), you can repeat the rule definition with -D to delete it.

For your particular example, this will delete the first matching rule in the OUTPUT chain for the nat table

iptables -t nat -D OUTPUT -p tcp -o lo --dport 3306 -j DNAT --to-destination RMT_IP:3306
0

If you need to easily toggle a rule on or off, how about making a separate chain for it?

iptables -t nat -N MySQLnat
iptables -t nat -A MySQLnat -j DNAT --to-destination RMT_IP:3306

Then create your rules in a slightly modified way:

iptables -t nat -A POSTROUTING -j MASQUERADE
iptables -t nat -A PREROUTING -p tcp --dport 3306 -j MySQLnat
iptables -t nat -I OUTPUT -p tcp -o lo --dport 3306 -j MySQLnat

Now you can easily erase the MySQL-specific DNAT rules for MySQL by emptying your custom chain:

iptables -t nat -F MySQLnat

An empty chain is the same as a chain that has just -j RETURN in it, so it does nothing and then continues processing the chain that jumped into the empty chain.

(In your position, I would be wary about deleting the conditionless -j MASQUERADE rule in the POSTROUTING chain, unless I was very sure nothing else depends on it.)

And when you need the MySQL DNAT again, simply put the contents of the chain back in:

iptables -t nat -A MySQLnat -j DNAT --to-destination RMT_IP:3306
1
  • I solved the problem, but this is an interesting solution that for sure could make some of my other scripts easier... Thank you.
    – MadHatter
    Aug 27, 2020 at 21:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.