4. Wireshark 过滤器:捕获过滤器(BPF 语法)与显示过滤器(表达式语法)、常用过滤规则实战

过滤器这东西,说白了就是帮你从海量数据里捞针的工具。我刚带团队做安全应急的时候,经常面对几十 GB 的 pcap 文件,要是没有过滤器,光看原始包就能把人看吐。Wireshark 给了我们两套过滤体系——捕获过滤器和显示过滤器,很多人搞混它们,今天咱们一次说清楚。

4.1 两套过滤器的本质区别

先记住一句话:捕获过滤器是「拦路虎」,显示过滤器是「筛子」。

  • 捕获过滤器:在抓包开始前设置,直接告诉网卡「我只收这些包,其他的别进来」。它工作在数据链路层,用的是 BPF(Berkeley Packet Filter)语法。好处是节省磁盘和内存,坏处是一旦设错,漏掉的包就再也找不回来了。
  • 显示过滤器:在抓包结束后或抓包过程中设置,对所有已捕获的包进行二次筛选。它工作在 Wireshark 内部,用的是 Wireshark 自己的表达式语法。好处是灵活,随时可以改,不会丢原始数据。

我的建议:日常分析用显示过滤器就够了。只有当你明确知道要抓什么协议、且流量极大(比如 1Gbps 以上)时,才用捕获过滤器提前过滤。我曾经在客户现场抓核心交换机流量,没加捕获过滤器,结果笔记本硬盘 5 分钟就写满了……嗯,从那以后我养成了先估算流量的习惯。

4.2 捕获过滤器:BPF 语法实战

BPF 语法其实不复杂,核心就是「协议 + 方向 + 地址 + 端口」的组合。Wireshark 的捕获过滤器输入框就在主界面顶部的绿色条里。

4.2.1 基础表达式

需求 BPF 表达式 说明
只抓 HTTP 流量 tcp port 80 HTTP 默认端口 80
只抓 HTTPS 流量 tcp port 443 HTTPS 默认端口 443
抓某个 IP 的所有流量 host 192.168.1.100 包括源和目标
抓某个网段 net 192.168.1.0/24 CIDR 表示法
排除某个 IP not host 10.0.0.1 用 not 取反
只抓 UDP 流量 udp 简单直接

4.2.2 组合表达式

BPF 支持逻辑运算符:and(&&)、or(||)、not(!)。

# 抓来自 192.168.1.100 的 DNS 查询
host 192.168.1.100 and udp port 53

# 抓除了 SSH 之外的所有 TCP 流量
tcp and not port 22

# 抓两个特定主机之间的流量
host 192.168.1.1 and host 192.168.1.2

# 抓 DHCP 请求(广播 + UDP 67/68)
udp and (port 67 or port 68)

注意:BPF 语法中,and 的优先级高于 or,所以组合条件时记得加括号。我曾经见过一个同事写 host 10.0.0.1 or host 10.0.0.2 and port 80,结果只抓到了 10.0.0.2 的 80 端口流量,10.0.0.1 的流量全丢了——因为实际解析成了 host 10.0.0.1 or (host 10.0.0.2 and port 80)。

4.2.3 高级 BPF:基于包偏移的过滤

BPF 的底层能力其实很强,可以直接操作包字节偏移。不过日常用得少,我一般只在分析特定协议异常时才会用。

# 抓 TCP SYN 包(TCP 标志位第 13 字节,SYN=0x02)
tcp[13] & 2 != 0

# 抓 TCP RST 包
tcp[13] & 4 != 0

# 抓 IP 包长大于 1000 字节的包
ip[2:2] > 1000

说实话,这种写法可读性太差。我个人更推荐用显示过滤器来做这类精细过滤,后面会讲到。

4.3 显示过滤器:Wireshark 表达式语法

显示过滤器才是 Wireshark 的精华。它基于协议字段,语法更直观,而且有自动补全和提示。你可以在主界面的过滤栏直接输入,也可以点「表达式…」按钮从列表里选。

4.3.1 基础语法结构

格式很简单:协议.字段 运算符 值。

运算符 含义 示例
== 或 eq 等于 ip.src == 192.168.1.1
!= 或 ne 不等于 ip.dst != 10.0.0.1
> 或 gt 大于 frame.len > 1500
< 或 lt 小于 tcp.port < 1024
contains 包含字符串 http.host contains "baidu"
matches 正则匹配 http.request.uri matches "^/api/v[12]/"
in 属于集合 tcp.port in {80,443,8080}

4.3.2 常用过滤规则速查

下面这些是我在项目中反复用到的,建议你直接收藏。

# 只看某个 IP 的流量
ip.addr == 192.168.1.100

# 只看某个 TCP 会话(五元组)
ip.addr == 192.168.1.1 and ip.addr == 10.0.0.1 and tcp.port == 443

