Delete a iptables chain with its all rules

I have a chain appended with many rules like:

> :i_XXXXX_i - [0:0]
> -A INPUT -s 282.202.203.83/32 -j i_XXXXX_i 
> -A INPUT -s 222.202.62.253/32 -j i_XXXXX_i 
> -A INPUT -s 222.202.60.62/32 -j i_XXXXX_i 
> -A INPUT -s 224.93.27.235/32 -j i_XXXXX_i 
> -A OUTPUT -d 282.202.203.83/32 -j i_XXXXX_i 
> -A OUTPUT -d 222.202.62.253/32 -j i_XXXXX_i 
> -A OUTPUT -d 222.202.60.62/32 -j i_XXXXX_i 
> -A OUTPUT -d 224.93.27.235/32 -j i_XXXXX_i

when I try to delete this chain with:

iptables -X XXXX

but got error like (tried iptables -F XXXXX before):

iptables: Too many links.

Is there a easy way to delete the chain by once command?


You can't delete chains when rules with '-j CHAINTODELETE' are referencing them. Figure out what is referencing your chain (the link), and remove that. Also, flush then kill.

-F, --flush [chain]

Flush the selected chain (all the chains in the table if none is given). This is equivalent to deleting all the rules one by one.

-X, --delete-chain [chain]

Delete the optional user-defined chain specified. There must be no references to the chain. If there are, you must delete or replace the referring rules before the chain can be deleted. The chain must be empty, i.e. not contain any rules. If no argument is given, it will attempt to delete every non-builtin chain in the table.


This is potentially off-topic, but it's what I did after I found this post! For some use cases the iptables -D option might be useful. Since it allows you to clear out referring rules added programmatically with -A (if you know precisely how you added them).

E.g

    iptables -N MYCHAIN
    iptables -A INPUT -i interface -j MYCHAIN
    iptables -A MYCHAIN -j ACCEPT

can be reversed with

   iptables -D INPUT -i interface -j MYCHAIN
   iptables --flush MYCHAIN
   iptables -X MYCHAIN

You need two steps, but this does it in one command.

Create a file, and place this in it.

# Empty the entire filter table
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Save the file as "clear-all-rules". Now, do this command:

iptables-restore < clear-all-rules

Now you can clear it anytime with just one command.


Here's an alternate plan. It involves three commands, not one, but with luck, it should work.

Dump your iptables ruleset to a file:

iptables-save > /tmp/iptables.txt

Remove ALL uses of (and references to) the offending chain:

sed -i '/i_XXXXX_i/d' /tmp/iptables.txt

Then reload the ruleset:

iptables-restore < /tmp/iptables.txt && rm /tmp/iptables.txt