tcpdump is your best friend when TCP is acting up, letting you see the raw handshake, data, and teardown exactly as it happens on the wire.

Let’s watch a simple HTTP GET request get captured and then debug a common problem.

First, the capture. We want to see TCP traffic on port 80, specifically from or to our local machine, and let’s save it to a file so we can analyze it later.

sudo tcpdump -i eth0 'tcp port 80 and host 192.168.1.100' -w http_capture.pcap

Here, sudo is needed because tcpdump needs elevated privileges to capture network packets. -i eth0 specifies the network interface to listen on (replace eth0 with your actual interface, like en0 on macOS or wlan0 for Wi-Fi). 'tcp port 80 and host 192.168.1.100' is the filter expression: we only care about TCP traffic on port 80, and we’re interested in communication involving the IP address 192.168.1.100. -w http_capture.pcap tells tcpdump to write the raw packets to a file named http_capture.pcap instead of printing them to the console.

Now, imagine you’re running a web server on 192.168.1.100 and clients can’t connect. You suspect a TCP issue. You’d run the tcpdump command above on the server. After a client tries to connect, you stop tcpdump (Ctrl+C) and analyze http_capture.pcap with tcpdump -r http_capture.pcap.

The most surprising thing about TCP debugging with tcpdump is that often, the problem isn’t in the data itself, but in the sequence and timing of the control packets. A dropped SYN-ACK or an out-of-order FIN can completely halt communication in ways that application logs might not even hint at.

Let’s look at a common scenario: a client sends a SYN, but the server never responds with a SYN-ACK.

[Client -> Server] SYN (Seq=12345)

If you tcpdump on the server and don’t see that SYN packet, the problem is upstream: a firewall is blocking it, or there’s a routing issue preventing it from reaching the server. The fix would be to check your firewall rules (e.g., sudo ufw status on Ubuntu, sudo iptables -L on Linux) to ensure port 80 is open, or investigate routing tables (ip route show).

If you do see the SYN on the server, but no SYN-ACK is sent back, the server’s TCP/IP stack is likely the culprit. The most common reason is that the server is overloaded and can’t process new connections. You’d check server resource utilization: top or htop to see CPU and memory load, and netstat -an | grep SYN_RECV to see how many connections are stuck in the SYN-RECV state. A high number here indicates the server is overwhelmed. The fix is to scale up your server resources (more CPU, RAM) or implement connection limiting at the OS level (e.g., adjusting net.ipv4.tcp_max_syn_backlog in /etc/sysctl.conf, then running sudo sysctl -p).

Another possibility is that the client’s IP address is being blocked by the server’s application itself, not the OS firewall. Some web servers or load balancers have their own IP blacklists. You’d need to inspect the configuration of your web server software (e.g., Nginx access.log and error.log, Apache httpd.conf and error_log) for any signs of blocked IPs. The fix is to remove the offending IP from the application’s blocklist.

Less common, but still relevant, is a misconfigured network interface on the server. Ensure ip addr show on Linux or ifconfig on macOS shows the correct IP address and that the interface is UP and RUNNING. If the IP is wrong, the server might be seeing the SYN but not recognizing it as destined for itself, or it might be trying to respond to the wrong interface. The fix is to correct the IP configuration using sudo ip addr add <correct_ip>/<netmask> dev eth0 and sudo ip link set dev eth0 up.

If the SYN is received and a SYN-ACK is sent back by the server, but the client never receives the SYN-ACK, then the problem is likely on the return path. This could be a firewall between the server and the client, or a routing issue on the server’s network segment. You’d tcpdump on the server again, but this time look for the SYN-ACK going out. If it’s there, you’d then tcpdump on the client to see if the SYN-ACK ever arrives. If it doesn’t, the issue is likely a network device (router, firewall) in between. The fix involves checking those intermediate devices.

Finally, consider the sequence numbers. TCP uses sequence numbers to order packets. If the server’s TCP stack is buggy or corrupted, it might send a SYN-ACK with an invalid or nonsensical sequence number. tcpdump will show this clearly. The fix here is often a server reboot, or in extreme cases, a TCP/IP stack reset at the OS level, though this is rare and usually points to deeper system instability.

Even after you’ve fixed the SYN/SYN-ACK exchange, you might encounter issues with the ACK packets. If the client sends data, and the server sends a SYN-ACK, but the client never sends an ACK for the SYN-ACK, the connection will eventually time out. tcpdump will show the SYN-ACK arriving at the client, but no subsequent ACK from the client. This is often indicative of the client’s TCP stack having issues or a firewall on the client side dropping the ACK.

The next common problem you’ll run into after fixing connection establishment is diagnosing stalled data transfers due to windowing issues or dropped packets.

Want structured learning?

Take the full Tcp course →