3. 显示过滤器:从入门到实战

抓包就像给网络做CT扫描。原始数据包是海量的,你不可能一个个翻。显示过滤器,就是帮你从这堆数据里精准捞出问题的那把手术刀。

我个人习惯,抓包时先全量抓,然后用显示过滤器慢慢筛。这比抓包前设一堆捕获过滤器要灵活得多。今天我们就把它彻底讲透。

3.1 显示过滤器语法基础

显示过滤器的核心语法其实很简单:协议.字段 运算符 值。就这么个结构,但组合起来威力巨大。

# 基本格式
协议.字段 运算符 值

# 实际例子
ip.src == 192.168.1.1
tcp.port == 80
http.request.method == "GET"

这里要注意,字段名是大小写敏感的。比如 tcp.port 写成 TCP.Port 就匹配不到。我曾经在排查一个DNS延迟问题时,就因为大小写写错,浪费了半小时。

运算符 含义 示例
== 等于 ip.src == 10.0.0.1
!= 不等于 ip.src != 10.0.0.1
> 大于 frame.len > 1500
< 小于 tcp.window_size < 65535
contains 包含子串 http.user_agent contains "Chrome"
matches 正则匹配 http.host matches "\.(com|cn)$"
小技巧: 在Wireshark的过滤栏输入时,按 Ctrl+Space 可以自动补全字段名。这个快捷键我每天用几十次。

3.2 逻辑运算符:组合你的过滤条件

单个条件往往不够用。比如你想看「从192.168.1.1发往80端口」的包,就需要组合条件。逻辑运算符就是干这个的。

# 与运算 (and / &&)
ip.src == 192.168.1.1 and tcp.dstport == 80

# 或运算 (or / ||)
tcp.port == 80 or tcp.port == 443

# 非运算 (not / !)
not arp

# 括号分组
(ip.src == 192.168.1.1 or ip.src == 192.168.1.2) and tcp.port == 443

嗯,这里要注意优先级。括号的优先级最高,然后是 not,接着是 and,最后是 or。我建议你拿不准的时候,直接用括号把条件包起来,清晰又安全。

实战场景: 排查Web服务器慢的问题时,我经常这样用:

http.time > 1 and ip.dst == 10.0.0.10

这能快速找出所有响应时间超过1秒的HTTP请求,而且只关注目标服务器。

3.3 字段匹配:深入协议内部

显示过滤器真正的威力,在于它能匹配协议字段的任意层级。你想想看,从二层MAC地址,到七层HTTP的Cookie,都能直接过滤。

3.3.1 二层与三层过滤

# MAC地址过滤
eth.addr == 00:1a:2b:3c:4d:5e
eth.src == 00:1a:2b:3c:4d:5e

# IP地址过滤
ip.addr == 192.168.1.1    # 同时匹配源和目标
ip.src == 192.168.1.0/24  # CIDR掩码也支持

# VLAN过滤
vlan.id == 100

3.3.2 四层传输层过滤

# TCP标志位过滤
tcp.flags.syn == 1        # 只显示SYN包
tcp.flags.reset == 1      # 只显示RST包
tcp.analysis.retransmission  # 显示重传包

# UDP过滤
udp.port == 53            # DNS查询

# 端口范围
tcp.port >= 1024 and tcp.port <= 65535
避坑指南: 我曾经用 tcp.flags.reset == 1 过滤RST包,结果发现很多正常的连接关闭也会产生RST。后来才意识到,需要结合 tcp.flags.ack == 0 来区分是主动RST还是被动RST。细节决定成败。

3.3.3 七层应用层过滤

# HTTP
http.request.method == "POST"
http.response.code == 404
http.content_type contains "json"

# DNS
dns.qry.name contains "example.com"
dns.flags.response == 0   # 只显示查询请求

# TLS/SSL
tls.handshake.type == 1   # Client Hello
tls.handshake.extensions_server_name contains "api"

3.4 过滤表达式复用:别重复造轮子

实际工作中,有些过滤条件你会反复用。比如排查数据库慢查询时,我每次都要过滤MySQL的慢查询日志。每次都重新敲一遍?太傻了。

3.4.1 保存为过滤按钮

Wireshark允许你把常用的过滤表达式保存为按钮,一键切换。

  1. 点击过滤栏左侧的「书签」图标
  2. 选择「管理显示过滤器」
  3. 输入名称和表达式,点击「新建」
  4. 以后直接点击按钮就能应用

3.4.2 使用配置文件

更高级的做法,是把过滤表达式写在配置文件里。这样换电脑、换环境都能直接导入。

# 在 Wireshark 的配置文件目录下
# Windows: %APPDATA%\Wireshark\dfilter
# Linux/Mac: ~/.config/wireshark/dfilter

# 文件内容示例
# 名称: 数据库慢查询
# 表达式: mysql.time > 1
# 
# 名称: HTTP错误
# 表达式: http.response.code >= 400

3.4.3 命令行复用

如果你用tshark(Wireshark的命令行版),可以把过滤表达式写在脚本里。

#!/bin/bash
# 分析TCP重传的脚本
FILTER="tcp.analysis.retransmission or tcp.analysis.fast_retransmission"
tshark -r capture.pcap -Y "$FILTER" -T fields -e ip.src -e ip.dst -e tcp.port
我的习惯: 我会把常用的10个过滤表达式做成一个文本文件,放在桌面。每次接到新的排查任务,先打开这个文件,复制粘贴,改改参数就能用。效率提升不是一点半点。

3.5 显示过滤器知识体系

下面这张图,是我自己总结的显示过滤器知识体系。你可以把它当作一个快速索引。

显示过滤器知识体系 显示过滤器 语法基础 逻辑运算符 字段匹配 表达式复用 协议.字段 运算符 值 and / && or / || not / ! 括号分组 二层/三层 四层传输 七层应用 保存为按钮 配置文件 命令行脚本 核心原则 先抓全量 → 再过滤 → 定位问题 → 复用表达式

3.6 实战:一个完整的排查案例

最后,我分享一个真实案例。有一次线上告警,用户反馈页面加载慢。我抓包后,用显示过滤器一步步定位。

# 第一步:只看HTTP请求
http

# 第二步:过滤出响应时间超过2秒的
http.time > 2

# 第三步:看看是哪些资源慢
http.request.uri contains ".js" and http.time > 2

# 第四步:确认是哪个服务器
ip.dst == 10.0.0.20 and http.time > 2

# 第五步:检查是否有TCP重传
tcp.analysis.retransmission and ip.dst == 10.0.0.20

最终发现,是一个JS文件因为CDN回源超时,导致TCP重传不断。整个过程,从抓包到定位,用了不到10分钟。显示过滤器就是你的探照灯,照到哪里,问题就现形到哪里。