When dealing with iptables firewall configurations, you essentially have two modes of operation:
- Stateful: Uses connection tracking (conntrack) to maintain session state information
- Stateless: Processes each packet independently without tracking connections
The key difference manifests in how rules are evaluated. Stateful rules can reference connection states like NEW
, ESTABLISHED
, or RELATED
, while stateless rules must match packets based only on their immediate characteristics.
To verify if your current iptables configuration is truly stateless, check for these indicators:
# List all rules with state matching
iptables-save | grep -i "state\|ctstate"
# Check loaded kernel modules
lsmod | grep conntrack
# Examine conntrack table status
cat /proc/net/nf_conntrack
If you see rules referencing connection states or the conntrack module is loaded, your firewall isn't operating in pure stateless mode.
Here's how to transform common stateful rules to their stateless equivalents:
# Stateful rule (to replace)
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Stateless equivalent (for TCP)
iptables -A INPUT -p tcp ! --syn -j ACCEPT
# Stateless equivalent (general)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Remove this
iptables -A INPUT -p tcp --tcp-flags ALL ACK -j ACCEPT # Stateless alternative
For a complete stateless configuration:
# Unload conntrack modules
modprobe -r nf_conntrack_netlink nf_conntrack_ipv4 nf_conntrack
# Prevent module autoloading
echo "blacklist nf_conntrack" >> /etc/modprobe.d/blacklist.conf
echo "blacklist nf_conntrack_ipv4" >> /etc/modprobe.d/blacklist.conf
# Flush conntrack table
iptables -t raw -F
Here's a sample stateless ruleset for a web server:
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# HTTP/HTTPS access
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# SSH access with rate limiting (stateless alternative)
iptables -A INPUT -p tcp --dport 22 -m recent --set --name ssh
iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 3 --name ssh -j DROP
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
After configuration, verify with these checks:
# Check active connections (should be empty if stateless)
conntrack -L
# Monitor packet flow
tcpdump -n -i eth0 not port 22
# Check kernel memory usage (conntrack allocates significant memory)
grep -i conntrack /proc/slabinfo
During peak traffic periods, Linux servers running stateful firewalls often encounter conntrack table overflows, leading to performance degradation or dropped connections. The connection tracking subsystem (nf_conntrack) maintains state tables that can consume significant system resources.
To check if your current iptables rules are stateless:
# List all iptables rules with verbose output
iptables -L -v
# Look for these stateful indicators:
# - References to 'ctstate' or 'state'
# - Rules containing '-m state' or '-m conntrack'
# - Rules mentioning 'ESTABLISHED,RELATED'
Here's how to convert common stateful rules to stateless equivalents:
# Stateful version
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Stateless equivalent (requires explicit port rules)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT # SSH
iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTP
To fully disable connection tracking:
# Unload conntrack modules
modprobe -r xt_conntrack nf_conntrack_ipv4 nf_conntrack
# Prevent module reload
echo "blacklist nf_conntrack" >> /etc/modprobe.d/blacklist.conf
echo "blacklist xt_conntrack" >> /etc/modprobe.d/blacklist.conf
Confirm your firewall is stateless with these checks:
# Check loaded kernel modules
lsmod | grep conntrack
# Examine current connection tracking
cat /proc/net/nf_conntrack
# Monitor conntrack table size
sysctl net.netfilter.nf_conntrack_count
Stateless firewalls typically show:
- 30-50% reduction in memory usage
- Lower CPU overhead during traffic spikes
- Elimination of conntrack-related bottlenecks
A basic stateless webserver configuration:
# Flush existing rules
iptables -F
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# ICMP (ping)
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
# SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Rate limiting for SSH (stateless method)
iptables -A INPUT -p tcp --dport 22 -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP