第四章 显示过滤器进阶:高级过滤技巧、函数与用户自定义过滤器

显示过滤器,说白了就是你跟Wireshark对话的语言。基础语法能让你抓到包,但想真正用好它,得学会高级玩法。我做了这么多年网络排障,发现很多人卡在“知道有这功能但不会用”的阶段。

今天咱们就把这块啃透。

4.1 逻辑运算符的深层用法

大部分人用 and、or、not 也就够了。但实际抓包时,条件往往更复杂。

核心原则:用括号明确优先级,别靠脑子记。

举个例子,你想看“来自192.168.1.1的HTTP流量,或者所有DNS查询”。很多人会写:

ip.src == 192.168.1.1 and http or dns

这其实是错的。Wireshark会解析成 (ip.src == 192.168.1.1 and http) or dns,结果把所有DNS包都捞出来了。正确写法是:

ip.src == 192.168.1.1 and (http or dns)

我在项目里见过好几次这种坑,排查了半天发现是过滤器逻辑搞反了。

4.2 比较运算符与切片操作

除了 ==、!=、>、<,Wireshark还支持一些冷门但好用的操作符。

运算符 含义 示例
contains 包含子串 http.host contains "baidu"
matches 正则匹配 http.request.uri matches "\.php$"
in 成员判断 ip.src in {10.0.0.0/8, 172.16.0.0/12}
[] 字节切片 eth.src[0:3] == 00:1a:2b

切片操作是我个人很爱用的。比如只看MAC地址前3字节(OUI)匹配某个厂商的包:

eth.addr[0:3] == 00:1a:2b

或者只看TCP负载的前4个字节:

tcp.payload[0:4] == 48:65:6c:6c

小技巧:切片语法是 [起始偏移:长度],偏移从0开始。不写长度就是取到末尾。

4.3 显示过滤器函数

Wireshark内置了一批函数,能帮你做更复杂的判断。我刚开始学的时候觉得这些函数可有可无,直到有一次要分析几千个TCP流……

4.3.1 upper() / lower()

字符串比较时忽略大小写:

upper(http.host) contains "GOOGLE"

4.3.2 len()

获取字段长度。比如只看UDP负载超过100字节的包:

len(udp.payload) > 100

4.3.3 count()

统计某个字段出现的次数。比如过滤出有超过3个TCP选项的包:

count(tcp.options) > 3

4.3.4 string()

把字段转成字符串,方便做正则匹配。比如:

string(frame.number) matches "^1[0-9]"

注意:string() 函数性能开销较大,在大流量抓包中慎用。我曾经在线上环境用这个函数,结果Wireshark卡了半分钟。

4.4 用户自定义显示过滤器

你有没有遇到过这种情况?一个复杂的过滤器,每次都要重新敲一遍。比如:

ip.src == 192.168.1.0/24 and tcp.port == 80 and not icmp

Wireshark允许你把这种常用过滤器保存成“按钮”,一键切换。

操作步骤:

  1. 点击显示过滤器栏右侧的 “+” 按钮(或右键 → 管理显示过滤器)
  2. 在弹出的对话框中,输入名称(比如“内网HTTP”)和过滤器表达式
  3. 点击保存

之后你就能在过滤器下拉菜单里直接选它了。我习惯把常用的排障场景都存成预设:

名称 过滤器表达式 用途
内网HTTP ip.src == 192.168.0.0/16 and http 只看内网HTTP请求
TCP重传 tcp.analysis.retransmission 快速定位重传
DNS异常 dns.flags.rcode != 0 过滤DNS错误响应
大包 frame.len > 1400 找出超过MTU的包

4.5 实战:用高级过滤器定位慢访问问题

咱们来走一个真实场景。用户反馈访问某个网站很慢,你抓了包,怎么快速定位?

我的做法是分三步:

  1. 先看TCP握手时间:
    tcp.flags.syn == 1 and ip.addr == 目标IP
    看SYN到SYN-ACK的延迟。
  2. 再看应用层响应时间:
    http.time > 1
    过滤出HTTP响应时间超过1秒的请求。
  3. 最后看是否有重传:
    tcp.analysis.retransmission and ip.addr == 目标IP

有一次我排查一个电商网站的慢访问,就是用这个组合拳,发现是某个CDN节点的TCP重传率高达15%。后来跟运营商一沟通,果然是路由问题。

4.6 知识体系总览

下面这张图把本章的核心逻辑串起来了。你想想看,从基础语法到函数,再到自定义过滤器,其实是一条线:表达能力越来越强,操作越来越快。

显示过滤器进阶知识体系 显示过滤器进阶知识体系 逻辑运算符 比较运算符 切片操作 显示过滤器函数:upper / lower / len / count / string 用户自定义过滤器:保存 / 管理 / 复用 实战场景:慢访问定位 / 重传分析 / 异常过滤 核心思路:从简单条件 → 函数增强 → 固化复用 → 解决实际问题 每一层都让你少敲键盘、少犯错、更快定位问题

4.7 避坑指南

最后分享几个我踩过的坑:

  • 别在显示过滤器里用 != 判断不存在的字段。比如 http.host != "baidu.com",它会匹配所有没有 http.host 字段的包(比如TCP握手包),结果完全不是你想要的。正确做法是 http.host and http.host != "baidu.com"。
  • 正则表达式别写太复杂。Wireshark的正则引擎性能一般,一个复杂的正则能让界面卡死。我一般只用 contains 解决80%的问题。
  • 自定义过滤器命名要有规律。我见过有人存了20多个过滤器,名字叫“test1”、“test2”……过两天自己都忘了是干嘛的。建议按“场景_协议_用途”命名,比如 web_http_慢请求。

我的习惯:每做完一次排障,就把用到的过滤器存下来,加个备注。半年下来,你的过滤器库就是一本排障手册。

好了,显示过滤器进阶就聊到这儿。这些技巧你多用几次,慢慢就会变成肌肉记忆。下次遇到复杂场景,别急着翻包,先想想能不能用一行过滤器搞定。