Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I have very complicated and long iptables script. It is not possible to operate on the existing iptables configuration, by doing manual inserts/replaces or deletions. I have a script which simply flushes all rules and custom chains, then reloads everything from scratch. This approach works well, to some extent.

I have a lot of sensitive traffic, like E1 lines encapsulated into IP packets and many others. I can't afford to just drop all rules and reinsert them, because this is simply too slow. Lots of stuff breaks if there is no rule for more then 50ms. Aside from that, some high throughput traffic runs in into partially restored firewall, which ends up in very bad conntrack entries, which require manual intervention to restore functionality.

The solution would be to append new rules at the end of current, then to remove the old ones, which can theoretically result in continuous ruleset in place. The problem is, that a script with custom chains, ipset's and such is getting very complicated and error prone.

Question is - do you know any existing solution (extra layer on top of iptables), which handles the problems I mentioned here?

Thanks in Advance.

share|improve this question
    
How frequently are you having to change rules, and which distribution are you running on top of? –  Scott Pack Jan 21 '11 at 1:29
    
Is linux really the right tool for this job? It sounds like you are getting into territory better covered by devices from Cisco and other networking vendors. –  Phil Hollenback Jan 21 '11 at 6:18
    
@packs The distribution doesn't really matter here. I am not using anything specific to any distribution. Set of rules in contained in a lsb-like custom start script. –  mdrozdziel Jan 21 '11 at 10:36
    
@Phil Mentioned Boxes are running BGP/IGP, IPSEC, LVS, policy routing and more layer 3 stuffh. Filtering is very complicated, mostly based on markings. Because several people maintain the environment, we have unified diffs generated between commits. Thus there is 4+ year old history of changes available. Equivalent functionality from Cisco/Juniper would cost us hundred of thousands of bucks in hardware and migration costs. I am sure parts of the stuff wouldn't be even possible to recreate with networking vendor hardware. –  mdrozdziel Jan 21 '11 at 10:42
    
@acidburn2k The distro can matter, since certain aspects of the firewall are managed differently across distros. RHEL and similar using /etc/sysconfig/iptales, Ubuntu using preups, etc. –  Scott Pack Jan 21 '11 at 12:34

5 Answers 5

Have you tried loading your new rules with the iptables-restore command? This is in theory an atomic operation, which may take care of most of your issues. This does require that you write your rules in the format used by iptables-save.

share|improve this answer
    
Well, I never thought that iptables-save and ipset -S are any different than just simple flush and rebuild of ruleset. I will look into this, thanks for the tip. –  mdrozdziel Jan 21 '11 at 10:53

This should be pretty easy if you use chains.

Create a chain or two and add all your rules to that. All you should have to do is flush, delete, and recreate the chain(s) when you need to reapply your rules.

So during an update, you insert a rule at the top that permits established connections, (maybe you want this to be a rule by itself always enabled and never touched), flush the chain, then adds the new rules to the chain. This assumes you are using stateful rules wherever possible.

share|improve this answer
    
+1 - I like this. With a box doing as much critical filtering you really should give a lot of thought to the architecture of your iptables rule set, designing for performance, correct function (obviously), and maintainability (often overlooked). –  Evan Anderson Jan 21 '11 at 5:17
    
Well, it even makes sense to create a new chain and replace the main hook point (iptables -R). This however won't work with ipset, since you can't remove ipset until it is referenced by iptables rule. In the end it pretty much comes down to the original idea - Append the rules at the end, then remove the old rules one-by-one. This can work in theory, but requires a major overhaul in our approach. Perhaps we should gave up on stuph like many custom chains or ipsets, to reduce complexity. Before that decision I would like to know if someone can suggest something less invasive. –  mdrozdziel Jan 21 '11 at 10:44

I don't think there is a solution for an extreme case like yours. However, the good news is that it would be pretty easy to write Python script that would replace insert the rule you want above the old one and then delete the old one.

orchidea 10.0.0.1 /etc/exim % iptables -L -n --line-numbers
Chain RH-Firewall-1-INPUT (2 references)
num  target     prot opt source               destination
1    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
2    ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0
3    ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           icmp type 255
4    ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:53

Just parse output above for chain and rule number, say 4, do iptables -I chain 4 newrule, and then iptables -D chain 5.

share|improve this answer
    
I don't find this case any extreme. Parsing "-L" output for entries isn't a trivial task. Aside from that, there there is no need to overcomplicate things like this. First of all there is "-R" for replace available. Second, it would be trivial just to add all rules at the end, then remove old rules from start. Unfortunetely this wont work due to problems referenced in other answers / comments. –  mdrozdziel Jan 24 '11 at 4:39

I suggest to adapt the script so that it uses one of two names for the same chain (makes sense to use a prefix), depending on how it is called. So instead of a chain dropthis there would be set0_dropthis or set1_dropthis.

That way you could create the new set of rules without disturbing the traffic. After that the default chains would be flushed and recreated with the new set as target. Optimal would be to have just a single rule in each default chain which would just direct the traffic to the old or to the new set. Replacing this single rule would be fast (and even safe with iptables -A; iptables -D ... 1). After that the old set's chains would be flushed and deleted.

A wrapper script would detect which set is currently active and call the real script with the respective parameter.

share|improve this answer

The only way for this to be feasible is to either rework your existing script to use the iptables-restore format or, modify your existing script to dump commands to stdout instead of executing them and then produce a second script to convert it to iptables-restore format.

iptables-restore is guaranteed to be atomic and is thus the only reliable way to do seamless rule replacement.

my suggestion to you in terms of getting the iptables-restore format would be to run your script against a VM or in a separate network namespace on the live machine and then use iptables-save to grab it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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