Unlike traditional firewalls like IPFW that require explicit state tracking rules, Linux's conntrack module in iptables operates automatically at the kernel level. The module begins tracking connection states the moment the first packet of a new connection hits the network stack - before any iptables rules are processed.
The state table gets populated through these automatic mechanisms:
1. When SYN packet initiates TCP connection
2. When first packet of UDP "connection" arrives
3. When ICMP request is detected
4. For other protocol's initial packets
Rules such as:
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
are not enabling tracking, but rather querying the existing state table that was populated automatically. This rule means: "Accept packets that belong to already established connections or related connections (like FTP data channels)."
A typical stateful firewall setup would look like:
# Allow established/related connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow new outgoing connections (tracking happens automatically)
iptables -A OUTPUT -j ACCEPT
# Allow specific new incoming connections (e.g., SSH)
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
# Default deny
iptables -P INPUT DROP
iptables -P FORWARD DROP
1. No need for explicit "keep state" rules - tracking is automatic
2. State table is shared between all chains (INPUT/OUTPUT/FORWARD)
3. States persist for some time even after connection closes (adjustable via sysctl)
To inspect the current connection tracking table:
conntrack -L
# Or for continuous monitoring:
conntrack -E
You can tune conntrack behavior through sysctl parameters:
# Increase maximum connections
sysctl -w net.netfilter.nf_conntrack_max=262144
# Adjust timeout for established TCP connections
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400
The Linux conntrack (connection tracking) module operates at a lower level than iptables rules and maintains connection states independently. Unlike BSD's IPFW where state tracking requires explicit rules, conntrack automatically tracks all connections passing through the system by default.
conntrack begins tracking packets as soon as they hit the network stack, before any iptables processing occurs. The module maintains a connection tracking table (/proc/net/nf_conntrack
) with entries for each observed connection. This happens automatically for:
- TCP connections (with full state tracking)
- UDP "connections" (tracked as pseudo-connections)
- ICMP (for error messages related to connections)
The example rule you mentioned:
iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Does NOT initiate state tracking. Instead, it:
- References the existing connection state information maintained by conntrack
- Matches packets that are part of established connections or related to them
- Accepts these packets to bypass further processing
Here are some common scenarios with corresponding iptables rules:
# Basic stateful firewall allowing outgoing connections
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
To inspect current connections being tracked:
cat /proc/net/nf_conntrack
# Or using conntrack-tools:
conntrack -L
To remove specific entries:
conntrack -D -s 192.168.1.100
You can tune conntrack parameters via sysctl:
# Increase maximum connections
sysctl -w net.netfilter.nf_conntrack_max=65536
# Set timeout for TCP connections
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=86400
When troubleshooting:
# View conntrack table with timestamps
conntrack -L -o extended
# Monitor connection events in real-time
conntrack -E