tcpdump Cheatsheet
Host and Network Filters
Use this tcpdump reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Single hosts
host is the default type qualifier, so host is often omitted, but write
it anyway for readability.
# Either direction sudo tcpdump -i eth0 -nn host 10.0.0.5 # One direction only sudo tcpdump -i eth0 -nn src host 10.0.0.5 sudo tcpdump -i eth0 -nn dst host 10.0.0.5 # Force one address family sudo tcpdump -i eth0 -nn ip host 10.0.0.5 sudo tcpdump -i eth0 -nn ip6 host 2001:db8::1
| Filter | Matches |
|---|---|
host 10.0.0.5 | IPv4, IPv6, and ARP/RARP traffic for that address |
ip host 10.0.0.5 | IPv4 only, no ARP |
src host 10.0.0.5 | Only where it is the source |
dst host 10.0.0.5 | Only where it is the destination |
host example.com | Resolved once at compile time, may expand to several |
A hostname in a filter is looked up when the filter compiles, not per
packet, so it costs nothing at capture time. But if the name has four A
records, the filter silently becomes a four-way or.
One host pair, both ways
The single most useful filter in practice. Two forms, and they mean different things.
# Any traffic touching both, in either direction sudo tcpdump -i eth0 -nn 'host 10.0.0.5 and host 10.0.0.9' # Strictly one direction of that pair sudo tcpdump -i eth0 -nn 'src host 10.0.0.5 and dst host 10.0.0.9'
host A and host B reads as "A is one endpoint and B is the other", which
is exactly the conversation view you want. Adding src/dst narrows it to
half the conversation, which halves what you can diagnose.
Networks and subnets
sudo tcpdump -i eth0 -nn net 10.0.0.0/8 sudo tcpdump -i eth0 -nn 'src net 172.16.0.0 mask 255.240.0.0' sudo tcpdump -i eth0 -nn dst net 192.168.1.0/24 sudo tcpdump -i eth0 -nn ip6 net 2001:db8::/32
| Form | Meaning |
|---|---|
net 10.0.0.0/8 | CIDR, the form to use |
net 10.0.0.0 mask 255.0.0.0 | Explicit netmask, equivalent |
net 10.0.0 | Classful shorthand, expands to 10.0.0.0/24 |
net 10 | Classful shorthand, expands to 10.0.0.0/8 |
Avoid the classful shorthand. net 128.3 becoming a /16 while
net 192.168.1 becomes a /24 is a real source of wrong captures. Write
CIDR.
Excluding your own SSH session
The classic mistake. You SSH in, run tcpdump, and every packet tcpdump prints generates more SSH traffic, which tcpdump prints, forever.
# Blunt but usually fine sudo tcpdump -i eth0 -nn not port 22 # Precise, keeps other SSH traffic visible sudo tcpdump -i eth0 -nn 'not (host 203.0.113.9 and port 22)' # Derive your client address from the environment sudo tcpdump -i eth0 -nn \ "not (host ${SSH_CLIENT%% *} and port ${SSH_CLIENT##* })"
$SSH_CLIENT is clientip clientport serverport, so ${SSH_CLIENT%% *}
is the client address and ${SSH_CLIENT##* } is the local SSH port. Note
the double quotes here, because the shell has to expand those.
Layer 2, MACs, broadcast, multicast
sudo tcpdump -i eth0 -nn -e ether host 00:11:22:33:44:55 sudo tcpdump -i eth0 -nn -e ether src 00:11:22:33:44:55 sudo tcpdump -i eth0 -nn -e ether broadcast sudo tcpdump -i eth0 -nn arp or icmp6
| Filter | Matches |
|---|---|
ether host <mac> | Either MAC field |
ether broadcast | ff:ff:ff:ff:ff:ff destination |
ether multicast | Multicast bit set in the destination MAC |
ip broadcast | IPv4 broadcast destination |
ip multicast | 224.0.0.0/4 destination |
ether proto \arp | ARP by EtherType, backslash is required |
vlan 100 | 802.1Q tag 100 |
mpls 1000 | MPLS label 1000 |
Add -e whenever you filter on MACs, otherwise the addresses you are
matching on are not printed and you cannot check your own filter.
Finding a rogue DHCP server or an ARP conflict:
# Every ARP on the segment, with MACs sudo tcpdump -i eth0 -nn -e arp # DHCP offers, which reveal the server MAC and address sudo tcpdump -i eth0 -nn -e -v 'udp port 67 or udp port 68'