3、抓包过滤器:捕获过滤器 vs 显示过滤器、BPF 语法入门、常见过滤表达式

说实话,我见过太多人一上来就开 Wireshark 全量抓包。结果呢?几秒钟就几万条数据包,看得人头皮发麻。这就像在图书馆里找一本书,却把整栋楼的书全搬到你桌上——你根本找不到重点。

所以,过滤器必须学会。而且得学透。

Wireshark 里其实有两套过滤器系统,很多人搞混。我刚开始用的时候也踩过这个坑,抓了半天发现想要的包没抓到,不想要的堆成山。嗯,咱们今天就把这事彻底理清楚。

3.1 捕获过滤器 vs 显示过滤器:到底有啥区别?

简单说,捕获过滤器是在抓包之前就设好的,它决定「哪些包进到内存里」。显示过滤器是抓完之后,在已经抓到的包里做筛选,它决定「哪些包显示在屏幕上」。

你想想看,捕获过滤器就像机场安检——没票的人直接拦在外面,根本进不了候机厅。显示过滤器呢,就像候机厅里的指示牌,告诉你哪些人去哪个登机口。

对比维度 捕获过滤器 显示过滤器
执行时机 抓包开始前 抓包完成后
语法基础 BPF(Berkeley Packet Filter) Wireshark 自定义表达式
性能影响 高——直接减少抓取量 低——只影响显示
能否恢复数据 不能——没抓到的永远没了 能——原始数据还在
典型场景 高流量环境、磁盘空间有限 事后分析、问题排查
⚠ 我曾经犯过的错:有一次排查线上延迟问题,我设了捕获过滤器只抓 TCP 80 端口。结果问题出在 DNS 解析阶段,端口是 53。所有 DNS 包全被过滤掉了,白抓了三个小时。从那以后,我养成了一个习惯——不确定场景时,先用显示过滤器,别用捕获过滤器。

3.2 BPF 语法入门:其实没那么玄乎

BPF 全称 Berkeley Packet Filter,是捕获过滤器的底层语言。说白了,它就是一套让网卡知道「哪些包我要,哪些包我不要」的指令集。

我个人习惯把 BPF 语法拆成三块来记:

  • 协议关键字:ether、ip、tcp、udp、arp 等
  • 方向关键字:src(源)、dst(目的)
  • 逻辑运算符:and(&&)、or(||)、not(!)

组合起来就是:[协议] [方向] [地址/端口] [逻辑] [协议] [方向] [地址/端口]

举个例子:

tcp dst port 80 and not src host 192.168.1.1

这句话的意思是:抓所有发往 TCP 80 端口的包,但排除源地址是 192.168.1.1 的包。你看,是不是很直白?

💡 一个小技巧:BPF 里 host 可以同时匹配源和目的。如果你只想匹配单向,一定要加 src 或 dst。我见过有人写 host 10.0.0.5,结果抓到了双向流量,自己还纳闷为什么数据量这么大。

3.3 常见过滤表达式:拿来就能用

下面这些是我工作中最常用的,你直接复制就能用。但别光复制,得理解每一条在干什么。

3.3.1 按 IP 过滤

# 只抓某个 IP 的流量(双向)
host 192.168.1.100

# 只抓从某个 IP 发出的流量
src host 192.168.1.100

# 只抓发往某个 IP 的流量
dst host 10.0.0.1

# 排除某个 IP
not host 192.168.1.1

3.3.2 按端口过滤

# 抓所有 HTTP 流量(80 端口)
tcp port 80

# 抓 HTTPS 流量
tcp port 443

# 抓 DNS 流量(UDP 53)
udp port 53

# 抓某个端口范围
tcp portrange 8000-9000

3.3.3 按协议组合过滤

# 只抓 HTTP 或 HTTPS
tcp port 80 or tcp port 443

# 抓所有非 SSH 的 TCP 流量
tcp and not port 22

# 抓 ICMP(ping)流量
icmp

3.3.4 按 MAC 地址过滤

# 抓某个 MAC 地址的流量
ether host 00:1a:2b:3c:4d:5e

# 抓从某个 MAC 发出的流量
ether src 00:1a:2b:3c:4d:5e

🔑 核心原则:捕获过滤器越精确越好。因为一旦抓漏了,数据就永远回不来了。我一般会先做一个「宽松版」的捕获过滤器,比如只按 IP 或端口过滤,然后在显示过滤器里做更细的筛选。

3.4 一张图看懂过滤器体系

下面这张图是我自己画的,把整个过滤器体系串起来了。你盯着看两分钟,应该就能记住。

Wireshark 过滤器体系结构图 Wireshark 过滤器体系 捕获过滤器 显示过滤器 特性 • 基于 BPF 语法 • 抓包前执行 • 减少抓取量,提升性能 • 无法恢复已过滤数据 特性 • 基于 Wireshark 表达式 • 抓包后执行 • 只影响显示,不影响原始数据 • 可随时切换/组合条件 共同目标:精准定位目标数据包 使用建议 不确定场景 → 用显示过滤器 | 高流量环境 → 用捕获过滤器

3.5 显示过滤器的快速入门

虽然本章重点讲捕获过滤器,但显示过滤器也得提一嘴。因为实际工作中,你往往是两者配合着用。

显示过滤器的语法更灵活,也更强大。比如:

# 显示所有 HTTP GET 请求
http.request.method == "GET"

# 显示所有 TCP 重传包
tcp.analysis.retransmission

# 显示所有 DNS 查询中域名为 example.com 的包
dns.qry.name == "example.com"

# 显示所有 IP 源地址在某个子网内的包
ip.src == 192.168.1.0/24

💡 我的习惯:在 Wireshark 里输入显示过滤器时,它会自动提示补全。你输入 tcp. 就会弹出所有 TCP 相关的字段。这个功能特别好用,我建议你多试试。

3.6 避坑指南:我踩过的那些坑

  • 坑一:BPF 里不能用 ==——BPF 用 = 或直接写值,比如 tcp port 80 而不是 tcp.port == 80。后者是显示过滤器的写法。
  • 坑二:大小写敏感——BPF 里协议关键字都是小写。TCP 不行,得写 tcp。
  • 坑三:逻辑运算符优先级——not 优先级最高,然后是 and,最后是 or。如果你不确定,加括号:tcp and (port 80 or port 443)。
  • 坑四:捕获过滤器不支持子网掩码——比如你不能写 ip src 192.168.1.0/24。得写成 src net 192.168.1.0/24。

好了,过滤器这块就这些。你先把捕获过滤器练熟,尤其是 BPF 那几条常用表达式。下次遇到高流量环境,你就知道该怎么省着抓了。