When working with iptables, you might encounter situations where you need to delete an entire chain along with all its references. The standard approach of using iptables -X chain_name
often fails with the "Too many links" error when jump rules still reference the chain.
In your case, you have a chain i_XXXXX_i
that's referenced in multiple rules across INPUT and OUTPUT chains. The error occurs because:
1. References exist in other chains (INPUT/OUTPUT)
2. Simply flushing (-F) doesn't remove these references
3. The chain cannot be deleted while being referenced
Here's the proper sequence to completely remove a chain:
# First, list all rules referencing the chain
iptables-save | grep i_XXXXX_i
# Then delete all referencing rules
iptables -D INPUT -s 282.202.203.83/32 -j i_XXXXX_i
iptables -D INPUT -s 222.202.62.253/32 -j i_XXXXX_i
iptables -D OUTPUT -d 282.202.203.83/32 -j i_XXXXX_i
# ... repeat for all references
# Flush the chain itself
iptables -F i_XXXXX_i
# Finally delete the chain
iptables -X i_XXXXX_i
For chains with many references, use this bash script:
#!/bin/bash
CHAIN="i_XXXXX_i"
# Delete all rules referencing the chain
for rule_num in $(iptables -L INPUT --line-numbers | grep "$CHAIN" | awk '{print $1}' | sort -rn); do
iptables -D INPUT $rule_num
done
for rule_num in $(iptables -L OUTPUT --line-numbers | grep "$CHAIN" | awk '{print $1}' | sort -rn); do
iptables -D OUTPUT $rule_num
done
# Flush and delete the chain
iptables -F "$CHAIN"
iptables -X "$CHAIN"
You can also use iptables-save/restore for complex cases:
iptables-save | grep -v "i_XXXXX_i" | iptables-restore
This method removes all rules mentioning the chain in one operation.
When working with iptables firewall rules in Linux, you might encounter a situation where you need to completely remove a custom chain along with all its associated rules. The error iptables: Too many links
typically occurs when you attempt to delete a chain that still has references from other rules.
In your case, you have a chain named i_XXXXX_i
with multiple jump rules from both INPUT and OUTPUT chains. Simply running:
iptables -F i_XXXXX_i # Flush chain rules
iptables -X i_XXXXX_i # Delete the chain
won't work because the chain is still being referenced by other rules.
Here's the proper sequence to completely remove a chain and all its references:
# First, list all rules referencing the chain
iptables-save | grep i_XXXXX_i
# Then delete all referencing rules
iptables -D INPUT -s 282.202.203.83/32 -j i_XXXXX_i
iptables -D INPUT -s 222.202.62.253/32 -j i_XXXXX_i
iptables -D INPUT -s 222.202.60.62/32 -j i_XXXXX_i
iptables -D INPUT -s 224.93.27.235/32 -j i_XXXXX_i
iptables -D OUTPUT -d 282.202.203.83/32 -j i_XXXXX_i
iptables -D OUTPUT -d 222.202.62.253/32 -j i_XXXXX_i
iptables -D OUTPUT -d 222.202.60.62/32 -j i_XXXXX_i
iptables -D OUTPUT -d 224.93.27.235/32 -j i_XXXXX_i
# Flush the chain's rules
iptables -F i_XXXXX_i
# Finally, delete the chain
iptables -X i_XXXXX_i
For frequently performing this task, consider creating a bash function:
function delete_iptables_chain() {
local chain_name="$1"
# Delete all rules referencing the chain
iptables-save | grep -E "\-j ${chain_name}\>" | \
while read -r rule; do
iptables -D ${rule#*-A }
done
# Flush and delete the chain
iptables -F "$chain_name"
iptables -X "$chain_name"
}
# Usage
delete_iptables_chain i_XXXXX_i
For complex rule sets, this method is more reliable:
# Create a backup
iptables-save > iptables.backup
# Filter out unwanted chain and references
grep -vE "(^-A.*-j i_XXXXX_i|^:i_XXXXX_i)" iptables.backup > iptables.new
# Restore cleaned rules
iptables-restore < iptables.new
- Always backup your iptables rules before making changes
- Consider using
iptables-persistent
package to save changes - For complex firewalls, investigate using nftables as iptables' successor