# 1 **核心原理:802.1ad 与 802.1Q 在BPF眼里的异同**
首先,你得明白,BPF的`vlan`关键字很聪明,它能同时理解802.1Q(EtherType `0x8100`)和802.1ad(EtherType `0x88a8`)。所以,我们昨天讨论的关于`vlan A and vlan B`的**位置决定论**在这里**完全适用**。
* 第一个 vlan 关键字:匹配最外层的标签,在802.1ad里就是 \*\*S-TAG (Service Tag)\*\*。
* 第二个 vlan 关键字:匹配内层的标签,在802.1ad里就是 \*\*C-TAG (Customer Tag)\*\*。
但是,如果你想更精确地只抓802.1ad的帧,而不抓普通的802.1Q,那我们就得用上它的专属“身份证号”——EtherType `0x88a8`。
1.1 802.1ad (QinQ) 常见抓包分析过滤语句
| 场景/目标 (Scenario / Goal) |
BPF 捕获过滤器语法 (Capture Filter Syntax) |
“说人话”解释 |
| 1. 抓取所有802.1ad帧 |
ether proto 0x88a8 |
我不管你内外层VLAN是多少,只要是802.1ad这种套娃封装的,都给我抓出来。 |
| 2. 抓取特定外层S-TAG的流量 |
vlan 500 |
只要是运营商分配的S-TAG是500的流量,不管里面客户的C-TAG是啥,我都要。 |
| 3. 抓取特定内层C-TAG的流量 |
vlan and vlan 100 |
我不管外层运营商的S-TAG是啥,我只想看客户VLAN 100的流量。(注意:vlan and是用来占位的,确保vlan 100匹配的是第二层标签) |
| 4. 抓取精确的S-TAG+C-TAG组合 |
vlan 500 and vlan 100 |
我就要看运营商S-TAG是500,里面客户C-TAG是100的这一家人的流量。 |
| 5. 抓取特定QinQ隧道内的IP流量 |
vlan 500 and vlan 100 and ip |
在S-TAG 500、C-TAG 100这个隧道里,所有IP协议的流量都给我。 |
| 6. 抓取特定QinQ隧道内特定主机的流量 |
vlan 500 and vlan 100 and host 192.168.1.1 |
在S-TAG 500、C-TAG 100这个隧道里,我只想看跟192.168.1.1这台主机有关的通信。 |
1.1.1 终极奥义:vlan vs ether proto 的细微差别
- vlan 500:这个过滤器会匹配任何最外层VLAN ID是500的帧,不管它是802.1Q还是802.1ad封装的。
- ether proto 0x88a8 and vlan 500:这个过滤器则更精确,它只匹配802.1ad封装的、并且外层S-TAG是500的帧。
在大多数情况下,vlan关键字已经足够好用。但如果你在一个复杂的环境里,需要严格区分802.1Q和802.1ad,那么组合使用 ether proto会更严谨。
2 纯BPF/libpcap过滤表达式(标准原语)分析802.1ad网络故障
2.1 一、802.1ad基础识别
2.1.1 1. 802.1ad帧结构偏移
// 802.1ad帧结构(双标签)
| DMAC(6) | SMAC(6) | 外层TPID(0x88a8) | 外层TCI | 内层TPID(0x8100) | 内层TCI | EtherType | Payload |
// 偏移量: 0 6 12 14 16 18 20
// 检测802.1ad帧(外层S-VLAN)
ether[12:2] = 0x88a8
// 检测802.1ad内层C-VLAN存在
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100
// 检测单层802.1ad标签(无内层C-VLAN)
ether[12:2] = 0x88a8 and ether[16:2] != 0x8100 and ether[16:2] != 0x88a8
2.1.2 2. S-VLAN和C-VLAN ID提取
// 提取S-VLAN ID(外层标签)
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 // S-VLAN ID 100
// 提取C-VLAN ID(内层标签)
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and (ether[18:2] & 0x0fff) = 200 // C-VLAN ID 200
// 同时匹配S-VLAN和C-VLAN
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and ether[16:2] = 0x8100 and (ether[18:2] & 0x0fff) = 200
2.2 二、802.1ad配置故障检测
2.2.1 1. 标签配置错误
// 检测S-VLAN ID为0或4095(保留值)
ether[12:2] = 0x88a8 and ((ether[14:2] & 0x0fff) = 0 or (ether[14:2] & 0x0fff) = 4095)
// 检测S-VLAN ID超出范围
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) > 4094
// 检测C-VLAN ID为0但非优先级标记
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and (ether[18:2] & 0x0fff) = 0 and (ether[18:2] & 0xe000) = 0
// 检测三层802.1Q封装(错误的三重标签)
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and ether[20:2] = 0x8100
2.2.2 2. 选择性QinQ配置故障
// 检测应封装但未封装的C-VLAN
not ether[12:2] = 0x88a8 and ether[12:2] = 0x8100 and (ether[14:2] & 0x0fff) = 100
// 检测不应封装但被封装的C-VLAN
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and (ether[18:2] & 0x0fff) = 1 // VLAN 1通常不应封装
// 检测S-VLAN与C-VLAN映射错误(如:C-VLAN 100-200应映射到S-VLAN 10,但映射到了S-VLAN 20)
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 20 and ether[16:2] = 0x8100 and
((ether[18:2] & 0x0fff) >= 100 and (ether[18:2] & 0x0fff) <= 200)
2.2.3 3. MTU/帧大小问题
// 802.1ad增加8字节,检测可能超MTU的帧
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and greater 1522
// 检测因802.1ad封装导致分片的IP包
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and (ether[22:2] & 0x1fff) > 1500 // IP总长度大于1500
// 检测Jumbo帧与802.1ad兼容性
ether[12:2] = 0x88a8 and greater 9000
2.3 三、QoS/优先级故障检测
2.3.1 1. S-VLAN优先级标记
// 检测S-VLAN优先级(PCP)标记
ether[12:2] = 0x88a8 and (ether[14:1] & 0xe0) = 0xe0 // PCP=7(最高优先级)
// 检测语音流量在S-VLAN中的优先级
ether[12:2] = 0x88a8 and (ether[14:1] & 0xe0) != 0xe0 and ether[20:2] = 0x0800 and
((ether[22:1] & 0xfc) = 0xb8) and (ether[30:2] >= 16384 and ether[30:2] <= 32767) // DSCP EF + RTP端口
// 检测S-VLAN DEI标记异常
ether[12:2] = 0x88a8 and (ether[14:2] & 0x1000) != 0 and (ether[14:1] & 0xe0) = 0x00 // DEI=1但PCP=0
2.3.2 2. C-VLAN到S-VLAN优先级映射
// 检测C-VLAN优先级未正确映射到S-VLAN
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and
((ether[14:1] & 0xe0) != (ether[18:1] & 0xe0)) // S-VLAN PCP != C-VLAN PCP
// 检测业务优先级映射(如:语音业务C-VLAN PCP=5应映射到S-VLAN PCP=5)
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and (ether[18:1] & 0xe0) = 0xa0 and (ether[14:1] & 0xe0) != 0xa0
// 检测优先级重标记配置错误
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and (ether[14:1] & 0xe0) = 0x00 and (ether[18:1] & 0xe0) > 0x00
2.4 四、协议相关故障检测
2.4.1 1. ARP在802.1ad中的问题
// 检测S-VLAN中的ARP请求但C-VLAN不同
ether[12:2] = 0x88a8 and ether[20:2] = 0x0806 and
((ether[24:1] = 0x01) and (ether[34:4] & 0xffffff00) != (ether[44:4] & 0xffffff00))
// 检测Proxy ARP在802.1ad环境中的异常
ether[12:2] = 0x88a8 and ether[20:2] = 0x0806 and ether[24:1] = 0x02 and
ether[30:6] = ff:ff:ff:ff:ff:ff
// 检测Gratuitous ARP的VLAN不匹配
ether[12:2] = 0x88a8 and ether[20:2] = 0x0806 and ether[24:1] = 0x01 and
ether[34:4] = ether[44:4] and (ether[38:4] & 0xffffff00) != (ether[34:4] & 0xffffff00)
2.4.2 2. DHCP/BOOTP中继问题
// 检测DHCP Discover带Option 82在802.1ad中
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and (ether[22:1] & 0x0f) > 5 and
ether[27:1] = 0x11 and ether[32:2] = 68 and ether[34:2] = 67 and
(ether[54:1] = 0x0c or ether[56:1] = 0x80)
// 检测DHCP中继代理未正确处理802.1ad标签
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] = 67 and ether[22:16:4] = 255.255.255.255
// 检测DHCP服务器响应中的VLAN信息不匹配
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] = 68 and (ether[22:1] & 0x80) = 0x00 and
(ether[14:2] & 0x0fff) != (ether[64:2] & 0x0fff) // S-VLAN ID != Option 82中的VLAN
2.4.3 3. 生成树协议在802.1ad中
// 检测MSTP在802.1ad中的BPDU
ether[12:2] = 0x88a8 and ether[20:2] = 0x4242 and ether[22:1] = 0x03
// 检测RSTP BPDU在802.1ad中(可能配置错误)
ether[12:2] = 0x88a8 and ether[20:2] = 0x4242 and ether[22:1] = 0x02
// 检测PVST+ BPDU在802.1ad中
ether[12:2] = 0x88a8 and ether[20:2] = 0x4242 and ether[22:1] = 0x00 and
(ether[14:2] & 0x0fff) != 1
2.5 五、服务提供商网络故障
2.5.1 1. 运营商边界问题
// 检测用户侧发送的802.1ad帧(不应发生)
ether[12:2] = 0x88a8 and ether[0:6] = <用户设备MAC>
// 检测运营商网络内部泄露用户C-VLAN
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and
((ether[18:2] & 0x0fff) >= 2 and (ether[18:2] & 0x0fff) <= 100) // 用户VLAN范围
// 检测多运营商互通时的TPID不匹配
ether[12:2] = 0x88a8 and ether[16:2] != 0x8100 and ether[16:2] != 0x88a8 and
ether[16:2] != 0x9100 and ether[16:2] != 0x9200 and ether[16:2] != 0x9300 // 非标准TPID
2.5.2 2. E-Line/E-LAN服务故障
// 检测E-Line(点到点)服务中的广播流量
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and
ether[0:6] = ff:ff:ff:ff:ff:ff
// 检测E-LAN(多点到多点)服务中的未知单播
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 200 and
(ether[0:1] & 0x01) = 0x00 and not ether dst host <已知MAC>
// 检测VPLS中的水平分割违规
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and
ether[22:12:4] = ether[22:16:4] // 源IP = 目的IP(环回)
2.5.3 3. Q-in-Q与MAC-in-MAC交互
// 检测802.1ah (MAC-in-MAC) over 802.1ad
ether[12:2] = 0x88a8 and ether[20:2] = 0x88e7
// 检测PBB (802.1ah) 与Q-in-Q结合的问题
ether[12:2] = 0x88a8 and ether[20:2] = 0x88e7 and
(ether[30:2] = 0x8100 or ether[30:2] = 0x88a8) // PBB内的VLAN标签
2.6 六、安全攻击检测
2.6.1 1. VLAN跳跃/Q-in-Q攻击
// 检测恶意三重标签攻击
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and ether[20:2] = 0x8100
// 检测S-VLAN欺骗攻击
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 0 and
ether[0:6] != <运营商设备MAC>
// 检测C-VLAN伪装攻击
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and
(ether[18:2] & 0x0fff) = 1 and (ether[14:2] & 0x0fff) != 4095 // C-VLAN 1但S-VLAN不是4095
2.6.2 2. ARP欺骗在802.1ad环境
// 检测跨S-VLAN的ARP欺骗
ether[12:2] = 0x88a8 and ether[20:2] = 0x0806 and ether[24:1] = 0x01 and
ether[34:4] = ether[44:4] and
((ether[38:4] & 0xffffff00) != (ether[34:4] & 0xffffff00))
// 检测网关ARP投毒在802.1ad中
ether[12:2] = 0x88a8 and ether[20:2] = 0x0806 and ether[24:1] = 0x02 and
ether[34:4] = <网关IP> and ether[34:6] != <网关MAC>
2.6.3 3. MAC地址泛洪攻击
// 检测S-VLAN内的MAC泛洪
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and
(ether[6:1] & 0x01) = 0x00 // 源MAC不是多播
// 检测C-VLAN MAC泛洪影响S-VLAN
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and
(ether[6:1] & 0x01) = 0x00 and rate() > 10000/1s
2.7 七、性能与容量问题
2.7.1 1. 广播风暴检测
// S-VLAN内广播风暴
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and
ether[0:6] = ff:ff:ff:ff:ff:ff
// C-VLAN广播泄漏到S-VLAN
ether[12:2] = 0x88a8 and ether[16:2] = 0x8100 and
ether[0:6] = ff:ff:ff:ff:ff:ff
// 检测多播泛滥
ether[12:2] = 0x88a8 and (ether[0:1] & 0x01) = 0x01 and
ether[0:2] != 0x3333 and ether[0:2] != 0x0100 // 排除IPv6和STP多播
2.7.2 2. 带宽与拥塞问题
// 检测高优先级流量拥塞
ether[12:2] = 0x88a8 and (ether[14:1] & 0xe0) = 0xe0 and
greater 1400 and rate() > 1000000/1s // 1Mpps
// 检测TCP重传在802.1ad环境中
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and (ether[22:1] & 0x0f) > 5 and
ether[27:1] = 0x06 and (ether[37:1] & 0x04) != 0 // TCP RST
// 检测UDP丢包(通过序列号间隙)
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] >= 16384 and ether[32:2] <= 32767 // RTP端口范围
2.8 八、高级诊断表达式
2.8.1 1. 运营商网络诊断
// 检测不同S-VLAN间的路由泄漏
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 10 and ether[20:2] = 0x0800 and
(ether[22:12:4] & 0xffffff00) = 192.168.20.0 and
(ether[22:16:4] & 0xffffff00) = 192.168.30.0
// 检测MPLS over 802.1ad问题
ether[12:2] = 0x88a8 and ether[20:2] = 0x8847 // MPLS unicast
ether[12:2] = 0x88a8 and ether[20:2] = 0x8848 // MPLS multicast
// 检测VPLS控制平面问题
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] = 646 and ether[34:2] = 646 // LDP端口
2.8.2 2. 数据中心互联(DCI)
// 检测VXLAN over 802.1ad
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] = 4789 // VXLAN端口
// 检测NVGRE over 802.1ad
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and (ether[22:1] & 0x0f) > 5 and
ether[27:1] = 0x2f // IPv4协议号47 (GRE)
// 检测STT over 802.1ad
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x06 and
ether[32:2] = 7471 // STT端口
2.8.3 3. 移动承载网络
// 检测GTP-U over 802.1ad
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
(ether[32:2] = 2152 or ether[34:2] = 2152) // GTP-U端口
// 检测同步以太网(SyncE)在802.1ad中
ether[12:2] = 0x88a8 and ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
ether[32:2] = 319 and ether[34:2] = 320 // PTP事件和通用消息
// 检测1588 PTP在802.1ad中的优先级
ether[12:2] = 0x88a8 and (ether[14:1] & 0xe0) != 0xe0 and
ether[20:2] = 0x0800 and ether[27:1] = 0x11 and
(ether[32:2] = 319 or ether[32:2] = 320)
2.9 九、优化与调试技巧
2.9.1 1. 性能优化表达式
// 只捕获特定S-VLAN的特定协议
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and
(ether[20:2] = 0x0800 or ether[20:2] = 0x0806 or ether[20:2] = 0x86dd)
// 排除广播/多播以关注单播问题
ether[12:2] = 0x88a8 and (ether[0:1] & 0x01) = 0x00
// 采样捕获以减少负载
ether[12:2] = 0x88a8 and (random() & 0xff) < 25 // 约10%采样率
2.9.2 2. 调试特定问题
// 调试S-VLAN 100的连通性问题
ether[12:2] = 0x88a8 and (ether[14:2] & 0x0fff) = 100 and
(ether[20:2] = 0x0806 or (ether[20:2] = 0x0800 and
(ether[22:12:4] = <源IP> or ether[22:16:4] = <目的IP>)))
// 调试QoS标记问题
ether[12:2] = 0x88a8 and ((ether[14:1] & 0xe0) = 0x00 or (ether[14:1] & 0xe0) = 0xe0)
// 调试MTU相关问题
ether[12:2] = 0x88a8 and greater 1500 and
(ether[20:2] = 0x0800 and (ether[22:2] & 0x1fff) > 1500)
这些纯BPF表达式完全使用标准原语和偏移量计算,不依赖vlan1/vlan2等扩展原语,可以在所有标准libpcap实现中使用。通过组合这些表达式,可以高效诊断802.1ad网络中的各种故障。