4. 显示过滤器进阶:过滤表达式语法、逻辑组合、按字段过滤、按时间/长度过滤
上一章我们聊了基础过滤,说白了就是点几下鼠标。但真正的高并发分析,靠鼠标点选是搞不定的。你得学会跟 Wireshark 的显示过滤器「对话」——用表达式精准地告诉它:我要看什么,不要看什么。
我个人习惯,80% 的日常分析工作都靠显示过滤器完成。它不会丢包,只是隐藏你不关心的数据。这一点很重要,你想想看,在高并发场景下,几万甚至几十万个包涌进来,眼睛看是看不过来的,必须靠过滤器把范围缩小到可分析的级别。
核心认知:显示过滤器(Display Filter)只改变视图,不改变抓取结果。你随时可以清除过滤器,所有数据都还在。
4.1 过滤表达式语法:从简单到复杂
Wireshark 的过滤语法,其实是一种领域特定语言(DSL)。它由三部分组成:字段名、比较操作符、值。
最基本的格式长这样:
字段名 操作符 值
举个例子:
tcp.port == 443
这表示「只看源端口或目的端口为 443 的 TCP 包」。注意,这里用的是双等号 ==,不是单等号。单等号在 Wireshark 里是赋值,不是比较。
常用的比较操作符有这些:
| 操作符 | 含义 | 示例 |
|---|---|---|
== |
等于 | ip.src == 192.168.1.1 |
!= |
不等于 | tcp.port != 80 |
> |
大于 | frame.len > 1000 |
< |
小于 | tcp.window_size < 65535 |
>= |
大于等于 | frame.time_relative >= 5.0 |
<= |
小于等于 | tcp.analysis.ack_rtt <= 0.1 |
contains |
包含子串 | http.host contains "api" |
matches |
正则匹配 | http.request.uri matches "^/v[0-9]/" |
我的小技巧:如果你不确定某个字段名怎么写,直接在包详情面板里右键点击字段,选择「作为过滤器应用」→「选中」。Wireshark 会自动帮你生成正确的表达式。我刚开始学的时候,全靠这个功能反推字段名。
4.2 逻辑组合:and、or、not
单个条件往往不够用。高并发场景下,你得同时满足多个条件。这时候就需要逻辑操作符出场了。
三个核心操作符:
- and(&&):两个条件都满足
- or(||):满足其中一个条件
- not(!):取反,排除某个条件
看几个实战例子:
# 只看从 10.0.0.1 发往 443 端口的包
ip.src == 10.0.0.1 and tcp.dstport == 443
# 只看 192.168.1.0/24 网段内,且长度大于 1500 的包
ip.addr == 192.168.1.0/24 and frame.len > 1500
# 排除所有广播包和组播包
not (eth.dst == ff:ff:ff:ff:ff:ff or eth.dst[0:1] == 01:00:5e)
# 看 HTTP 或 DNS 流量
http or dns
这里有个坑,我踩过好几次。你注意看 ip.addr 这个字段——它同时包含了源地址和目的地址。所以 ip.addr == 10.0.0.1 的意思是「源地址或目的地址任意一个是 10.0.0.1」。如果你只想看源地址,必须用 ip.src。
我曾经犯过的错:有一次排查一个高并发连接池问题,我用了 ip.addr == 10.0.0.1 and tcp.port == 8080。结果发现过滤出来的包比预期多了一倍。后来才意识到,tcp.port 也是同时匹配源端口和目的端口。正确的写法应该是 ip.addr == 10.0.0.1 and (tcp.srcport == 8080 or tcp.dstport == 8080)。
4.3 按字段过滤:tcp.port、ip.addr 的深层用法
字段过滤是显示过滤器的核心能力。Wireshark 支持数千个协议字段,每个字段都可以作为过滤条件。我挑几个高并发场景下最常用的来讲。
4.3.1 tcp.port 的微妙之处
tcp.port 是一个「合成字段」,它等价于 tcp.srcport or tcp.dstport。这意味着:
# 这两个表达式是等价的
tcp.port == 443
tcp.srcport == 443 or tcp.dstport == 443
但如果你只想看客户端发往服务器的包,必须明确指定方向:
# 客户端发往 443
tcp.dstport == 443
# 服务器从 443 发出
tcp.srcport == 443
4.3.2 ip.addr 的网段过滤
高并发场景下,经常要过滤整个网段。Wireshark 支持 CIDR 表示法:
# 只看 10.0.0.0/8 网段的流量
ip.addr == 10.0.0.0/8
# 排除 192.168.0.0/16 的内网流量
not ip.addr == 192.168.0.0/16
嗯,这里要注意:CIDR 过滤只能用在 ip.addr、ip.src、ip.dst 这类地址字段上,不能用在端口上。
4.3.3 其他高并发常用字段
| 字段 | 含义 | 高并发场景用途 |
|---|---|---|
tcp.analysis.ack_rtt |
ACK 往返时间 | 排查延迟抖动 |
tcp.analysis.retransmission |
重传标记 | 定位丢包 |
tcp.window_size |
接收窗口大小 | 判断接收端瓶颈 |
tcp.stream |
TCP 流编号 | 追踪单条连接 |
http.response.code |
HTTP 响应码 | 过滤 5xx 错误 |
4.4 按时间/长度过滤:精准定位异常
高并发连接分析中,时间和长度是两个极其重要的维度。异常往往就藏在「不该出现的时间点」和「不该出现的大小」里。
4.4.1 按时间过滤
Wireshark 提供了几个时间相关的字段:
frame.time_relative:相对于抓包开始的时间(秒)frame.time_delta:与前一个包的间隔(秒)frame.time_delta_displayed:与上一个显示出来的包的间隔
实战例子:
# 只看抓包开始后 5 到 10 秒之间的包
frame.time_relative >= 5 and frame.time_relative <= 10
# 看间隔超过 1 秒的包(可能是超时)
frame.time_delta > 1.0
# 结合场景:看 5 秒后出现的重传
frame.time_relative > 5 and tcp.analysis.retransmission
我的经验:分析高并发连接池泄漏时,我经常用 frame.time_relative 配合 tcp.stream 来看一条连接的生命周期。如果一条连接在抓包开始后 30 秒还在发数据,但其他同类连接早就结束了,那这条连接很可能有问题。
4.4.2 按长度过滤
包长度是另一个重要指标。高并发场景下,异常的包大小往往意味着问题。
# 只看大于 1500 字节的包(可能涉及分片)
frame.len > 1500
# 只看小于 64 字节的包(可能是控制包或攻击包)
frame.len < 64
# 看特定长度的 TCP 载荷
tcp.len == 0 # 纯 ACK 包
tcp.len > 1000 # 大数据包
这里有个容易混淆的点:frame.len 是整个帧的长度(包含以太网头部),ip.len 是 IP 包的长度(包含 IP 头部),tcp.len 是 TCP 载荷的长度(不包含 TCP 头部)。
举个例子,一个典型的 HTTP 响应包:
frame.len= 1514(以太网帧)ip.len= 1500(IP 包)tcp.len= 1460(TCP 载荷,去掉了 IP 头部 20 字节和 TCP 头部 20 字节)
4.5 知识体系总览
下面这张图把本章的核心知识点串起来了。你可以把它当作一个快速参考地图。
4.6 实战组合:一个高并发场景的过滤链
最后,我拿一个真实场景来演示怎么把这些知识串起来。
假设你在分析一个高并发 Web 服务,怀疑有客户端在疯狂重试导致服务器负载飙升。你想找出那些「在短时间内发起大量连接、且频繁重试」的客户端。
过滤链可以这样构建:
# 第一步:只看 TCP 握手包(SYN 包)
tcp.flags.syn == 1 and tcp.flags.ack == 0
# 第二步:加上时间窗口,只看最近 10 秒
frame.time_relative > 10 and frame.time_relative < 20
# 第三步:排除内网健康检查
not ip.src == 10.0.0.0/8
# 第四步:只看目标端口 443
tcp.dstport == 443
# 最终组合
frame.time_relative > 10 and frame.time_relative < 20
and tcp.flags.syn == 1 and tcp.flags.ack == 0
and tcp.dstport == 443
and not ip.src == 10.0.0.0/8
这个过滤器会帮你精准定位到「在 10-20 秒之间,从外网发往 443 端口的所有 SYN 包」。如果某个源 IP 出现了几十次,那它大概率就是问题客户端。
我的习惯:我会把这个长表达式保存成一个过滤按钮(点击过滤器栏左侧的「+」号),下次直接点一下就能用。高并发场景下,时间就是命,能省一秒是一秒。