iptables -A vs -I: Understanding Rule Insertion Order in Linux Firewall Configuration


1 views

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:

  1. Your INPUT chain likely had a DROP/REJECT rule at the end
  2. Appended DNS rule came AFTER the blocking rule
  3. 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