tcpdump Command Examples: Filters and Practical Packet Capture - 夜莺博客

tcpdump Command Examples: Filters and Practical Packet Capture

When an application works on one host but misbehaves on another, or a switch port shows errors that SNMP cannot explain, tcpdump is usually the fastest way to see what is actually on the wire. This guide collects the tcpdump commands that network and Linux engineers use every day: interface selection, host/port/protocol filters, packet capture files, and troubleshooting patterns, all with copy-paste syntax.

tcpdump Basics: Choosing the Capture Interface

tcpdump must run as root (or with CAP_NET_RAW) and the first decision is always which interface to listen on. List interfaces with tcpdump -D, then capture on one:

sudo tcpdump -i eth0        # specific interface
sudo tcpdump -i any         # all interfaces (good for VPN/tunnel debugging)
sudo tcpdump -D             # list available interfaces

Always add -n (no DNS resolution) and -nn (no port-name resolution) in production: name resolution makes output slow and hides numeric truth. For noisy links, bound the capture with -c N or a timeout with -G.

One subtlety catches people out on the first day: -i any uses the Linux cooked-capture (SLL) pseudo-interface, which aggregates packets from every interface but reports a synthetic link-layer header. It is the right choice when you do not yet know which interface carries the traffic, and the wrong choice when you need real Ethernet headers for MAC-level analysis. For loopback debugging, capture on lo explicitly — traffic between two local processes never appears on eth0, and -i any will show it but with the cooked header.

Filtering by Host, Port and Protocol

Capture filters use Berkeley Packet Filter (BPF) syntax and are evaluated by the kernel, so they are extremely fast. The core vocabulary:

sudo tcpdump host 192.168.1.10              # traffic to/from one host
sudo tcpdump src host 192.168.1.10          # only from that source
sudo tcpdump dst host 192.168.1.10          # only to that destination
sudo tcpdump port 22                        # SSH traffic
sudo tcpdump src port 443                   # from source port 443
sudo tcpdump tcp                            # TCP only
sudo tcpdump udp                            # UDP only
sudo tcpdump icmp                           # ICMP (ping) traffic
sudo tcpdump arp                            # ARP traffic
sudo tcpdump port 53                        # DNS queries/responses
sudo tcpdump vlan 100                       # frames tagged for VLAN 100

Two more filters earn their place in the toolkit. portrange 5060-5070 matches a range of ports, which is handy for SIP and other multi-port protocols, and net 10.0.0.0/22 matches a supernet rather than a single subnet. Both avoid the trap of writing a chain of or clauses for adjacent ranges.

sudo tcpdump 'portrange 5060-5070'          # SIP signalling range
sudo tcpdump 'net 10.0.0.0/22'              # matches 10.0.0.0 - 10.0.3.255

Combining Filters with Boolean Operators

Real problems need compound expressions. Quote them so the shell does not split them, and use and/or/not:

sudo tcpdump 'tcp and port 80'                        # HTTP over TCP
sudo tcpdump 'host 10.0.0.5 and port 22'              # SSH for one host
sudo tcpdump 'port 80 or port 443'                    # web traffic
sudo tcpdump 'net 192.168.1.0/24 and not port 22'     # subnet, minus SSH
sudo tcpdump 'tcp[13] & 2 != 0'                       # SYN packets only
sudo tcpdump 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'  # new connections

BPF operators bind tighter than you might expect, so brackets and quotes are not optional. When an expression has several or clauses mixed with and, parenthesise the or group explicitly — 'udp and (port 53 or port 123)' is unambiguous, while the same expression without brackets can silently match more than you intended.

Reading tcpdump Output Line by Line

Before filters, get comfortable with the output format, because most “tcpdump is not working” tickets are really “I did not recognise what I was looking at”. A single line contains six fields:

14:22:01.918273 IP 10.0.0.5.49312 > 10.0.0.9.443: Flags [S], seq 123456789, win 64240, options [mss 1460,sackOK,TS val 1001 ecr 0,nop,wscale 7], length 0
  • Timestamp — 14:22:01.918273. Add -t to drop it, -tttt for a UNIX epoch timestamp that is easier to correlate with logs.
  • Protocol — IP, IP6, ARP, STP. Anything unexpected here is a finding in itself.
  • Source and destination — 10.0.0.5.49312 > 10.0.0.9.443, port attached to the address with a dot. That the source port is a high ephemeral number and the destination port is a well-known one tells you the direction of the flow.
  • Flags — [S] SYN, [S.] SYN-ACK, [.] ACK, [P.] PSH-ACK, [F.] FIN-ACK, [R] RST. A handshake is S, then S., then .; nothing else means the connection is established.
  • Sequence and window — seq and win. Add -S to print absolute sequence numbers instead of relative ones when you are comparing captures.
  • Length — length 0. A SYN carries no payload, so zero length is expected; a length 0 on a data packet usually indicates a truncated capture, which points at the snaplen.

Controlling Output Format and Verbosity

The default one-line summary is not always enough. These flags change what tcpdump prints without changing what it captures:

sudo tcpdump -i eth0 -nn -v 'port 22'      # verbose: TTL, TOS, options
sudo tcpdump -i eth0 -nn -vv 'port 22'     # very verbose: checksums, window scaling
sudo tcpdump -i eth0 -A 'port 80'          # ASCII payload (HTTP, SMTP, plain text)
sudo tcpdump -i eth0 -X 'port 80'          # hex + ASCII
sudo tcpdump -i eth0 -XX 'port 80'         # hex + ASCII with the link-layer header
sudo tcpdump -i eth0 -e 'arp'              # include Ethernet MAC addresses
sudo tcpdump -i eth0 -q 'port 80'          # quiet: less protocol detail, more lines

For text protocols, -A is the quickest way to confirm whether an HTTP request is being sent at all, and -e is essential when the question is about L2 forwarding — which MAC the frame came from and which it was addressed to. Pair -e with -c to keep the output readable.

Saving and Reading Capture Files

When a problem needs analysis after the fact (or a ticket needs evidence), write the capture to a pcap file with -w and inspect it later:

sudo tcpdump -i eth0 -w /tmp/capture.pcap 'port 443'
sudo tcpdump -r /tmp/capture.pcap | head -20        # read back, text
sudo tcpdump -r /tmp/capture.pcap -n -c 100          # first 100 packets

pcap files open directly in Wireshark, which is useful when you need to reassemble streams or follow TCP conversations; see our guide on Wireshark capture vs display filters to translate BPF knowledge into Wireshark syntax.

When you capture to a file, remember to raise the snaplen. Older tcpdump defaults truncated packets to 96 bytes, which is enough for headers and useless for payloads, so pass -s 0 (or a large value) to store the full frame:

sudo tcpdump -i eth0 -s 0 -w /tmp/full.pcap 'host 10.0.0.5'

Capture Performance: Buffers, Snaplen and Rotation

On a busy interface, tcpdump can itself become the bottleneck. The default socket buffer is small relative to modern link speeds, and when it overflows the kernel silently drops packets — tcpdump will report the drop count in the “packets dropped by kernel” line when you stop it. Two options mitigate this without changing the filter:

sudo tcpdump -i eth0 -s 0 -B 32768 -w /tmp/big.pcap 'port 443'     # 32 MiB buffer
sudo tcpdump -i eth0 -w /tmp/rot.pcap -G 300 -W 12 -z gzip 'not port 22'
  • -B 32768 raises the capture buffer to 32 MiB. On 10 GbE and above, this is the difference between a clean capture and a soup of gaps.
  • -G 300 -W 12 rotates the output file every 300 seconds and keeps 12 files — an hour of rolling capture with a bounded footprint.
  • -z gzip compresses each file as it is closed, which matters when the capture will be attached to a ticket and uploaded over a slow link.
  • -s 0 stores the whole frame; reduce the snaplen to 128 if you only care about headers and want to save disk at line rate.

Permissions and Capabilities

Running tcpdump as root is convenient but unnecessary. Granting the binary the capability to open raw sockets lets an unprivileged user capture without full root:

sudo setcap cap_net_raw,cap_net_admin=eip $(which tcpdump)
getcap $(which tcpdump)

This is the standard hardening step on production hosts. Note that the capability is lost whenever the tcpdump package is upgraded, so re-apply it as part of your package-update runbook.

