TTR Networks

Intermediate · Packets That Never Come Back · section 2 of 7

tcpdump essentials

✓ Lab-tested 17 October 2026 on VyOS 2026.10.16-0024-rolling, Debian 12

tcpdump captures packets as the kernel sees them on an interface: before the host firewall drops incoming packets, and after routing chooses an outgoing interface. That makes it the ground truth for "did it arrive?" and "did it leave?".

Options you'll use every time

OptionWhy
-i eth0Pick the interface. -i any is handy but merges interfaces and loses the Ethernet header.
-nnDon't resolve names or ports. Faster, and no misleading DNS lookups.
-eShow MAC addresses: which router did that packet come from or go to?
-vShow IP header details: TTL, DF flag, total length, ID.
-c 20Stop after 20 packets.
-lLine-buffer output, so it shows up immediately in pipes.
-w file.pcap / -r file.pcapWrite raw packets for later (or for Wireshark), and read them back with any filter.
-A / -XPrint the payload as ASCII, or hex + ASCII.
-s 96Capture only the first 96 bytes: headers only, much smaller files.
-C 100 -W 10Ring buffer: 10 files of 100 MB each, oldest overwritten. Leave it running until the problem recurs.

Filters (BPF)

Filters run in the kernel, so only matching packets are copied to tcpdump. Quote them.

  • Hosts and ports: host 203.0.113.20, src net 10.0.0.0/24, tcp port 443, portrange 33434-33534
  • Combine with and, or, not and parentheses: icmp or (tcp port 9000 and greater 1400)
  • TCP flags: tcp[tcpflags] & tcp-syn != 0 (SYN and SYN-ACK), tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0 (connection starts and ends)
  • ICMP types: icmp[icmptype] == icmp-unreach
  • Size: greater 1400 / less 100

Capture first, filter later: a broad -w capture can be re-read with many narrow filters without asking the problem to happen again.

Capture to a file (real output)
root@client:~# tcpdump -nn -i eth0 -c 10 -w /tmp/web.pcap tcp port 80
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10 packets captured
10 packets received by filter
0 packets dropped by kernel
  • Line 1: -w writes raw packets instead of decoding them; -c 10 stops after ten. The filter keeps the file small.
  • Lines 3–5: "dropped by kernel" > 0 means tcpdump couldn't keep up. Narrow the filter, or write to a file instead of the screen.
Read it back three ways (real output)
root@client:~# tcpdump -nn -r /tmp/web.pcap
reading from file /tmp/web.pcap, link-type EN10MB (Ethernet), snapshot length 262144
21:43:37.117915 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [S], seq 4126017685, win 64240, options [mss 1460,sackOK,TS val 662061826 ecr 0,nop,wscale 10], length 0
21:43:37.118945 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [S.], seq 976961291, ack 4126017686, win 65160, options [mss 1360,sackOK,TS val 1265992858 ecr 662061826,nop,wscale 10], length 0
21:43:37.118959 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [.], ack 1, win 63, options [nop,nop,TS val 662061827 ecr 1265992858], length 0
21:43:37.118996 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [P.], seq 1:87, ack 1, win 63, options [nop,nop,TS val 662061827 ecr 1265992858], length 86: HTTP: GET /index.html HTTP/1.1
21:43:37.119343 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [.], ack 87, win 64, options [nop,nop,TS val 1265992859 ecr 662061827], length 0
21:43:37.121717 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [P.], seq 1:185, ack 87, win 64, options [nop,nop,TS val 1265992861 ecr 662061827], length 184: HTTP: HTTP/1.0 200 OK
21:43:37.121726 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [.], ack 185, win 63, options [nop,nop,TS val 662061830 ecr 1265992861], length 0
21:43:37.121734 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [FP.], seq 185:191, ack 87, win 64, options [nop,nop,TS val 1265992861 ecr 662061827], length 6: HTTP
21:43:37.121777 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [F.], seq 87, ack 192, win 63, options [nop,nop,TS val 662061830 ecr 1265992861], length 0
21:43:37.122042 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [.], ack 88, win 64, options [nop,nop,TS val 1265992861 ecr 662061830], length 0
root@client:~# tcpdump -nn -r /tmp/web.pcap "tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0"
reading from file /tmp/web.pcap, link-type EN10MB (Ethernet), snapshot length 262144
21:43:37.117915 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [S], seq 4126017685, win 64240, options [mss 1460,sackOK,TS val 662061826 ecr 0,nop,wscale 10], length 0
21:43:37.118945 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [S.], seq 976961291, ack 4126017686, win 65160, options [mss 1360,sackOK,TS val 1265992858 ecr 662061826,nop,wscale 10], length 0
21:43:37.121734 IP 203.0.113.20.80 > 10.0.0.10.58780: Flags [FP.], seq 185:191, ack 87, win 64, options [nop,nop,TS val 1265992861 ecr 662061827], length 6: HTTP
21:43:37.121777 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [F.], seq 87, ack 192, win 63, options [nop,nop,TS val 662061830 ecr 1265992861], length 0
root@client:~# tcpdump -nn -A -r /tmp/web.pcap "tcp dst port 80 and tcp[tcpflags] & tcp-push != 0"
reading from file /tmp/web.pcap, link-type EN10MB (Ethernet), snapshot length 262144
21:43:37.118996 IP 10.0.0.10.58780 > 203.0.113.20.80: Flags [P.], seq 4126017686:4126017772, ack 976961292, win 63, options [nop,nop,TS val 662061827 ecr 1265992858], length 86: HTTP: GET /index.html HTTP/1.1
E...P.@.@..!
..
..q....P....:;?....?F......
'vC.Ku..GET /index.html HTTP/1.1
Host: 203.0.113.20
User-Agent: curl/7.88.1
Accept: */*
  • Lines 3–5: The three-way handshake: SYN [S], SYN-ACK [S.], ACK [.]. (The SYN-ACK's mss 1360 comes from the MSS clamp configured in scenario 3.)
  • Lines 6–8: [P.] = push + ack: data. The 86-byte request, then the 184-byte response.
  • Lines 10–12: [F.]: each side closes its half of the connection.
  • Lines 13–18: Only connection starts and ends: the quickest way to see whether connections are being set up, refused ([R]) or torn down.
  • Lines 19–28: -A prints the payload as text: the HTTP request itself. Only works for unencrypted protocols.
A ring buffer (real output)
# Ran for 12 s while big.bin (300 KB) was downloaded 12 times:
root@client:~# timeout 12 tcpdump -nn -i eth0 -w /tmp/ring.pcap -C 1 -W 3 tcp port 80
root@client:~# ls -l /tmp/ring.pcap*
-rw-r--r-- 1 tcpdump tcpdump  984684 Oct 16 21:43 /tmp/ring.pcap0
-rw-r--r-- 1 tcpdump tcpdump 1000315 Oct 16 21:43 /tmp/ring.pcap1
-rw-r--r-- 1 tcpdump tcpdump 1001055 Oct 16 21:43 /tmp/ring.pcap2
  • Line 2: -C 1: start a new file every 1,000,000 bytes. -W 3: keep three files, overwriting the oldest. Leave this running for days without filling the disk.
  • Lines 4–6: About 3.6 MB of traffic was captured, but only the newest ~3 MB is kept. When the problem recurs, stop it and the evidence is in the newest file.

Check your understanding

Which filter shows only TCP packets that start or end connections, including resets?

  • tcp port 80
  • tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) != 0
  • tcp[tcpflags] == tcp-syn
  • greater 1400