3、抓包过滤器:抓包过滤器语法、BPF表达式、MAC/IP/端口过滤实战

抓包过滤器这东西,说白了就是给Wireshark装个「筛子」。网络流量那么大,你不筛一下,根本看不清楚。我刚开始学抓包那会儿,经常被满屏的数据包淹死,后来才明白——会抓包不如会过滤。

这一章,咱们就聊聊怎么用好这个筛子。我会把BPF语法、MAC/IP/端口过滤这些实战技巧掰开揉碎了讲。嗯,都是我在项目里踩过坑之后总结出来的。

核心观点:抓包过滤器分为两种——捕获过滤器(抓之前筛)和显示过滤器(抓之后筛)。前者用BPF语法,后者用Wireshark自己的表达式。本章重点讲捕获过滤器,因为它是第一道关卡,用好了能省下大量磁盘空间和分析时间。

抓包过滤器知识体系 抓包过滤器 捕获过滤器 显示过滤器 BPF语法 MAC/IP/端口 表达式语法 高级过滤 本章重点:捕获过滤器(BPF) 在抓包之前就过滤掉不需要的流量 语法: [协议] [方向] [类型] [值]

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中配置捕获过滤器

配置方法很简单:

  1. 打开Wireshark,点击菜单栏的「捕获」→「选项」。
  2. 在「捕获过滤器」输入框中输入你的BPF表达式。
  3. 点击「开始」按钮,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表达式不难,但细节决定成败。记住三点——加协议修饰符、加方向修饰符、加括号。这三招用好了,你的捕获过滤器就不会出错。

好了,这一章的内容就到这儿。你可以在自己的实验环境里试试这些表达式,感受一下不同过滤条件的效果。抓包这东西,光看没用,得动手。