When tcptrack shows SYN_SENT connections while netstat reveals nothing, we're looking at a classic TCP handshake failure scenario. The SYN packet did reach your server's network interface (otherwise tcptrack wouldn't see it), but the TCP stack didn't process it properly to create a socket.
Here's the technical breakdown:
1. tcptrack operates at a lower level (libpcap) capturing packets before kernel processing
2. netstat only shows established sockets in the kernel's TCP stack
3. The disconnect suggests packets are dropped between NIC and TCP stack
Common culprits we should examine:
- Firewall rules silently dropping SYN packets (-j DROP vs -j REJECT)
- SYN flood protection (net.ipv4.tcp_syncookies)
- NIC queue issues or buffer overflows
- conntrack table exhaustion
- Improper TCP timestamp or window scaling options
For deeper investigation:
# Monitor kernel drops
$ ethtool -S eth0 | grep -i drop
$ cat /proc/net/softnet_stat
# Check connection tracking
$ conntrack -L count
$ sysctl net.netfilter.nf_conntrack_max
# Advanced packet capture
$ tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn) != 0 and not tcp[tcpflags] & (tcp-ack) != 0'
Since you mentioned Apache, verify these settings:
# In httpd.conf or apache2.conf
ListenBacklog 511
MaxRequestWorkers 150
EnableMMAP Off
EnableSendfile Off
Here's a script to monitor TCP handshake failures in real-time:
#!/bin/bash
INTERFACE=eth0
LOG_FILE=/var/log/tcp_handshake.log
while true; do
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
syn_count=$(netstat -s | grep -i "SYNs to LISTEN")
drop_count=$(netstat -s | grep -i "dropped")
echo "[$timestamp] SYNs: $syn_count | Drops: $drop_count" >> $LOG_FILE
sleep 5
done
Consider these specialized tools:
- ss (socket statistics) from iproute2
- dropwatch for kernel-level packet drop analysis
- perf-tools for tracing kernel functions
- ebpf-based tools like tcplife or tcptop
When troubleshooting connection timeout issues on our Apache server, we observed an interesting discrepancy between tcptrack
and netstat
outputs. Here's what's happening:
# tcptrack output example
192.168.1.100:51234 -> 10.0.0.1:80 [SYN_SENT] 0B 0B 0s
# netstat -nat output (no matching entry)
Not necessarily. tcptrack
showing SYN_SENT while netstat
shows nothing indicates one of these scenarios:
- The SYN packet was filtered/dropped before reaching TCP stack (firewall, iptables)
- The server's SYN backlog queue is full
- TCP timestamp or other options mismatch
The difference stems from their monitoring layers:
Tool | Monitoring Layer | SYN_SENT Visibility |
---|---|---|
tcptrack | Network interface (raw packets) | Sees all SYN packets arriving at NIC |
netstat | Kernel TCP stack | Only shows established connections |
Here are some effective ways to trace lost TCP connections:
# 1. tcpdump for packet-level inspection
sudo tcpdump -i eth0 'tcp port 80 and (tcp-syn|tcp-ack)'
# 2. Check SYN backlog and overflow counters
cat /proc/net/netstat | grep -i 'TcpExtListenOverflows\|TcpExtListenDrops'
# 3. Kernel parameter tuning (temporary test)
sysctl -w net.core.somaxconn=4096
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
For Apache servers, consider these configuration tweaks:
# In httpd.conf
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# For event MPM
<IfModule mpm_event_module>
ServerLimit 16
MaxRequestWorkers 400
ThreadsPerChild 25
</IfModule>
Here's a Python script to test SYN handling:
import socket
import time
def test_syn_handling(host, port, count=10):
successes = 0
for i in range(count):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.connect((host, port))
s.close()
successes += 1
except Exception as e:
print(f"Attempt {i+1} failed: {str(e)}")
time.sleep(0.1)
print(f"Success rate: {successes}/{count}")