用 Wireshark 和 tcpdump 按 MAC 地址过滤抓包
按 MAC 地址过滤是二层排查最常用的操作。Wireshark 有两套语法容易混淆:捕获过滤器用 BPF,显示过滤器用自己的表达式语言。写错语法是新手最常见的挫败来源。
显示过滤器:分析已抓到的包
显示过滤器写在 Wireshark 主界面的过滤栏,作用于已捕获的数据。
eth.addr == 00:1b:a9:12:34:56 # 源或目标任一匹配
eth.src == 00:1b:a9:12:34:56 # 仅源地址
eth.dst == 00:1b:a9:12:34:56 # 仅目标地址
eth.addr != 00:1b:a9:12:34:56 # 排除某个地址
按 OUI 过滤是个很实用的技巧。想看某个厂商所有设备的流量:
eth.addr[0:3] == 00:1b:a9 # 前三字节匹配
这里 [0:3] 是切片语法,从第 0 字节取 3 个字节。要确认某个前缀属于哪家厂商,可以在厂商目录里查。
筛出组播和广播:
eth.dst == ff:ff:ff:ff:ff:ff # 广播
eth.ig == 1 # 所有组播(含广播)
eth.lg == 1 # 本地管理地址
eth.lg == 1 特别有用,它一次筛出所有启用了随机化的客户端和虚拟接口。标志位的含义见读懂 MAC 地址第一字节。
捕获过滤器:抓之前就丢掉
捕获过滤器用 BPF 语法,在内核层面丢弃不匹配的包。高流量环境下必须用它,否则磁盘和 CPU 都吃不消。
ether host 00:1b:a9:12:34:56 # 源或目标
ether src 00:1b:a9:12:34:56 # 仅源
ether dst 00:1b:a9:12:34:56 # 仅目标
ether broadcast # 广播帧
ether multicast # 组播帧
not ether host 00:1b:a9:12:34:56 # 排除
注意两套语法完全不通用。在捕获过滤栏里写 eth.addr == 会直接报错,反之亦然。记忆方法:带点号的属于显示过滤器,带空格的关键字属于捕获过滤器。
tcpdump 用同一套 BPF 语法
# 抓某个 MAC 的全部流量
sudo tcpdump -i eth0 ether host 00:1b:a9:12:34:56 -w out.pcap
# 只抓 ARP,便于排查地址解析和欺骗
sudo tcpdump -i eth0 arp -nn
# 抓某 OUI 的流量,用字节偏移比较
sudo tcpdump -i eth0 'ether[6:4] = 0x001ba912'
最后一条值得解释。以太网帧的第 6 到 11 字节是源 MAC,ether[6:4] 取 4 个字节做比较。这是 BPF 没有内置 OUI 过滤时的变通做法。
排查 ARP 问题时,-nn 参数很重要,它禁止把地址解析成名称,输出更快也更真实。配合ARP 欺骗防御里的检测方法使用效果最好。
几个实际场景
找出谁在发大量广播。 先按广播过滤,然后看统计:
eth.dst == ff:ff:ff:ff:ff:ff
再打开 Statistics 菜单里的 Conversations,按 Ethernet 标签排序,发包最多的源地址一目了然。
确认一台设备是否真的在通信。 用它的 MAC 做捕获过滤器,抓几分钟。完全没有包说明设备离线或不在这个广播域,这比 ping 可靠,因为 ping 会被防火墙挡下。
排查 IP 与 MAC 不一致。 如果某个 IP 对应的源 MAC 在抓包过程中变了,要么是设备真的换了,要么存在欺骗。把两个 MAC 都在查询页查一下厂商,往往能立刻判断。
无线抓包的额外要求
要看到其它设备的帧,网卡必须进入监听模式:
sudo ip link set wlan0 down
sudo iw dev wlan0 set type monitor
sudo ip link set wlan0 up
监听模式下无法正常上网,而且并非所有网卡和驱动都支持。注意抓取他人流量涉及法律与合规问题,请只在自己拥有或获得明确授权的网络上操作。