The Case Against "You Need a Cloud WAF"
The conventional wisdom for SYN flood protection is to put your traffic through a cloud provider's scrubbing infrastructure. Cloudflare, AWS Shield, and similar services are excellent options when you are already using them. But they are not prerequisites for detection. Detection and mitigation are different problems. You can know you are under a SYN flood — within seconds of it starting — using nothing but the counters the Linux kernel already maintains.
This matters for two reasons. First, detection is what triggers mitigation. Whether you respond by calling your upstream NOC, enabling SYN cookies, or spinning up emergency iptables rules, you can only do any of those things if you know the attack is happening. Second, many servers — bare-metal game hosts, dedicated database servers, VPS instances — cannot simply be placed behind a WAF without significant architecture changes. These hosts still need SYN flood detection.
Reading /proc/net/snmp
The most reliable source of SYN flood data on a Linux system is /proc/net/snmp. This file exposes SNMP MIB-II counters that the kernel updates in real time. The relevant section is TcpExt, and within it the key counters are:
TcpExtSyncookiesSent— increments every time the kernel sends a SYN-ACK with a SYN cookie instead of allocating a connection table slot. Non-zero means the SYN backlog queue is full.TcpExtSyncookiesRecv— increments when a valid cookie ACK comes back. The ratio of Sent to Recv tells you how many SYN requests completed the handshake versus how many were from spoofed IPs.TcpExtSyncookiesFailed— bad cookie ACKs. Elevated during attacks where the attacker sends a second wave of ACKs with invalid cookies.TcpExtTCPReqQFullDrop— SYN requests dropped because the half-open queue was full. This fires before SYN cookies kick in.TcpExtTCPReqQFullDoCookies— SYN requests where the kernel fell back to SYN cookies because the queue was full.
# Read current SYN cookie counters
grep -A1 "^TcpExt:" /proc/net/snmp | tail -1 | tr ' ' '\n' | \
paste - <(grep "^TcpExt:" /proc/net/snmp | tr ' ' '\n') | \
grep -E "Syncookies|ReqQFull"
# Cleaner one-liner: extract just the values you care about
awk '/^TcpExt:/{
split($0,h)
getline
split($0,v)
for(i in h) {
if(h[i]~/Syncookies|ReqQFull/) printf "%s = %s\n", h[i], v[i]
}
}' /proc/net/snmp
At baseline, TcpExtSyncookiesSent should be zero or very close to it. If you poll this counter every second and see it incrementing, a SYN flood is filling your connection backlog. The rate of increment correlates directly with the attack intensity.
Using ss -s for Real-Time Half-Open Connection Counts
The ss command can report TCP state summaries directly from the kernel. During a SYN flood, the SYN-RECV state count is the most informative:
# Check TCP state summary ss -s # Normal output: # Total: 847 # TCP: 312 (estab 298, closed 4, orphaned 2, timewait 4) # # Under SYN flood: # Total: 65891 # TCP: 65412 (estab 287, closed 3, orphaned 0, timewait 2, synrecv 65120) # Get just the SYN-RECV count for scripting ss -tn state syn-recv | wc -l
A healthy server with normal traffic will have fewer than 10 connections in SYN-RECV state at any given moment. During a SYN flood, this number climbs into the thousands or tens of thousands. When it hits net.ipv4.tcp_max_syn_backlog (check with sysctl net.ipv4.tcp_max_syn_backlog), the kernel either drops new SYNs or activates SYN cookies.
Know about SYN floods before your users do
Flowtriq detects attacks like this in under 2 seconds, classifies them automatically, and alerts your team instantly. 7-day free trial.
Start Free Trial →Reading /proc/net/tcp Directly
For environments where you cannot install extra tooling, /proc/net/tcp gives you the raw connection table. Each line represents one socket. The fifth field is the TCP state in hex: 01 = ESTABLISHED, 02 = SYN_SENT, 03 = SYN_RECV, 06 = TIME_WAIT.
# Count SYN_RECV sockets directly from /proc/net/tcp
awk '$4 == "03" {count++} END {print count " SYN_RECV sockets"}' /proc/net/tcp
# Build a simple monitor loop (no watch required)
while true; do
COUNT=$(awk '$4=="03"{c++}END{print c+0}' /proc/net/tcp)
echo "$(date +%T) SYN_RECV: $COUNT"
[ "$COUNT" -gt 1000 ] && echo "*** ALERT: Possible SYN flood ***"
sleep 1
done
Conntrack Table Exhaustion: The Silent Killer
If you are running iptables with the conntrack module (which you almost certainly are if you use -m state or -m conntrack rules), a SYN flood can exhaust the conntrack table before it exhausts the TCP backlog. When the conntrack table is full, the kernel cannot track new connections and starts dropping packets — including packets from legitimate, established connections.
# Check current conntrack table usage
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# Calculate percentage full
awk '{print "Conntrack usage: " $1}' /proc/sys/net/netfilter/nf_conntrack_count
awk '{print "Conntrack limit: " $1}' /proc/sys/net/netfilter/nf_conntrack_max
# Watch for exhaustion in real time
watch -n1 'echo "$(cat /proc/sys/net/netfilter/nf_conntrack_count) / \
$(cat /proc/sys/net/netfilter/nf_conntrack_max)" | bc -l | \
awk "{printf \"Conntrack: %.1f%% full\n\", \$1*100}"'
When nf_conntrack_count approaches nf_conntrack_max, the kernel logs a message like nf_conntrack: table full, dropping packet to dmesg. You can watch for this with:
dmesg -w | grep "nf_conntrack" # or journalctl -k -f | grep "nf_conntrack"
The default
nf_conntrack_maxon most distributions is 65,536. A moderate SYN flood generating 10,000 half-open connections per second will fill this table in about 6 seconds. Increase it withsysctl -w net.netfilter.nf_conntrack_max=524288as a temporary measure while you implement rate limiting.
iptables NEW State Rate Limiting for Detection
Beyond counting, you can use iptables to implement detection thresholds that trigger alerts or automatic mitigations. The --state NEW rate limit approach:
# Log when the new connection rate exceeds threshold
# This creates a detection rule, not a drop rule
iptables -A INPUT -p tcp --syn -m state --state NEW \
-m limit --limit 1000/s --limit-burst 500 -j ACCEPT
iptables -A INPUT -p tcp --syn -m state --state NEW \
-m limit --limit 5/s --limit-burst 10 \
-j LOG --log-prefix "SYN_FLOOD_DETECT: " --log-level 4
iptables -A INPUT -p tcp --syn -m state --state NEW -j DROP
# Monitor log entries per second as an attack rate indicator
journalctl -k -f | grep "SYN_FLOOD_DETECT" | \
awk '{count++; if(count%100==0) print count " SYN packets logged"}'
How Flowtriq Reads These Same Counters
Flowtriq's bare-metal agent runs on your server and reads /proc/net/snmp, /proc/net/dev, and the conntrack counters every second. It calculates the rate of change for TcpExtSyncookiesSent and TcpExtTCPReqQFullDrop, compares them against a rolling baseline, and fires a SYN flood alert when the derivative exceeds the anomaly threshold — typically within 1–2 seconds of attack onset.
The alert includes the current TcpExtSyncookiesSent rate, the SYN-RECV socket count, and a PCAP of the attack traffic. If you have PagerDuty, Slack, or webhook integrations configured, the alert lands there before you would have even noticed the connection rate climbing in a dashboard.
Protect your infrastructure with Flowtriq
Per-second DDoS detection, automatic attack classification, PCAP forensics, and instant multi-channel alerts. $9.99/node/month.
Start your free 7-day trial →