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:
- Test new rules in a non-production environment
- Update documentation and automation scripts
- 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