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 本章知识体系
下面这张图帮你理清两套过滤器的关系和使用场景。
4.7 避坑指南
最后分享几个我踩过的坑:
- 捕获过滤器写错,包就没了:我曾经在抓包时写了个
host 192.168.1.0/24,注意,BPF 里host后面不能跟 CIDR,得用net。结果抓了半天全是空的,还以为是网卡有问题。 - 显示过滤器大小写敏感:
http和HTTP不一样,contains和CONTAINS也不一样。Wireshark 的字段名都是小写的,养成用小写的习惯。 - 别在捕获过滤器里用
tcp.analysis.flags:这类字段是 Wireshark 分析引擎生成的,不是原始包里的字段,捕获过滤器根本不认识。我见过有人把显示过滤器的语法直接复制到捕获过滤器里,结果 Wireshark 直接报错。 - 过滤栏变黄是警告,变红是错误:黄色表示语法可能有问题但能执行,红色表示语法错误无法执行。看到红色就检查一下字段名和运算符。
好了,过滤器这块的内容就这么多。记住一个原则:先想清楚你要看什么,再选对过滤器。工具是死的,思路是活的。多练几次,你就能像我一样闭着眼写出过滤条件了。