3. 显示过滤器:语法、协议、字段与逻辑组合

抓包只是第一步,真正要命的是从几千个包里找到你关心的那几条。我见过不少同事,抓包半小时,找包两小时——其实用对显示过滤器,几秒钟就能搞定。

显示过滤器跟捕获过滤器不一样。捕获过滤器是「抓不抓」,显示过滤器是「显不显」。说白了,前者在门口拦人,后者在屋里点名。今天我们就把它彻底讲透。

核心原则:显示过滤器只影响显示,不影响已捕获的数据包。你随时可以改、可以删、可以叠加,不会丢包。

3.1 显示过滤器语法基础

Wireshark 的显示过滤器语法,本质上是一套表达式语言。它的基本结构是:

协议.字段 运算符 值

举个例子:

ip.src == 192.168.1.1

意思就是「源 IP 等于 192.168.1.1 的所有包」。嗯,就这么直白。

运算符有几种:

运算符 含义 示例
== 等于 ip.src == 10.0.0.1
!= 不等于 ip.src != 10.0.0.1
> / < 大于 / 小于 frame.len > 1500
contains 包含子串 http.host contains "baidu"
matches 正则匹配 http.user_agent matches "Chrome"
in 属于集合 ip.src in {10.0.0.0/8, 172.16.0.0/12}

个人习惯:我几乎不用 matches,除非真的需要正则。因为 contains 已经够用了,而且性能更好。有一次排查一个慢速攻击,用 matches 把 Wireshark 卡死了——从那以后我就记住了这个教训。

3.2 协议过滤:最常用的操作

协议过滤是最简单的。直接输入协议名就行:

http
dns
tcp
arp
icmp
tls

Wireshark 会自动匹配所有包含该协议的数据包。注意,这里说的是「包含」——比如一个 HTTP 包,它同时也包含 TCP、IP、以太网。所以 tcp 会显示所有 TCP 包,包括 HTTP 的。

如果你想只看「纯」某种协议的包,可以用 tcp.port 或 udp.port 来缩小范围。比如:

tcp.port == 443

这跟 tls 不一样。前者只看端口 443 的 TCP 包,后者只看 TLS 协议包——即使它跑在非标准端口上。

我曾经踩过的坑:有一次排查一个 HTTPS 问题,我用了 tcp.port == 443,结果发现服务器把 TLS 跑在 8443 端口上。后来改用 tls 才抓到。所以,协议名过滤比端口过滤更可靠——前提是你知道它用了什么协议。

3.3 字段过滤:精准定位

协议过滤只能告诉你「这是什么协议」,字段过滤才能告诉你「这个包有什么特征」。

字段过滤的格式是:

协议.字段名 运算符 值

比如:

ip.src == 192.168.1.1
tcp.dstport == 80
http.request.method == "GET"
dns.qry.name contains "google"

怎么知道有哪些字段?两个方法:

  1. 在包详情里右键,选择「作为过滤器应用」→「选中」
  2. 在过滤器输入框里按 Tab,会自动弹出字段提示

我个人更推荐第一种。因为你在看包的时候,直接右键就能生成过滤器,省得记字段名。尤其是那些嵌套很深的字段,比如 tls.handshake.extensions_server_name——你让我背我也背不下来。

3.4 逻辑组合:and、or、not

单个条件往往不够。你需要把多个条件组合起来。Wireshark 支持三种逻辑运算符:

运算符 含义 示例
and 或 && 与 ip.src == 10.0.0.1 and tcp.port == 80
or 或 || 或 ip.src == 10.0.0.1 or ip.dst == 10.0.0.1
not 或 ! 非 not arp

举个例子,我想看「从 192.168.1.1 发出的 HTTP 请求,但不包括图片下载」:

ip.src == 192.168.1.1 and http.request and not (http.request.uri contains ".jpg" or http.request.uri contains ".png")

注意括号的使用。逻辑优先级是 not > and > or,但为了可读性,我建议你永远加括号。你想想看,三个月后你自己回来看这段过滤器,没括号你还能看懂吗?

避坑指南:我曾经在排查一个 DNS 劫持问题时,写了一个很长的过滤器:dns and not (ip.src == 8.8.8.8 or ip.src == 114.114.114.114)。结果发现漏掉了好多包——因为 DNS 响应可能来自多个服务器。后来我改成 dns and not ip.src in {8.8.8.8, 114.114.114.114},用 in 运算符,简洁多了。

3.5 表达式构建:从简单到复杂

实际工作中,你很少只用一两个条件。我来分享几个我常用的「组合拳」:

场景一:排查 TCP 重传

tcp.analysis.retransmission or tcp.analysis.fast_retransmission

这个过滤器会显示所有重传包。配合 ip.addr == 目标IP 就能定位到具体设备。

场景二:看某个 IP 的所有流量

ip.addr == 10.0.0.5

注意,ip.addr 同时匹配源和目标。如果你想区分方向,用 ip.src 和 ip.dst。

场景三:抓取特定应用的 HTTP 请求

http.user_agent contains "curl" or http.user_agent contains "Postman"

这个我在调试 API 接口时经常用。能快速区分是浏览器请求还是脚本请求。

场景四:排除广播和组播

not (eth.dst == ff:ff:ff:ff:ff:ff or eth.dst[0] & 1 == 1)

嗯,这个稍微复杂一点。但如果你在分析一个高流量网络,排除广播包能让你清净不少。

3.6 知识体系总览

下面这张图总结了显示过滤器的核心结构。你可以把它当作一个快速参考:

显示过滤器知识体系 显示过滤器 协议过滤 字段过滤 逻辑组合 表达式构建 http / dns / tcp ip.src / tcp.port and / or / not 组合 + 括号 == / != / > / < contains / matches 括号优先级 in 集合运算符 💡 核心公式 协议.字段 运算符 值 [and/or/not 协议.字段 运算符 值] 🔍 快速获取字段名 方法1:在包详情区右键 → 「作为过滤器应用」 方法2:在过滤器输入框按 Tab 键自动补全

3.7 实用技巧与避坑

最后,分享几个我这些年积累的小技巧:

  • 用颜色标记过滤器:Wireshark 允许你为不同的过滤器设置颜色。我习惯把「错误」标红、「重传」标黄、「正常」标绿。一眼就能看出问题。
  • 保存常用过滤器:在过滤器输入框旁边有个「保存」按钮。把常用的表达式存起来,下次直接点。我存了大概 20 个,覆盖了 90% 的日常场景。
  • 用「!」排除干扰:如果你在分析一个高流量网络,先排除广播、多播、STP 等协议。比如 !stp and !arp and !(eth.dst == ff:ff:ff:ff:ff:ff)。
  • 注意大小写:协议名和字段名不区分大小写,但字符串值区分。比如 http.request.method == "get" 和 "GET" 不一样。

重要提醒:显示过滤器不会减少捕获的数据量。如果你抓了一个 1GB 的 pcap 文件,用过滤器只是「隐藏」了不匹配的包,文件还是那么大。如果你需要缩小文件体积,请用捕获过滤器或者在导出时使用「导出指定包」功能。

好了,显示过滤器的核心内容就这些。你只要记住「协议.字段 运算符 值」这个公式,再加上 and/or/not 组合,就能应对 95% 的场景。剩下的 5%,等你遇到具体问题时,再查字段列表也来得及。