Practical Troubleshooting Recipes

  • No packets appear? Verify the interface with -D; try -i any. On Linux, tcpdump does not see traffic between local processes on the loopback unless you capture on lo.
  • Output too slow: hostnames cause DNS lookups per packet - add -n.
  • Permission denied: run with sudo or grant the CAP_NET_RAW capability.
  • Packets truncated: add -s 0 to capture full frames (older tcpdump versions default to 262144 or 96 bytes).
  • Watch retransmissions: sudo tcpdump -i eth0 'tcp[13] & 4 != 0' isolates RST, and tcp[13] & 16 != 0 isolates ACK-heavy retransmit patterns - combine with -S for absolute sequence numbers.
  • Inspect payload: -A prints ASCII payload, -X/-XX prints hex + ASCII dumps.

Two protocol-specific recipes are worth memorising because they answer the two most common calls. To confirm whether a client is even reaching a DHCP server, filter on the server ports and look for the four-message exchange:

sudo tcpdump -i eth0 -nn -e 'udp and (port 67 or port 68)'      # DHCP
sudo tcpdump -i eth0 -nn 'udp port 53'                          # DNS
sudo tcpdump -i eth0 -nn 'tcp port 443 and tcp[13] & 2 != 0'    # new TLS connections

If a DNS query goes out and no response returns, the problem is upstream of the client; if the query never leaves, the resolver configuration on the host is at fault. Similarly, if the SYN for a TLS connection is sent but no SYN-ACK returns, you are looking at routing, a firewall, or an ACL rather than anything in the application. For the wider diagnostic workflow around packet loss and latency, our guide to using mtr to diagnose packet loss and latency complements what you see here, and for retransmission analysis in a GUI the article on telling retransmissions apart from out-of-order segments is the natural next step.

Common Errors and Their Causes

  • tcpdump: eth0: You don't have permission to capture on that device — the user lacks CAP_NET_RAW. Use sudo or apply the capability shown above.
  • tcpdump: syntax error — the BPF expression is malformed, usually from an unescaped shell character or a missing bracket. Put the whole filter in single quotes.
  • Packets have bad checksums — on many NICs, checksum offload means the capture sees an incomplete checksum that the hardware would have computed. This is cosmetic, and disabling offload with ethtool makes it disappear; you can read more in our ethtool diagnostics guide.
  • Only one direction of a flow is captured — the capture point is not on the path for the return traffic. Move the capture to a mirror port, or use SPAN/RSPAN/ERSPAN mirroring to see both directions.
  • Captures look empty on a container host — the traffic may live inside a network namespace. Use ss, netstat and namespace-aware capture techniques to enter the right namespace before capturing.

When to Move from tcpdump to Wireshark or tshark

tcpdump is unbeatable for a quick look, a tight filter and a file you can hand to someone else. It is the wrong tool when you need to reassemble a stream, decode an application protocol field by field, follow a TCP conversation across hundreds of packets, or compare two captures for latency. At that point, move the pcap into Wireshark, or use tshark when you want Wireshark’s dissectors on a headless server:

tshark -r /tmp/capture.pcap -Y 'tcp.analysis.retransmission' -T fields -e ip.src -e ip.dst
tshark -r /tmp/capture.pcap -Y 'http.request' -T fields -e http.host -e http.request.uri

The division of labour is straightforward: capture with tcpdump because it is small, scriptable and available everywhere, then analyse with Wireshark because its dissectors understand the protocols. On network equipment the same pattern applies — a switch or router can capture on its own interfaces, which is covered in our walkthrough of Junos monitor traffic capture and, for Cisco platforms, IOS-XE embedded packet capture.

Summary

tcpdump rewards a small amount of study. Learn -i, -n, -nn and -c for control; learn host/port/protocol filters and Boolean operators for precision; learn -w, -r, -s 0 and -B for capture hygiene; and learn to read the flags, sequence numbers and lengths in the output so you can tell a handshake from a reset at a glance. With those in hand, most “the network is slow” or “the application cannot connect” tickets can be answered in a couple of minutes without touching a GUI.

tcpdump pairs well with the rest of the Linux network toolbox: use ethtool to check driver-level counters first, capture with tcpdump to confirm what crosses the NIC, and validate throughput with iperf3 when the question is performance rather than correctness. For a filter-first reference of the same tool, see our BPF filter cheatsheet for packet capture.

原文链接:https://linuxize.com/cheatsheet/tcpdump