3、抓包过滤器:抓包过滤器语法、BPF表达式、MAC/IP/端口过滤实战
抓包过滤器这东西,说白了就是给Wireshark装个「筛子」。网络流量那么大,你不筛一下,根本看不清楚。我刚开始学抓包那会儿,经常被满屏的数据包淹死,后来才明白——会抓包不如会过滤。
这一章,咱们就聊聊怎么用好这个筛子。我会把BPF语法、MAC/IP/端口过滤这些实战技巧掰开揉碎了讲。嗯,都是我在项目里踩过坑之后总结出来的。
核心观点:抓包过滤器分为两种——捕获过滤器(抓之前筛)和显示过滤器(抓之后筛)。前者用BPF语法,后者用Wireshark自己的表达式。本章重点讲捕获过滤器,因为它是第一道关卡,用好了能省下大量磁盘空间和分析时间。
3.1 BPF语法:抓包过滤器的「内核语言」
BPF全称是Berkeley Packet Filter,伯克利包过滤器。它最早是BSD系统上的东西,后来成了几乎所有抓包工具的标准。Wireshark底层用的就是BPF。
BPF表达式的核心结构很简单:
[协议] [方向] [类型] [值]
举个例子:
host 192.168.1.1
这个表达式表示「只抓取源或目标IP为192.168.1.1的包」。你看,是不是很直观?
我个人习惯把BPF表达式分成三类:原语、修饰符和逻辑运算符。咱们一个一个说。
3.1.1 原语(Primitives)
原语就是过滤条件的基本单元。常见的原语有:
| 原语 | 含义 | 示例 |
|---|---|---|
host |
匹配指定主机 | host 10.0.0.5 |
net |
匹配指定网段 | net 192.168.0.0/24 |
port |
匹配指定端口 | port 80 |
ether host |
匹配指定MAC地址 | ether host aa:bb:cc:dd:ee:ff |
ip |
匹配IPv4协议 | ip |
arp |
匹配ARP协议 | arp |
tcp |
匹配TCP协议 | tcp |
udp |
匹配UDP协议 | udp |
icmp |
匹配ICMP协议 | icmp |
3.1.2 修饰符(Qualifiers)
修饰符用来细化原语的范围。它分三种:
- 类型修饰符:
host、net、port——指定你要过滤什么类型的东西。 - 方向修饰符:
src、dst——指定数据包的方向。不写的话默认是src或dst都匹配。 - 协议修饰符:
ip、arp、tcp、udp——指定协议栈的层级。
举个例子,你想抓「从192.168.1.10发出来的HTTP流量」:
tcp src host 192.168.1.10 and port 80
这里tcp是协议修饰符,src是方向修饰符,host和port是类型修饰符。
小技巧:方向修饰符src和dst可以组合使用。比如src and dst host 10.0.0.1表示「源和目标都是10.0.0.1」——这通常意味着广播或多播流量。
3.1.3 逻辑运算符
多个原语之间可以用逻辑运算符组合:
| 运算符 | 含义 | 示例 |
|---|---|---|
and 或 && |
与 | host 10.0.0.1 and port 443 |
or 或 || |
或 | port 80 or port 443 |
not 或 ! |
非 | not arp |
优先级方面,not最高,然后是and,最后是or。如果你搞不清楚优先级,就用括号:
host 10.0.0.1 and (port 80 or port 443)
这个表达式表示「抓取10.0.0.1的80或443端口的流量」。括号让逻辑更清晰,我建议你养成加括号的习惯。
3.2 MAC地址过滤实战
MAC地址过滤在局域网排错时特别有用。比如你怀疑某台设备的网卡有问题,或者想排除某个MAC地址的干扰流量。
基本语法:
ether host aa:bb:cc:dd:ee:ff
也可以指定方向:
ether src aa:bb:cc:dd:ee:ff
ether dst aa:bb:cc:dd:ee:ff
我记得有一次,客户说内网某个IP地址间歇性丢包。我抓了半天没发现问题,后来改用MAC地址过滤,才发现是ARP欺骗——那个IP地址对应了两个不同的MAC地址,轮流上线。嗯,MAC地址过滤在这种场景下比IP过滤更可靠。
注意:MAC地址过滤只对局域网有效。一旦数据包经过路由器,源和目标MAC地址会被改写。所以跨网段排错时,MAC过滤基本没用。
3.3 IP地址过滤实战
IP地址过滤是最常用的。语法很简单:
host 192.168.1.100
指定方向:
src host 192.168.1.100
dst host 192.168.1.100
过滤网段:
net 10.0.0.0/8
net 192.168.0.0/24
排除某个IP:
not host 192.168.1.1
我曾经遇到过一个场景:公司出口带宽被占满,怀疑是某台服务器在大量上传。我用src host 10.0.0.50 and not port 443过滤出那台服务器非HTTPS的出站流量,结果发现它在疯狂发送SNMP trap——嗯,监控系统配置错了。
实战建议:排错时先用host锁定目标,再用port缩小范围。别一上来就搞复杂的组合表达式,容易把自己绕晕。
3.4 端口过滤实战
端口过滤用来定位特定服务。基本语法:
port 80
port 443
port 53
指定协议和方向:
tcp port 22
udp port 53
tcp src port 8080
tcp dst port 3306
端口范围:
tcp portrange 8000-9000
udp portrange 10000-20000
你想想看,如果你怀疑Web服务器响应慢,可以这样过滤:
host 10.0.0.100 and tcp port 80
这样只抓Web服务器上的HTTP流量,其他乱七八糟的包全扔掉。
小技巧:很多服务同时用TCP和UDP。比如DNS用53端口,既有TCP也有UDP。如果你只关心UDP的DNS查询,就写udp port 53,别漏了协议修饰符。
3.5 综合实战:组合过滤
实际排错中,很少只用单一条件。咱们来看几个真实场景。
场景一:排查Web服务器问题
只抓Web服务器的HTTP和HTTPS流量:
host 10.0.0.10 and (tcp port 80 or tcp port 443)
场景二:排除监控流量
抓所有流量,但排除SNMP和ICMP:
not (udp port 161 or icmp)
场景三:抓两个主机之间的所有流量
host 192.168.1.10 and host 192.168.1.20
注意,这里用and连接两个host,表示「同时涉及这两个IP的流量」。
场景四:抓广播和多播流量
broadcast or multicast
这个在排查网络风暴时特别有用。
避坑指南:我曾经在抓包时写了个host 10.0.0.1 or host 10.0.0.2,结果发现抓到的包比预期少很多。后来才意识到——这个表达式只抓「源或目标是10.0.0.1」或者「源或目标是10.0.0.2」的包,但两个IP之间的通信包会被重复计数吗?不会。但如果你想要的是「两个IP之间的通信」,应该用host 10.0.0.1 and host 10.0.0.2。方向搞反了,结果天差地别。
3.6 在Wireshark中配置捕获过滤器
配置方法很简单:
- 打开Wireshark,点击菜单栏的「捕获」→「选项」。
- 在「捕获过滤器」输入框中输入你的BPF表达式。
- 点击「开始」按钮,Wireshark就会按你的规则抓包。
你也可以保存常用的过滤器:输入表达式后,点击旁边的「保存」按钮,给它起个名字。下次直接从下拉列表里选就行。
我个人习惯把常用的过滤器保存下来,比如:
- Web流量:
tcp port 80 or tcp port 443 - DNS查询:
udp port 53 - 排除本机:
not host 192.168.1.100 - 内网全流量:
net 192.168.0.0/16
这样每次排错就不用重新敲了。
3.7 常见错误与调试
BPF表达式写错了,Wireshark会报错。常见的错误有:
| 错误写法 | 问题 | 正确写法 |
|---|---|---|
host 192.168.1.1 and 80 |
缺少port关键字 |
host 192.168.1.1 and port 80 |
src 10.0.0.1 |
缺少host关键字 |
src host 10.0.0.1 |
tcp or udp port 53 |
逻辑混乱,or优先级问题 |
tcp port 53 or udp port 53 |
not host 10.0.0.1 and port 80 |
优先级问题,实际等价于not (host 10.0.0.1 and port 80) |
(not host 10.0.0.1) and port 80 |
嗯,最后一个错误我犯过好几次。不加括号的话,not的优先级比and高,结果完全不是你想要的。
总结一下:BPF表达式不难,但细节决定成败。记住三点——加协议修饰符、加方向修饰符、加括号。这三招用好了,你的捕获过滤器就不会出错。
好了,这一章的内容就到这儿。你可以在自己的实验环境里试试这些表达式,感受一下不同过滤条件的效果。抓包这东西,光看没用,得动手。