BPF Filters
Slice a giant capture down to the one host, port, or subnet you care about.
What you will learn
- -Write host, port, and net filters in BPF syntax
- -Combine primitives with and, or, and not
- -Filter a capture down to one conversation on the wire or from a pcap
A busy interface pushes thousands of a second. Reading all of them is hopeless. Berkeley Packet Filter syntax is the language that tells tcpdump (and Wireshark's capture side) exactly which packets to keep. Learn a handful of primitives and you can carve one conversation out of the flood.
The three primitives you use constantly
Every BPF filter is built from a few keywords. These are the ones that matter:
host 10.10.14.5keeps traffic to or from that one IP.port 80keeps traffic to or from that , either direction.net 10.10.14.0/24keeps traffic to or from anything in that .
Add a direction word to be specific: src host 10.10.14.23 is traffic from
that , dst port 22 is traffic to port 22. Without src or dst, BPF
matches both directions.
$sudo tcpdump -i eth0 -nn host 10.10.14.5$sudo tcpdump -i eth0 -nn dst port 22$sudo tcpdump -i eth0 -nn net 10.10.14.0/24The net primitive takes , so knowing your subnet math pays off
directly here. A /24 filter watches up to 254 hosts, a /29 just six.
- Network address
- 10.10.14.0
- Usable range
- 10.10.14.1 - 10.10.14.254
- Broadcast
- 10.10.14.255
- Subnet mask
- 255.255.255.0
- Wildcard
- 0.0.0.255
- Total / usable hosts
- 256 / 254
Combine them with logic
Primitives powerful when you glue them together with and, or, and not.
Wrap groups in escaped parentheses so the does not eat them.
$sudo tcpdump -i eth0 -nn host 10.10.14.5 and port 80$sudo tcpdump -i eth0 -nn port 80 or port 443$sudo tcpdump -i eth0 -nn not port 22$sudo tcpdump -i eth0 -nn 'host 10.10.14.5 and (port 80 or port 443)'That not port 22 trick is a daily habit. When you are SSHed into the box you
are sniffing, your own session floods the output. Filter it out and the real
traffic becomes readable.
Filter a saved pcap the same way
The exact same syntax works when reading a file back with -r, so you can
capture broadly and slice narrowly later.
$tcpdump -nn -r capture.pcap 'host 10.10.14.5 and port 21'Set your capture filter wide (a whole subnet, or no filter at all) so you never miss a packet, then apply tight BPF filters when reading the pcap back. A packet you filtered out at capture time is gone forever; one you keep can be sliced any way you want afterward.
Which filter captures all traffic to or from the 10.10.14.0/24 subnet?
Write a BPF filter that keeps only HTTP or HTTPS traffic to or from host 10.10.14.5. Just the filter expression, not the full command.
Combine a host primitive with an or-group of the two web ports, joined by and.