Wireshark Capture Filters vs Display Filters Explained - 夜莺博客

Wireshark Capture Filters vs Display Filters Explained

Wireshark has two filter languages that beginners constantly mix up: capture filters, which are Berkeley Packet Filter (BPF) expressions evaluated in the kernel before a packet is even stored, and display filters, which hide already-captured packets inside Wireshark's dissector engine. Getting them backwards causes either enormous capture files or the confusing situation where "no packets match" even though traffic exists. This article explains both, with examples and the workflow that uses each where it belongs.

The confusion is understandable, because the two languages look superficially alike — both use the words and, or and not — yet they execute in completely different places, accept completely different syntax, and answer completely different questions. A capture filter answers "which packets am I willing to keep?" A display filter answers "which of the packets I kept do I want to look at right now?" Once that distinction clicks, the rest is vocabulary.

Why Two Filter Languages Exist

Wireshark handles packets in two stages. First, a capture driver (libpcap on Linux and macOS, Npcap on Windows) asks the kernel or the NIC driver for copies of frames. Second, Wireshark's dissectors parse those frames into protocol trees and hand them to the packet list. A capture filter is installed at stage one; a display filter works at stage two.

Because the capture stage sits closest to the wire, it is the only place where you can genuinely reduce load. If you are capturing on a 10 Gbps uplink that mostly carries storage replication you do not care about, a capture filter that keeps only one host's traffic means the kernel copies a tiny fraction of frames, your SSD fills slowly, and Wireshark has far less to dissect. A display filter applied after the fact cannot give any of that back — the frames are already on disk and already parsed.

The trade-off is that the capture stage is irreversible: whatever a capture filter drops is gone. There is no undo for a BPF expression, and there is no "capture filter history" that lets you recover a frame you excluded. That single fact drives most of the practical advice below — capture broadly enough that you do not lose evidence, then use display filters for the precision work.

Capture Filters: BPF Before the Disk

Capture filters run in the kernel via libpcap/Npcap. Packets that do not match never enter Wireshark at all, so they save disk space and CPU on busy links — but the filter cannot be changed mid-capture and anything filtered out is gone forever. Syntax is the classic tcpdump/BPF style:

host 192.168.1.100              # to/from one host
net 10.0.0.0/24                 # whole subnet
tcp port 80 or tcp port 443     # HTTP/HTTPS
not port 22                     # everything except SSH
src host 10.0.0.5               # source only
icmp or arp                     # specific protocols

How BPF Grammar Actually Works

Every BPF primitive is built from up to three qualifiers followed by an identifier:

  • Type — what the identifier names: host, net, port, portrange.
  • Direction — which way the traffic flows: src, dst, src or dst (the default), or src and dst.
  • Protocol — restrict to a protocol layer: ether, ip, ip6, arp, tcp, udp, icmp.

When you omit the type, BPF assumes host; when you omit the direction it assumes src or dst; when you omit the protocol it matches every protocol. That implicit behaviour is why port 53 quietly means "TCP or UDP port 53 in either direction", and why host 10.0.0.1 matches both an IP address and (if the name resolves) anything else that looks like it. Being explicit costs nothing and removes doubt:

tcp dst portrange 1-1023        # TCP to a privileged port
udp src port 53                 # DNS responses only
ip proto 47                     # GRE by protocol number
ether host 00:11:22:33:44:55    # one MAC address
vlan 100                        # 802.1Q tag 100
greater 1400 and less 9000      # frame length window
tcp[13] & 0x02 != 0             # TCP SYN flag using byte offset

The last two lines show BPF's low-level power: you can match on frame length with greater/less, and on raw header bytes with the proto[offset:size] syntax. tcp[13] & 0x02 != 0 inspects byte 13 of the TCP header and masks out the SYN bit — the older, tcpdump-native way of saying "show me SYNs". It is powerful but brittle: hard-coded offsets break the moment you meet an IPv6 or tunneled packet, and a display filter like tcp.flags.syn == 1 is far more readable for the same job.

Display Filters: DFL After the Capture

Display filters use Wireshark's Display Filter Language: protocol-aware, rich in operators, applied after capture to hide (never delete) packets. You can change them on the fly while the capture runs:

ip.addr == 192.168.1.1
tcp.port == 443
http.request.method == "GET"
tcp.analysis.retransmission        # all retransmissions
dns.qry.name contains "google"
frame.len > 1400                   # jumbo-sized frames
http.response.code >= 400          # 4xx and 5xx
tcp.flags == 0x002                 # pure SYN packets

Operators include ==/eq, !=/ne, >/gt, contains, matches (regex) and the logical and/or/not.

Display Filter Fields, Functions and Shortcuts

The real strength of the display filter language is that it knows protocol structure. Instead of remembering byte offsets, you name the field. Every field can be typed into the filter bar, and Wireshark autocompletes both field names and valid values as you type — the single fastest way to learn the vocabulary is to click a field in the packet detail pane and watch it appear in the status bar at the bottom.

ip.src == 10.1.1.0/24 and ip.dst == 10.2.2.0/24   # subnet-to-subnet
tcp.srcport == 22 and tcp.flags.ack == 1          # SSH ACKs only
eth.addr == 00:1c:73:aa:bb:cc                     # any frame with that MAC
http.host == "api.example.com"                    # HTTP virtual host
tls.handshake.type == 1                           # TLS Client Hello
dns.flags.rcode != 0                              # DNS errors only
frame.time_delta_displayed > 0.5                  # gaps over 500 ms
tcp.stream eq 7                                   # one conversation
not (arp or icmp or stp)                          # noisy-chatter cleanup
tcp.len > 0 and tcp.analysis.flags                # data-bearing problems

Several conveniences are worth memorising. Comparison with == on a string field accepts either quotes or bare values. The in operator tests membership: tcp.port in {80, 443, 8080}. Byte-field slices let you test part of a field: ip.src[0:2] == 0a:0b. Regular expressions use matches, e.g. http.user_agent matches "(?i)curl", though regexes are slow over large captures and should be a last resort.

Three display-filter features save even more time: Filter buttons (the Bookmarks icon) store named expressions for one-click reuse; Apply as Filter and Prepare as Filter in the right-click context menu build filters from a selected packet without any typing; and colouring rules are display filters with colours attached, so the same syntax that finds retransmissions can paint them red automatically as you scroll.

Key Differences at a Glance

  • When: capture filters are set before starting; display filters apply any time.
  • Performance: capture filters are very efficient (kernel-level, saves disk); display filters consume CPU/RAM as they scan the packet list.
  • Syntax: BPF (host 1.2.3.4) vs DFL (ip.addr == 1.2.3.4).
  • Data loss: capture filters discard non-matching packets permanently; display filters only hide them.
  • Reversible: a display filter can be edited, cleared or combined indefinitely; a capture filter is locked in for the life of the capture.
  • Awareness: BPF sees the wire and knows nothing about protocols beyond basic header offsets; the display engine parses every protocol Wireshark can dissect, including reassembled application data.
  • Portability: BPF is portable to tcpdump, tshark, ngrep and hardware capture tools; display filter syntax is Wireshark-only (tshark supports it, but nothing else does).

Performance, Ring Buffers and File Size

On a fast link the capture stage is where capture quality is won or lost, and BPF is not the only lever. Three settings in Capture > Options matter as much:

  • Snaplen — capture only the first N bytes of each frame. Truncating to 96 bytes keeps headers while discarding payload, which is ideal for analysing retransmissions and TCP windows but destroys any chance of reading HTTP bodies or TLS handshakes.
  • Ring buffer — write to a rotating set of files with a size and count limit, so an unattended capture cannot fill the disk. A "1 GB × 10 files" ring covering 10 GB of recent traffic is often more useful than a single unbounded file.
  • Output format — switch to pcapng for protocol metadata and comments, or keep pcap for maximum tool compatibility.

For unattended captures, run dumpcap (the same capture engine Wireshark uses, but without the GUI) rather than the full Wireshark binary. It uses far less memory and can be supervised by systemd with automatic restart, so a long-running capture survives a session dying.

The Recommended Workflow

Use a broad capture filter to keep the file manageable, then slice with precise display filters during analysis. Investigating a web server problem: capture with host 203.0.113.42 and (tcp port 80 or tcp port 443), then display-filter to http.response.code >= 500 to find server errors, then tcp.analysis.retransmission to see if the network is dropping segments. The capture-side BPF grammar is identical to tcpdump, so everything in our tcpdump BPF filter guide applies; for capture on AOS-CX switches see Aruba AOS-CX packet capture.

Common Mistakes and How to Avoid Them

Almost every "Wireshark shows nothing" report traces back to one of a handful of errors:

  • Using display syntax in the capture field. ip.addr == 1.2.3.4 is not valid BPF; the correct capture form is host 1.2.3.4. Wireshark refuses to start the capture, but the error message is easy to miss.
  • Using capture syntax in the display field. host 1.2.3.4 in the display bar turns red because the field name "host" does not exist. The display equivalent is ip.addr == 1.2.3.4.
  • Filtering on a port that changes after NAT. A capture taken inside a NAT boundary sees translated addresses and ports, so a filter written for the outside world matches nothing.
  • Forgetting VLAN tags. On a trunked capture a filter of host 10.0.0.1 still works (BPF matches the inner IP), but a display filter of ip.addr == 10.0.0.1 fails on some builds until you account for the 802.1Q tag — use vlan and ip.addr == 10.0.0.1.
  • Capturing on the wrong interface. A wireless NIC in monitor mode, a management interface, and a production data interface are three different capture points, and each sees a different subset of traffic.

Practical Scenarios: Latency, Loss and VoIP

Slow application. Capture broadly on the server, then filter tcp.stream eq N for the one conversation, and add tcp.time_delta > 0.2 to surface the stalls. Cross-check with tcp.analysis.retransmission and tcp.analysis.zero_window: retransmissions point at loss on the path, while a zero window points at a receiver that cannot keep up.

Packet loss on an uplink. Capture with host 203.0.113.42, then display tcp.analysis.lost_segment or tcp.analysis.retransmission. If retransmissions cluster on one source but not the destination, the loss is usually downstream of your capture point. Our walkthrough of retransmission versus out-of-order packets covers how to tell the two apart, because they look similar in a packet list but mean very different things.

VoIP call quality. SIP signalling is a display-filter job (sip or rtp), then Telephony > RTP > Show All Streams produces jitter, loss and mean-opinion-score statistics per call. If the same traffic must also be mirrored to a second collector, see our SPAN, RSPAN and ERSPAN guide for how mirroring affects what the capture actually contains.

Quick Reference Checklist

  • Decide before capturing: which hosts and ports must be in the file?
  • Write the BPF filter with explicit type, direction and protocol qualifiers.
  • Set a snaplen you can live with and a ring buffer you cannot overflow.
  • Capture on the interface closest to the problem, not the most convenient one.
  • Analyse with display filters; save the useful ones as filter buttons.
  • Add colouring rules for retransmissions, resets and errors so problems paint themselves.
  • Remember that display filters never recover packets a capture filter discarded.

原文链接:https://wiki.wireshark.org/CaptureFilters