# 只看 HTTP 请求(GET/POST)
http.request

# 只看 HTTP 响应状态码为 404 的
http.response.code == 404

# 只看 DNS 查询域名包含 "google" 的
dns.qry.name contains "google"

# 只看 TCP 重传包
tcp.analysis.retransmission

# 只看 TCP 零窗口(接收方没空间了)
tcp.analysis.zero_window

# 只看 ARP 请求
arp.opcode == 1

# 只看 TLS 握手 Client Hello
tls.handshake.type == 1

# 只看 ICMP 回显请求(ping)
icmp.type == 8

小技巧:在过滤栏输入时,Wireshark 会自动把匹配的字段高亮成绿色,不匹配的字段显示红色。如果你看到红色,别急着回车——先检查拼写或字段名对不对。我习惯先输入 tcp. 然后按 Ctrl+Space 触发自动补全,这样基本不会写错。

4.4 实战场景:用过滤器快速定位问题

光讲语法没意思,咱们来几个真实场景。

场景一:网站打不开,是不是 DNS 的问题?

先抓包,然后用显示过滤器:

dns.qry.name == "www.example.com"

看看有没有 DNS 响应。如果没有,说明 DNS 解析失败。如果有,但响应 IP 不对,那就是 DNS 劫持或配置错误。我在一次故障排查中就遇到过这种情况——DNS 返回了一个内网 IP,但那个服务根本没部署,白白浪费了半小时。

场景二:某个接口响应特别慢

先找到那个 HTTP 请求:

http.request.uri contains "/api/order/list"

然后右键这个包 → Follow → HTTP Stream,就能看到完整的请求和响应。接着用 tcp.analysis.ack_rtt 看 TCP 往返时延,或者用 http.time 看 HTTP 总耗时。如果耗时主要在服务器端(响应时间 > 1s),那就是后端代码的问题;如果耗时在网络传输上,那就得看带宽或链路质量了。

场景三:怀疑有人在扫端口

端口扫描的特征是短时间内大量 SYN 包发往不同端口。用这个过滤器:

tcp.flags.syn == 1 and tcp.flags.ack == 0 and tcp.dstport not in {22,80,443,8080}

然后看 Statistics → Conversations,按包数排序。如果某个 IP 在短时间内发了几千个 SYN 包,基本可以实锤了。

4.5 过滤器保存与复用

好的过滤器值得保存。Wireshark 支持两种方式:

  • 显示过滤器按钮:在过滤栏旁边有个小加号,点一下就能把当前过滤器保存为按钮。下次直接点按钮就能切换。
  • 配置文件:在 Edit → Configuration Profiles 里可以创建不同的配置文件,每个配置文件可以有自己的过滤器按钮组。我一般会建一个「Web 分析」配置和一个「安全分析」配置,里面预置好常用的过滤器。

我的习惯:把最常用的 5-10 个过滤器做成按钮,比如「只看 HTTP」「只看 DNS」「只看错误包」「只看重传」。这样在应急响应时能省下大量时间。你想想看,当老板站在你身后问「到底什么问题」的时候,你还在手敲过滤条件——那画面多尴尬。

4.6 本章知识体系

下面这张图帮你理清两套过滤器的关系和使用场景。

Wireshark 过滤器知识体系 捕获过滤器(BPF) 显示过滤器(表达式) 工作层:数据链路层(内核态) 语法:BPF(协议 + 方向 + 地址 + 端口) 特点:抓前过滤,节省资源,不可逆 工作层:Wireshark 内部(用户态) 语法:协议.字段 运算符 值 特点:抓后过滤,灵活可改,不丢数据 使用建议 日常分析 → 优先用显示过滤器 大流量/明确需求 → 用捕获过滤器提前拦截

4.7 避坑指南

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

  • 捕获过滤器写错,包就没了:我曾经在抓包时写了个 host 192.168.1.0/24,注意,BPF 里 host 后面不能跟 CIDR,得用 net。结果抓了半天全是空的,还以为是网卡有问题。
  • 显示过滤器大小写敏感:http 和 HTTP 不一样,contains 和 CONTAINS 也不一样。Wireshark 的字段名都是小写的,养成用小写的习惯。
  • 别在捕获过滤器里用 tcp.analysis.flags:这类字段是 Wireshark 分析引擎生成的,不是原始包里的字段,捕获过滤器根本不认识。我见过有人把显示过滤器的语法直接复制到捕获过滤器里,结果 Wireshark 直接报错。
  • 过滤栏变黄是警告,变红是错误:黄色表示语法可能有问题但能执行,红色表示语法错误无法执行。看到红色就检查一下字段名和运算符。

好了,过滤器这块的内容就这么多。记住一个原则:先想清楚你要看什么,再选对过滤器。工具是死的,思路是活的。多练几次,你就能像我一样闭着眼写出过滤条件了。