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.
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 byiptables-save
.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.
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.
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.
Just parse output above for chain and rule number, say 4, do iptables -I chain 4 newrule, and then iptables -D chain 5.
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.