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

I have a set of scripts I designed for network monitoring, control and so on. One thing I do in these scripts is create an iptables chain like iptables -N mychain. I then insert rules into the main tables as appropriate to get packets to my custom chain for whatever purpose I want them to have there.

My question is: I have a script that does a "Refresh" - in other words, it removes all rules and starts over. It is useful in case of any odd anomalies that crop up. People often still manually manage iptables even if there's something managing part of it. (This is why I wanted all of my work to be done in a separate table.)

If I want to clear my chain, that's easy: iptables -F mychain. But what I don't know how to do is to remove any rule that I may have created that references that chain back in the built-in chains (INPUT, OUTPUT, etc.)

Let's assume there was a bug in my app, or a user was fiddling and ended up messing with the tables, and it somehow added the rule to the INPUT chain twice. Now packets will go through the chain twice - being counted twice, being routed twice, whatever.

The obvious solution to this is to go through the main chains and remove any rule whose jump target is my custom chain. But I don't know how to do this.

Here's an example of a worst-case situation we could setup:

iptables -N TEST
iptables -A INPUT -j TEST
iptables -I INPUT 1 -p tcp --dport 1234 -j TEST
iptables -I INPUT 1 -p tcp --dport 1234 -j TEST # again, for doubling error
iptables -I INPUT -p icmp -j TEST

Let's assume that an unscrupulous or uninformed admin created the three bottommost rules.

So now, I could issue iptables -D INPUT -j TEST and the rule I created would go away. However, those other rules would not be deleted since the parameters when using -D have to match. So even if I remove my own rule diligently, the packets could still end up there more than once for different reasons.

Flushing the main chains isn't necessarily appropriate. Again, using iptables at the command line is common (I do it myself all the time) so just blindly clearing every rule could clear out something someone added for a good reason, even if it's a temporary rule.

The obvious solution is to somehow remove any rule whose destination is the TEST chain and remove those rules. However I haven't seen any commands in the iptables man page that could accomplish this.

The closest thing I could see that may be of any user is iptables -S. I could use iptables -S and create a parser to interpret the output, but this is a bit of extra work. I was just wondering if there's a more correct way to delete rules in some sort of wildcard way. Again, remove any rule whose jump target is whichever chain I want.

A similar situation can occur if I have a chain that I want to get rid of, but it has a reference somewhere else. I would want to be able to figure out where that reference is, and most likely, delete it also.

Is this possible? Or am I going to end up having to write a parser to interpret the iptables -S output?

share|improve this question

2 Answers 2

This should be fairly simple. Use iptables-save to write the current rule-set out to a file or stdout, remove anything with -j YOURCHAIN and load the result back with iptables-restore

This is tempting to do as a pipe

iptables-save | grep -v -- '-j YOURCHAIN' | iptables-restore

However, I'm not sure if running save and restore concurrently would work well. It would be safer to separate the save from the restore. There will be a small critical region where an intervening update to the ruleset would be lost.

share|improve this answer
1  
Oooh interesting - just checked on a test system and it does work as a pipeline. –  Iain May 9 at 11:01
    
Elegant, and useful to know! +1 from me. –  MadHatter May 9 at 14:54

I don't think there is a trivial way to solve this other than perhaps reloading the whole configuration.

You should perhaps give some thought to adding a drop Policy to your chain that way at least if you are diligent it will cause issues for the less so and perhaps provoke some discussion.

From a technical standpoint if you're going to have to parse the output of various commands, you may find --line-num helpful but remember to delete in reverse order (high to low) so that the index doesn't change every time.

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.