4. 显示过滤器:语法、运算符与实战技巧
抓包只是第一步,真正有价值的是从海量数据里捞出你想要的流量。显示过滤器就是干这个的。它不像捕获过滤器那样在抓包前就做取舍,而是等所有数据都抓下来之后,你再像用 SQL 查数据库一样,把关心的包筛出来。
我个人习惯把显示过滤器叫做 Wireshark 的「灵魂功能」。你想想看,一个 pcap 文件里可能有几十万甚至上百万个包,没有过滤器,你只能对着屏幕发呆。
核心认知:显示过滤器只影响「显示」,不影响原始抓包数据。你随时可以清空过滤器,所有包都会回来。这一点和捕获过滤器有本质区别。
4.1 显示过滤器语法基础
显示过滤器的语法其实不复杂,核心就一句话:「协议.字段 运算符 值」。比如:
ip.src == 192.168.1.1
tcp.port == 80
http.request.method == "GET"
每个表达式由三部分组成:
- 协议:小写,如 ip、tcp、udp、http、dns
- 字段:点号连接,如 src、dst、port、request.method
- 值:IP 地址、端口号、字符串(加引号)、十六进制等
我记得刚学的时候,总记不住字段名。后来发现一个窍门:在 Wireshark 里点开一个包,展开协议树,右键点击你想过滤的字段,选择「作为过滤器应用」→「选中」。Wireshark 会自动帮你生成正确的语法。这招我到现在还在用。
小技巧:在过滤器输入框里打字时,Wireshark 会自动弹出字段补全提示。输入 tcp. 就会列出所有 tcp 相关字段,省得你死记硬背。
4.2 比较运算符
显示过滤器支持多种比较方式,我整理了一张常用表:
| 运算符 | 含义 | 示例 |
|---|---|---|
== |
等于 | ip.src == 10.0.0.1 |
!= |
不等于 | ip.src != 10.0.0.1 |
> < |
大于 / 小于 | frame.len > 1500 |
>= <= |
大于等于 / 小于等于 | tcp.window_size >= 65535 |
contains |
包含子串 | http.host contains "baidu" |
matches |
正则匹配 | http.request.uri matches "\.php$" |
in |
属于集合 | tcp.port in {80 443 8080} |
这里有个坑我要提醒你:字符串比较要加双引号,数字和 IP 不用。我曾经见过有人写 http.request.method == GET(没加引号),结果过滤器死活不生效,排查了半天才发现是语法问题。
避坑指南:我曾经在排查一个 HTTP 403 问题时,用 http.response.code == 403 死活筛不出包。后来发现响应码字段其实是 http.response.code,但有些版本里它叫 http.response.status_code。遇到这种情况,右键点开协议树看字段名最靠谱。
4.3 逻辑运算符
单个条件往往不够用,你需要把多个条件组合起来。逻辑运算符就是干这个的:
and(或&&):两个条件都满足or(或||):满足其中一个not(或!):取反():括号改变优先级
举个例子,我想看从 192.168.1.100 发往 10.0.0.1 的 HTTP 请求:
ip.src == 192.168.1.100 and ip.dst == 10.0.0.1 and http.request
或者排除掉 SSH 和 RDP 流量:
not (tcp.port == 22 or tcp.port == 3389)
我个人习惯用英文单词(and/or/not),因为更直观。但如果你喜欢符号(&&/||/!),也没问题,Wireshark 都支持。
4.4 常用过滤表达式
下面这些是我在日常工作中几乎每天都会用到的表达式,我按场景分了个类:
4.4.1 地址过滤
ip.addr == 192.168.1.1 # 只看某个 IP 的所有流量
ip.src == 192.168.1.0/24 # 只看某个网段的源地址
ip.dst == 10.0.0.1 # 只看目的地址
eth.addr == 00:1a:2b:3c:4d:5e # 按 MAC 地址过滤
4.4.2 端口与协议过滤
tcp.port == 443 # 只看 HTTPS
udp.port == 53 # 只看 DNS
tcp.port in {80 443 8080} # 多个端口
http # 只看 HTTP 协议(所有 HTTP 包)
dns # 只看 DNS 协议
4.4.3 应用层过滤
http.request.method == "POST" # 只看 POST 请求
http.response.code == 404 # 只看 404 响应
dns.qry.name contains "google" # DNS 查询中包含 google
tcp.flags.syn == 1 # 只看 SYN 包
tcp.flags.reset == 1 # 只看 RST 包
4.4.4 长度与时间过滤
frame.len > 1400 # 大包(可能含数据)
frame.len < 64 # 小包(可能为控制包)
tcp.analysis.retransmission # 只看重传包
tcp.analysis.fast_retransmission # 快速重传
tcp.analysis.duplicate_ack # 重复确认
实战经验:排查网络慢的问题时,我通常会先输入 tcp.analysis.retransmission or tcp.analysis.fast_retransmission。如果重传包占比超过 1%,基本可以断定网络有问题。这个经验值是我在好几个项目里验证过的。
4.5 过滤表达式保存与加载
有些过滤条件你可能会反复用到。比如每次排查 DNS 问题都要写 dns.flags.response == 0,每次都重新打字太麻烦了。Wireshark 提供了保存功能。
4.5.1 保存过滤器
- 在过滤器输入框旁边,点击那个「书签」图标(或者叫「过滤器管理」按钮)
- 选择「管理过滤器」
- 点击「新建」,输入名称和表达式
- 点击「确定」保存
保存之后,下次你点那个书签图标,就能直接选之前保存的过滤器了。我个人习惯按场景命名,比如「DNS 查询」「HTTP 4xx」「TCP 重传」这样,找起来方便。
4.5.2 加载与导入导出
Wireshark 的过滤器配置保存在 cfilters 和 dfilters 文件里(Windows 在 %APPDATA%\Wireshark\,Linux/Mac 在 ~/.config/wireshark/)。你可以直接复制这些文件到另一台机器上,实现过滤器的迁移。
我记得有一次帮同事排查问题,他那台机器上没配任何过滤器。我直接把我本地的 dfilters 文件发给他,覆盖之后重启 Wireshark,所有过滤器就都出现了。省得他一个个重新配。
注意:不同版本的 Wireshark 之间,过滤器文件格式可能略有差异。跨版本迁移时,建议先备份原文件。我曾经从 3.x 升级到 4.x 时,过滤器文件直接复制过去报错了,后来重新配了一遍才搞定。
4.6 知识体系总览
下面这张图把显示过滤器的核心知识点串起来了,你可以对照着回顾一下:
4.7 本章小结
显示过滤器是 Wireshark 里最常用的功能,没有之一。你只要记住「协议.字段 运算符 值」这个基本结构,再配合逻辑运算符组合条件,就能应对绝大多数场景。
我建议你平时多积累自己的过滤器库。遇到好用的表达式就保存下来,时间长了就是一笔宝贵的财富。下次排查问题时,直接调出来用,效率翻倍。