A surprising truth about tcpdump is that it’s not just a packet sniffer; it’s a powerful diagnostic tool that can dissect network conversations at a granular level, making it indispensable for understanding and troubleshooting network behavior.

Let’s watch tcpdump in action, filtering for specific traffic. Imagine we’re troubleshooting a web server and want to see only incoming HTTP requests on port 80, and also any UDP traffic on port 53 (DNS).

sudo tcpdump -i eth0 'tcp port 80 or udp port 53'

Here, -i eth0 tells tcpdump to listen on the eth0 network interface. The core of the command is the filter expression 'tcp port 80 or udp port 53'. This tells tcpdump to capture packets that are either TCP packets destined for port 80 or UDP packets destined for port 53. You’ll see a stream of output showing packets matching these criteria, like this:

14:35:10.123456 IP 192.168.1.100.54321 > 192.168.1.200.80: Flags [S], seq 123456789, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 12345678 ecr 0], length 0
14:35:10.123500 IP 192.168.1.200.80 > 192.168.1.100.54321: Flags [S.], seq 987654321, ack 123456790, win 29200, options [mss 1460,nop,wscale 6,TS val 87654321 ecr 12345678], length 0
14:35:10.123600 IP 192.168.1.100.54321 > 192.168.1.200.80: Flags [.], ack 1, win 1024, options [nop,nop,TS val 12345679 ecr 87654321], length 0
14:35:10.124000 IP 192.168.1.200.80 > 192.168.1.100.54321: Flags [P.], seq 1:100, ack 1, win 1024, options [nop,nop,TS val 87654322 ecr 12345679], length 99: HTTP: GET / HTTP/1.1
14:35:10.500000 IP 192.168.1.50.12345 > 192.168.1.200.53: 12345+ A? example.com. (28)
14:35:10.500100 IP 192.168.1.200.53 > 192.168.1.50.12345: 12345 1/0/0 A 93.184.216.34 (44)

This output shows a TCP handshake for an HTTP connection followed by a DNS query and its response.

The fundamental problem tcpdump solves is visibility. Networks are often black boxes. When something goes wrong, you don’t know what is being sent, to whom, or why. tcpdump, with its filtering capabilities, acts like a targeted spotlight, illuminating only the traffic relevant to your investigation.

Internally, tcpdump uses the libpcap library (or WinPcap on Windows) to capture packets directly from the network interface. The filter expression you provide is processed by the kernel’s packet filtering engine (like Berkeley Packet Filter - BPF) before the packets are even copied into user space. This is incredibly efficient, as it minimizes the amount of data tcpdump has to process and store, preventing it from overwhelming your system.

The filter syntax is a powerful mini-language. You can combine conditions using logical operators: and (or &&), or (or ||), and not (or !). You can filter by protocol (tcp, udp, icmp, arp), by host (host 192.168.1.1), by port (port 22), by network (net 10.0.0.0/8), or even by specific packet content (though this is more advanced). You can also specify direction (src or dst) to narrow down traffic even further. For example, tcp src port 80 and dst host 192.168.1.200 would show only TCP traffic originating from port 80 and destined for the server at 192.168.1.200.

A common misconception is that tcpdump can only capture raw packets. However, when you use the -X or -A flags, tcpdump can display the packet’s payload in hexadecimal (-X) or ASCII (-A) format, respectively. This is invaluable for understanding the actual data being transmitted, especially for application-level protocols. For instance, using sudo tcpdump -i eth0 -A 'tcp port 80' will show you the HTTP requests and responses in a human-readable format, making it easy to spot errors in application logic or malformed requests.

When you need to capture traffic to a file for later analysis, use the -w flag. For example, sudo tcpdump -i eth0 -w capture.pcap 'tcp port 80'. This saves the raw packets to capture.pcap, which can then be opened by tcpdump itself or more advanced tools like Wireshark. The -r flag is used to read from such a file: tcpdump -r capture.pcap.

Understanding how to combine these filters is key. For instance, to see all ICMP traffic, you’d use icmp. To see only ICMP echo requests (pings) from a specific host, you might use host 192.168.1.100 and icmp[icmptype] == icmp-echo. The icmp[icmptype] part is a bitmask operation on the ICMP header, where icmp-echo is a predefined constant representing the type code for echo requests. This level of detail allows for very precise network diagnostics.

After you’ve successfully filtered and analyzed your traffic, the next challenge you’ll likely face is dealing with the sheer volume of data, even with filters, and learning how to correlate packet captures with application logs.

Want structured learning?

Take the full Tcpdump course →