3

Say there are several iptables scripts (run at boot time), all of which run something like iptables -A ... to add rules. I'm thinking this could be improved, turning all those shell scripts into text files generated by iptables-save.

But I must be doing something wrong, trying to read all those rulesets. The script run at boot time would loop through those files and read them using iptables-restore. Of course with -n or --noflush. This works for some rules (stored in the default chains) but not for most of my rules which are in other chains. Below is an example of 2 rulesets that flush each other (reading set a, check; reading set b, check but set a is gone).

How would you read a bunch of iptables rulesets?

Example:

$ cat fake1-a.rules 
*nat
:PREROUTING ACCEPT [7:997]
:INPUT ACCEPT [7:997]
:OUTPUT ACCEPT [28:1810]
:POSTROUTING ACCEPT [28:1810]
COMMIT
*mangle
:PREROUTING ACCEPT [344:84621]
:INPUT ACCEPT [344:84621]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [296:37971]
:POSTROUTING ACCEPT [296:37971]
COMMIT
*filter
:INPUT ACCEPT [102:26513]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [89:10767]
:TESTCHAIN - [0:0]
-A TESTCHAIN -p tcp -m tcp --dport 12345 -j DROP
COMMIT
$ cat fake1-b.rules 
*nat
:PREROUTING ACCEPT [7:997]
:INPUT ACCEPT [7:997]
:OUTPUT ACCEPT [28:1810]
:POSTROUTING ACCEPT [28:1810]
COMMIT
*mangle
:PREROUTING ACCEPT [344:84621]
:INPUT ACCEPT [344:84621]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [296:37971]
:POSTROUTING ACCEPT [296:37971]
COMMIT
*filter
:INPUT ACCEPT [102:26513]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [89:10767]
:TESTCHAIN - [0:0]
-A TESTCHAIN -p tcp -m tcp --dport 54321 -j DROP
COMMIT
# cat fake1-a.rules | iptables-restore --noflush
# iptables -nL | grep DROP
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:12345
# cat fake1-b.rules | iptables-restore --noflush
# iptables -nL | grep DROP
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:54321
roaima
  • 107,089
  • 14
  • 139
  • 261
basic6
  • 6,105
  • 4
  • 24
  • 29
  • I would do it in a single file ... in fact that is what I am doing, but of course your use case is different. Does this yield any different outcome if you chain the files and leave out the `COMMIT` from them and then add the commit to the end yourself? E.g. in a subshell `(cat file1 file2 file2; echo "COMMIT")|iptables-restore -n` ... also not sure you need to declare the chain creation stanzas once again, perhaps the CHAIN gets re-created? – 0xC0000022L Jun 05 '14 at 17:09
  • @0xC0000022L `iptables-restore: line 43 failed` (that's the last `COMMIT`). Without the echo, only the last ruleset is applied. – basic6 Jun 06 '14 at 07:42

1 Answers1

3

The --noflush option for iptables-restore doesn't work for user-defined chains, such as TESTCHAIN, only builtin chains. Your best bet is to consolidate all of the TESTCHAIN rules into a single file and import that ruleset using iptables-restore. You could find all the rules with something along the lines of:

egrep -r  "\sTESTCHAIN\s" firewall_rules_directory/*
Creek
  • 5,002
  • 1
  • 22
  • 33
  • Oh, interesting fact. Thanks. This is not even mentioned in the `man` page. – 0xC0000022L Jun 06 '14 at 11:14
  • @0xC0000022L yea, it's funny what they don't tell you – Creek Jun 06 '14 at 11:17
  • So --noflush is basically broken, thanks for the confirmation. The regex would have to be more complex though, because it makes a difference what table the rules live in. – basic6 Jun 06 '14 at 11:55
  • 1
    Just as an update to this, I'm using iptables v1.4.21 and the "iptables-restore -n" functionality now works correctly, including user-defined chains. – Jak Sep 18 '14 at 11:38