tcpdump has a weird little filter language (BPF syntax) that I never remember under pressure. This page is my cheatsheet.
Basic syntax
tcpdump -i <interface> -n <filter>
-n don't resolve addresses/ports
-i interface (eth0, any, lo)
-v verbose (-vv, -vvv more)
-w write to file for later wireshark
-r read from file
-c N stop after N packets
-s 0 capture full packet (not truncated)
Host and network filters
host 192.0.2.1 # to or from
src host 192.0.2.1 # from only
dst host 192.0.2.1 # to only
net 192.0.2.0/24 # subnet
src net 192.0.2.0/24 # subnet as source
Port filters
port 443 # source or dest port 443
src port 443 # source only
dst port 443 # dest only
portrange 50000-60000 # range
Protocol filters
tcp # TCP only
udp # UDP only
icmp # ICMP only
arp # ARP
tcp port 443 # combine
'tcp[tcpflags] & tcp-syn != 0' # TCP with SYN flag
TCP flag combinations
# SYN only (connection attempts)
'tcp[tcpflags] == tcp-syn'
# SYN-ACK
'tcp[tcpflags] == tcp-syn|tcp-ack'
# RST (connection resets)
'tcp[tcpflags] & tcp-rst != 0'
# FIN (connection closes)
'tcp[tcpflags] & tcp-fin != 0'
Combining filters
host 192.0.2.1 and tcp port 443
'host 192.0.2.1 and (port 80 or port 443)'
'not arp and not port 22'
Boolean operators: and, or, not (or &&, ||, !).
Payload filters (advanced)
Capture HTTP GET requests:
'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420'
0x47455420 is ASCII “GET " (with trailing space). The [(tcp[12:1] & 0xf0) >> 2]:4 offset accesses the first 4 bytes of the TCP payload.
Similar for POST:
'tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354'
Interface tricks
# All interfaces (Linux)
tcpdump -i any
# Specific Docker container veth
tcpdump -i veth_abc123
# Wireguard interface
tcpdump -i wg0
Useful one-liners
Count packets by source IP:
tcpdump -i eth0 -n -c 1000 2>/dev/null | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head
DNS queries (port 53):
tcpdump -i any -n port 53 and not port 5353
SSL/TLS handshakes:
tcpdump -i eth0 -n 'tcp port 443 and (tcp[((tcp[12:1] & 0xf0) >> 2)] = 0x16)'
HTTP requests (including Host header):
tcpdump -i eth0 -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420 or tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x504f5354)'
Saving for wireshark analysis
tcpdump -i eth0 -w capture.pcap -s 0 'host problem-server.example.com'
Then open in Wireshark GUI locally. Wireshark has infinitely better filters and display — tcpdump is for capture, Wireshark for analysis.
When tcpdump isn’t enough
- ebpf tools (bpftrace, bcc) for kernel-level events tcpdump can’t see
- ss for socket-level details (-i for TCP info like cwnd, rtt)
- conntrack -L for NAT state
- tshark for scriptable wireshark-style analysis