Skip to content

๐Ÿ” conntrack Connection Tracking โ€‹

What is Connection Tracking? โ€‹

For a firewall to determine whether a packet belongs to a "new connection" or is a "subsequent packet of an existing connection," it relies on conntrack (Connection Tracking). It maintains a connection table that records the state of each connection.

This is why you often see -m state --state ESTABLISHED,RELATED -j ACCEPT โ€” it allows reply packets for established connections to pass through, saving you from writing rules for each direction.

๐Ÿ’ก Tip: ๐Ÿ’ก Three states: NEW โ€” the first packet, the start of a new connection. ESTABLISHED โ€” connection established, data flowing in both directions. RELATED โ€” related to an existing connection (e.g., FTP data channel, ICMP errors). There's also INVALID โ€” unrecognized packets, which are usually dropped directly.

Viewing the Connection Tracking Table โ€‹

bash
# View all tracked connections
conntrack -L
tcp  6 431999 ESTABLISHED src=192.168.1.100 dst=10.0.0.50 sport=54321 dport=80 src=10.0.0.50 dst=192.168.1.100 sport=80 dport=54321 [ASSURED] use=1
udp  17 29 src=192.168.1.100 dst=8.8.8.8 sport=12345 dport=53 src=8.8.8.8 dst=192.168.1.100 sport=53 dport=12345 use=1

# View only TCP connections
conntrack -L -p tcp

# View connections from a specific IP
conntrack -L -s 192.168.1.100

# Count connections
conntrack -C
247

# View the maximum tracking count allowed by the kernel
sysctl net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_max = 262144

โš ๏ธ Warning: โš ๏ธ What happens when the connection limit is reached? If the tracking table is full (reaching nf_conntrack_max), new connections will be silently dropped! Your server will suddenly "lose connectivity" โ€” SSH disconnects, websites become inaccessible, but ping might still work. This is one of the most common "mysterious failures" in production environments.

Adjusting Connection Tracking Parameters โ€‹

bash
# View current values
sysctl net.netfilter.nf_conntrack_max
sysctl net.netfilter.nf_conntrack_tcp_timeout_established

# Temporary adjustment (lost on reboot)
sysctl -w net.netfilter.nf_conntrack_max=524288
sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=3600

# Make permanent โ€” write to /etc/sysctl.conf
cat >> /etc/sysctl.conf << 'EOF'
# conntrack optimization
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 15
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 30
EOF

sysctl -p

# Monitor tracking table usage
watch -n 2 'conntrack -C && echo "/ $(sysctl -n net.netfilter.nf_conntrack_max)"'

๐Ÿ’ก Tip: ๐Ÿ’ก Recommended values: Regular web server: 524288 (2x the default). High-traffic Nginx reverse proxy: 1048576. Database server: default is usually sufficient. Reducing TIME_WAIT timeout from the default 120s to 30s can reclaim many "zombie connections."

conntrack and Performance โ€‹

conntrack isn't free โ€” every connection takes up a record in the kernel. Pay special attention in the following scenarios:

ScenarioProblemSolution
NAT gatewayAll internal traffic goes through conntrack, table fills up quicklyIncrease nf_conntrack_max + optimize timeouts
High-concurrency webMassive short-lived connections put pressure on tracking tableUse NOTRACK to skip tracking + keepalive
DNS serverMany short UDP connectionsSet short UDP timeout (15-30s)
FTP serverRELATED state tracking adds extra overheadLoad nf_conntrack_ftp module
bash
# Skip connection tracking for specific traffic (improve performance)
iptables -t raw -A PREROUTING -p tcp --dport 80 -j NOTRACK
iptables -t raw -A OUTPUT -p tcp --sport 80 -j NOTRACK

# Accordingly, this traffic cannot be matched with -m state
# Use -m conntrack --ctstate or just allow directly
iptables -A INPUT -p tcp --dport 80 -j ACCEPT