iptables: State vs Conntrack Modules – Key Differences and Best Practices for Connection Tracking


2 views

When working with iptables firewall rules, you'll encounter two similar but distinct modules for connection tracking:

# Legacy state module
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# Modern conntrack module
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

The state module was the original implementation in early Linux kernels. The conntrack module was introduced later as a more powerful replacement that directly interfaces with the connection tracking system (conntrack).

Key technical distinctions between the modules:

  • Module Name: -m state vs -m conntrack
  • Parameter Syntax: --state vs --ctstate
  • Underlying System: Both use the same connection tracking system (nf_conntrack)
  • Compatibility: state is older but still widely supported

While both essentially perform the same function, there are subtle differences:

# Using conntrack with additional features:
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP

# Using state with older kernels:
iptables -A INPUT -m state --state INVALID -j DROP

For modern systems (Linux kernel 2.6+), conntrack is recommended because:

  • It's actively maintained and enhanced
  • Provides better integration with newer netfilter features
  • Supports more connection tracking states and parameters

Here's how you might use conntrack for more complex scenarios:

# Allow SSH only for established connections
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

# Rate limit new connections
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 60/minute --limit-burst 20 -j ACCEPT

If you need to support very old Linux distributions (pre-2006), you might need to use the state module. For modern systems, the conntrack module is preferred as it provides access to the full range of connection tracking features.

When writing firewall rules today, I recommend using the conntrack module exclusively unless you have specific legacy compatibility requirements. The syntax is cleaner and it's better aligned with the current netfilter architecture.


While both -m state and -m conntrack serve similar purposes in iptables rules for connection tracking, they represent different generations of the connection tracking system:

  • state module: The older implementation (deprecated in newer kernels) that uses simple connection state tracking
  • conntrack module: The modern replacement that interfaces with the more sophisticated netfilter connection tracking system

The conntrack module provides several advantages:

// Legacy state module example
iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT

// Modern conntrack equivalent
iptables -A INPUT -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT

Key differences include:

  • Conntrack supports more complex connection states and additional parameters
  • Better integration with other netfilter subsystems
  • More consistent behavior across different kernel versions

For modern systems (kernel 2.6.18+), you should use -m conntrack exclusively. Here's a complete example firewall rule set:

# Flush existing rules
iptables -F
iptables -X

# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow loopback
iptables -A INPUT -i lo -j ACCEPT

# Allow established/related connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Allow ICMP (ping)
iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ACCEPT

# Allow SSH
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT

# Log dropped packets
iptables -A INPUT -j LOG --log-prefix "iptables-dropped: "

When upgrading from older systems using state module:

  1. Test new rules in a non-production environment
  2. Update documentation and automation scripts
  3. Monitor logs for any connection tracking issues

The conntrack module generally performs better because:

  • It's integrated with the kernel's connection tracking subsystem
  • Reduces redundant state checking
  • Supports more efficient hashing of connection states