4、Wireshark高级过滤:过滤表达式语法、协议过滤、字段过滤、逻辑运算符组合过滤

说实话,很多搞网络的人用了好几年Wireshark,还停留在「点一下菜单栏,输入个http」的水平。嗯,这其实挺可惜的。Wireshark真正的威力,藏在那个小小的过滤栏里。今天我就带你把这层窗户纸捅破。

4.1 过滤表达式语法:你得先懂这个骨架

Wireshark的过滤语法,说白了就两套体系:一套是显示过滤器(Display Filter),另一套是捕获过滤器(Capture Filter)。我们日常99%的场景都在用显示过滤器,所以我重点讲这个。

显示过滤器的基本语法长这样:

协议.字段 运算符 值

举个例子:

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 > 1000
< 小于 frame.len < 64
contains 包含字符串 http.host contains "baidu"
matches 正则匹配 http.user_agent matches "Chrome"
我的小习惯:我一般用双等号==,不用单等号。虽然Wireshark两者都认,但双等号更符合编程习惯,不容易搞混。

4.2 协议过滤:快速锁定你关心的流量

协议过滤是最基础的,也是最常用的。你直接在过滤栏输入协议名就行:

dns
http
tcp
arp
icmp
tls

就这么简单。但这里有个坑——协议名是大小写敏感的。你输入HTTP可以,输入http也可以,但输入Http就不行。我曾经因为这个在客户现场排查了半小时,最后发现是大小写写错了……嗯,尴尬。

如果你想过滤某个协议的子类,比如只看HTTP的GET请求:

http.request.method == "GET"

或者只看DNS的A记录查询:

dns.qry.type == 1

这里1代表A记录,2代表NS记录,15代表MX记录。记不住没关系,Wireshark的自动补全会帮你。

4.3 字段过滤:深入到协议内部去

协议过滤只是第一层。真正的高手,会直接操作协议字段。比如:

tcp.port == 443
ip.addr == 192.168.1.1
eth.addr == 00:11:22:33:44:55
frame.time_delta > 0.1

这些字段从哪里来?你点开任何一个包,展开协议树,看到的每一行都是一个字段。比如TCP协议下面有src port、dst port、sequence number、acknowledgment number等等。你右键点击某个字段,选择「作为过滤器应用」,Wireshark会自动帮你生成过滤表达式。

我个人习惯是:先点开一个包看看结构,再手动写过滤表达式。这样既能理解协议细节,又能快速定位问题。

重点:字段名是分层的,用点号连接。比如tcp.analysis.flags是TCP分析标志,tcp.analysis.retransmission是重传标志。你可以在过滤栏输入tcp.analysis.然后按Tab键,Wireshark会列出所有可用的子字段。

4.4 逻辑运算符组合过滤:这才是真正的杀手锏

单个条件过滤太简单了。实际工作中,你往往需要组合多个条件。Wireshark支持三种逻辑运算符:

  • and(&&):两个条件都满足
  • or(||):满足其中一个条件
  • not(!):取反

举个例子,我想看「从192.168.1.1发往百度服务器的HTTP流量」:

ip.src == 192.168.1.1 and http.host contains "baidu.com"

或者我想看「除了SSH以外的所有TCP流量」:

tcp and not tcp.port == 22

再复杂一点,我想看「DNS查询失败或者HTTP返回500的包」:

dns.flags.rcode != 0 or http.response.code == 500

你想想看,这种组合过滤能帮你多快定位问题?

注意优先级:and的优先级高于or。如果你写a or b and c,实际执行的是a or (b and c)。如果你想让(a or b) and c,一定要加括号。我曾经在排查一个DNS问题时,因为没加括号,结果过滤出来的数据完全不对,浪费了整整一个下午。

4.5 实战案例:一次真实的网络故障排查

我记得有一次,客户反馈某个业务系统访问特别慢。我抓了包,先用这个过滤表达式:

tcp.analysis.retransmission or tcp.analysis.fast_retransmission

结果发现大量重传包。进一步过滤:

tcp.analysis.retransmission and ip.dst == 10.0.0.100

锁定目标IP后,再用:

tcp.analysis.retransmission and ip.dst == 10.0.0.100 and tcp.port == 443

最终发现是SSL握手阶段频繁重传。再深入:

tls.handshake.type == 1 and ip.dst == 10.0.0.100

找到了问题根源——客户端发送的Client Hello包被中间设备截断了。整个过程,从抓包到定位,不到10分钟。

你看,这就是高级过滤的威力。没有这些组合过滤,你只能在一堆数据里大海捞针。

4.6 几个我常用的过滤表达式

最后,分享几个我工作中高频使用的过滤表达式,你可以直接拿去用:

场景 过滤表达式
查看TCP三次握手 tcp.flags.syn == 1 and tcp.flags.ack == 0
查看TCP挥手 tcp.flags.fin == 1
查看所有重传 tcp.analysis.retransmission
查看HTTP POST请求 http.request.method == "POST"
查看特定端口的UDP流量 udp.port == 53
查看ICMP超时 icmp.type == 11
排除广播和多播 not (eth.dst == ff:ff:ff:ff:ff:ff or ip.dst == 224.0.0.0/4)
小技巧:Wireshark的过滤栏支持历史记录。你按上下箭头键,可以快速切换之前用过的过滤表达式。我一般会把常用的表达式存成按钮(过滤栏右侧的「保存」按钮),下次直接点击就能用。

好了,关于Wireshark高级过滤,今天就聊这么多。说白了,过滤表达式就是你和数据包之间的翻译官。你学得越深,它就越懂你。下一章,我会讲怎么用这些过滤技巧做离线数据分析,到时候咱们再接着聊。