When working with iptables, the order in which rules are added significantly impacts firewall behavior. The difference between -A
(append) and -I
(insert) isn't just about syntax but fundamentally changes how packets are processed.
# Append (-A) adds rule to END of chain
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Insert (-I) adds rule to BEGINNING of chain (default position 1)
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
# You can also specify insertion position
iptables -I INPUT 3 -p udp --dport 53 -j ACCEPT
The original issue occurred because:
- Your INPUT chain likely had a DROP/REJECT rule at the end
- Appended DNS rule came AFTER the blocking rule
- Packets matched the blocking rule first
Correct DNS configuration:
# First allow DNS (insert at beginning)
iptables -I INPUT -p udp --dport 53 -j ACCEPT
iptables -I INPUT -p tcp --dport 53 -j ACCEPT
# Then add other rules
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Default deny policy at end
iptables -A INPUT -j DROP
Use -I when:
- Adding exceptions to restrictive policies
- Creating high-priority allow rules
- Debugging (temporarily inserting test rules)
Use -A when:
- Adding default policies
- Building ordered rule sequences
- Maintaining rule hierarchy
# Insert rule as 4th in chain
iptables -I INPUT 4 -p tcp --dport 443 -j ACCEPT
# View rule positions with line numbers
iptables -L -n --line-numbers
In iptables, -A
(APPEND) and -I
(INSERT) represent fundamentally different approaches to rule placement:
# Appends to the end of the INPUT chain
iptables -A INPUT -p udp --dport 53 -j ACCEPT
# Inserts at the beginning (default position 1) of INPUT chain
iptables -I INPUT -p udp --dport 53 -j ACCEPT
Packet processing follows the chain's rule order sequentially. A common mistake scenario:
# Existing rules:
iptables -A INPUT -j DROP # Default drop at chain end
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH allowed
# Problem: This DNS rule won't work because it's added AFTER the DROP
iptables -A INPUT -p udp --dport 53 -j ACCEPT
When to use -A:
- General allow rules where order doesn't matter
- Final default policies (DROP/REJECT)
- Logging rules at chain end
When to use -I:
- Critical service access (SSH, DNS, etc.)
- Rules that must precede restrictive policies
- Temporary debugging rules
Both commands support explicit positioning:
# Insert as 3rd rule in INPUT chain
iptables -I INPUT 3 -p tcp --dport 443 -j ACCEPT
# Append to OUTPUT chain with connection tracking
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
View your current rule sequence with line numbers:
iptables -L INPUT -v --line-numbers
Example output showing why a DNS rule might fail:
num pkts bytes target prot opt in out source destination
1 0 0 DROP all -- * * 0.0.0.0/0 0.0.0.0/0
2 142 10384 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp dpt:53