4. Wireshark 过滤表达式入门归纳总结
抓包不难,难的是从成千上万个包里找到你要的那几个。
我的经验是,刚入门的同事常常盯着满屏的绿色、蓝色数据包发愣——这跟大海捞针没区别。其实 Wireshark 提供了两套过滤器:捕获过滤器和显示过滤器。搞懂它们,你才算真正入了门。
4.1 两类过滤器的核心区别
先别急着背语法。我先问一个问题:你是想在抓包之前就丢掉不关心的流量,还是抓完包之后再用条件筛选?
前者叫捕获过滤器,后者叫显示过滤器。我在项目里见过不少人把两者混着用,结果要么漏包,要么机器卡死。咱们用一张表说清楚:
| 对比维度 | 捕获过滤器 | 显示过滤器 |
|---|---|---|
| 作用时机 | 抓包前,网卡一侧就开始过滤 | 抓包后,对已保存的包过滤显示 |
| 丢弃的包 | 直接丢弃,不可恢复 | 包仍在文件里,只是隐藏 |
| 语法风格 | 类 BPF (Berkeley Packet Filter) | 类 C 语言表达式 |
| 性能 | 高,适合高流量环境 | 中等,取决于文件大小 |
| 典型场景 | 抓 TLS 握手时排除其他流量 | 从已有文件里定位特定握手失败 |
4.2 显示过滤器的基本功
坦白讲,显示过滤器才是我们日常用得最多的。你只要在 Wireshark 顶部那个带绿色/红色背景的输入框里敲表达式,回车就能看到结果。
4.2.1 协议层过滤
最直接的写法:直接输协议名。
tls
http
dns
arp
注意,输入 tls 会显示所有携带 TLS 协议的数据包,但不限于握手包。如果你只想看握手包,可以加条件:
tls.handshake.type == 1 // Client Hello
tls.handshake.type == 2 // Server Hello
tls.handshake.type == 11 // Certificate
tls.handshake.type == 16 // Encrypted Extensions
4.2.2 IP 和端口过滤
这个太常用了。比如你想看某个服务器跟客户端的交互:
ip.addr == 192.168.1.100
ip.src == 10.0.0.1 && ip.dst == 10.0.0.2
tcp.port eq 443
udp.portrange 8000-8100
坑:ip.addr == 192.168.1.100 匹配源或目标任一地址。如果你只想要源地址,必须写 ip.src。我曾经因为这个写错,把服务器回包误认为客户端流量,排查了半天才发现。
4.2.3 组合条件与逻辑运算
Wireshark 支持 and、or、not、() 括号分组:
tls and ip.addr == 192.168.1.1
tcp.port == 443 or tcp.port == 80
not icmp
(tls.handshake.type == 1) and (tls.handshake.cipher_suites contains 0x1301)
这里 contains 操作符非常实用,能匹配字节序列或字符串。比如想找特定密码套件:
tls.handshake.cipher_suites contains 0x1301 // TLS_AES_128_GCM_SHA256
避坑指南:我曾经用 tls.handshake.cipher_suites == 0x1301 想找单个套件,结果没反应。为什么?因为 cipher_suites 字段是个列表,不是单值。必须用 contains 或 == 配合位置索引。细节决定成败。
4.3 捕获过滤器的实战用法
捕获过滤器用的是 BPF 语法,写在 Wireshark 捕获选项的输入框里。它的写法更精简,但限制也更多——不能深入协议字段。
host 192.168.1.1
port 443
tcp port 443 and host 10.0.0.1
not arp and not icmp
ether host aa:bb:cc:dd:ee:ff
我以前遇到过一个问题:在交换机镜像端口抓包时,流量里混杂了大量 LLDP 和 STP 包。只加一条 not stp and not lldp,捕获文件体积立刻缩小 70%。
注意:捕获过滤器不支持 tls.handshake.type 这种高层字段。它只工作在二层到四层。如果你需要针对 TLS 握手阶段做精准捕获,只能用显示过滤器或者先用捕获过滤器缩小范围,再慢慢分析。
4.4 过滤表达式核心逻辑一览
我把两种过滤器的关系画成一张图,方便你整体记忆:
4.5 快速定位 TLS 握手故障的过滤套路
说到具体场景,我分享几个我常用的“组合拳”:
- 只看完整的握手过程:
先用tls.handshake.type and tcp.stream eq 42tcp.stream找到一条 TCP 连接,再过滤出握手包。 - 找握手失败:
Alert 消息往往紧接着握手失败出现,一眼就能看到差错原因。tls.alert_message and tcp.stream eq 42 - 查看服务器证书链:
只看 Certificate 消息,右键 → Follow TLS Stream 可以导出证书。tls.handshake.type == 11 and ip.addr == 服务器IP - 分析密码套件协商:
在 Server Hello 里查看服务端最终选定的套件。tls.handshake.type == 2 and tls.handshake.cipher_suite
我的小技巧:别死记硬背字段名。在 Wireshark 里随便点开一个 TLS 包,展开每一层,右键你想过滤的字段,选择“Apply as Filter → Selected”,表达式会自动生成。非常省力。
4.6 常见错误与调试方法
你想想看,输入表达式后显示红色背景,是不是很烦?别慌,多半是以下几种情况:
- 字段名拼错了。比如把
tls.handshake写成tls.hanshake。Wireshark 不会自动纠错,它会认为这是一个不存在的字段。 - 类型不匹配。字符串字段不能用
==跟数字比,反之亦然。比如tls.handshake.cipher_suite == "0x1301"就错了,数字不用加引号。 - 忘记括号优先级。
tls and ip.src == 1.1.1.1 or ip.dst == 2.2.2.2会被解析成(tls and ip.src == 1.1.1.1) or ip.dst == 2.2.2.2。如果你希望括号是tls and (ip.src == 1.1.1.1 or ip.dst == 2.2.2.2),必须自己加括号。
调试方法很简单:把你要过滤的字段单独拎出来测试。比如先输 tls.handshake.type == 1,确认能出包,再慢慢加上其他条件。
注意:捕获过滤器一旦写成,无法修改正在进行的抓包。你必须停止捕获,修改语法,再重新开始。显示过滤器可以随时改,随时看结果。所以除非你很确定自己要抓什么,否则我建议先用显示过滤器。
4.7 小结
过滤表达式是 Wireshark 技能树里的基本功,也是最高频使用的功能。我个人觉得,只要把捕获和显示两套体系分清楚,再记住几个常用字段和逻辑符,日常抓包分析基本够用了。
你后续在分析 TLS 握手故障时,第一个动作一定是:打开过滤器,输入 tls.handshake.type,按回车。然后慢慢加条件缩小范围。