第四节:数据链路层测试——MAC地址过滤与欺骗、帧结构验证、交换机转发行为
各位同行,今天我们来聊聊数据链路层的测试。这一层在OSI模型里排第二,但说实话,它才是网络通信真正开始干活的地方。物理层只管把比特流扔出去,而数据链路层要管帧的格式、地址的识别、还有错误检测。我这些年做协议测试,踩坑最多的就是这一层。
咱们分三个大块来讲:MAC地址的过滤与欺骗测试、帧结构验证(前导码和CRC校验)、以及交换机/网桥的转发行为测试。每个点我都会结合自己的项目经验来说,希望能帮你少走弯路。
4.1 MAC地址过滤与欺骗测试
MAC地址过滤,说白了就是交换机或AP根据源MAC地址来决定让不让这个帧通过。很多企业网络会用这个做简单的准入控制。但我要告诉你,这玩意儿其实很脆弱。
4.1.1 MAC地址过滤的测试方法
测试MAC地址过滤,我一般分三步走:
- 白名单测试:配置只允许特定MAC地址通信,然后发送来自该MAC的帧,验证能通过;再发送其他MAC的帧,验证被丢弃。
- 黑名单测试:反过来,禁止某个MAC地址,验证该MAC的帧被丢弃,其他正常。
- 广播/组播测试:有些设备对广播帧的过滤规则不一样,需要单独验证。
关键点:测试时一定要同时抓取入口和出口的报文。我遇到过设备声称支持MAC过滤,但实际上只是把帧标记了丢弃,并没有真正从队列里移除——结果就是CPU负载飙升。
4.1.2 MAC地址欺骗测试
MAC地址欺骗,就是伪造一个合法的MAC地址来绕过过滤。这个测试很重要,因为很多安全方案都依赖MAC地址的唯一性。
我常用的测试工具是Scapy,简单几行代码就能伪造MAC地址:
from scapy.all import *
# 伪造源MAC地址为 00:11:22:33:44:55
packet = Ether(src="00:11:22:33:44:55", dst="ff:ff:ff:ff:ff:ff") / IP(dst="192.168.1.1")
sendp(packet, iface="eth0")
测试时,我会先让合法的MAC地址通过,然后立刻用伪造的相同MAC发送帧。如果设备没有做MAC和端口的绑定(比如802.1X),那伪造的帧大概率能混进去。
注意:MAC欺骗测试可能会触发交换机的MAC地址漂移告警。我在一次测试中,因为伪造帧频率太高,直接把交换机的控制平面打挂了。建议控制发包速率,每秒10-20个帧就够了。
4.2 帧结构验证:前导码与CRC校验
以太网帧的结构,教科书上都讲过:前导码、定界符、目标MAC、源MAC、类型/长度、数据、填充、FCS(CRC校验)。但实际测试中,很多细节容易被忽略。
4.2.1 前导码验证
前导码是7个字节的0x55,加上1个字节的0xD5(定界符)。它的作用是让接收端同步时钟。我见过不少设备对前导码的长度很敏感。
测试方法:用硬件发包仪(比如Spirent或IXIA)发送不同长度的前导码:
- 标准7字节前导码 + 1字节定界符
- 缩短的前导码(比如5字节)
- 延长的前导码(比如9字节)
我记得有一次测试某款国产交换机,发送缩短的前导码时,设备直接丢帧了。查了半天,发现是PHY芯片的同步逻辑太死板。后来厂商更新了驱动才解决。
4.2.2 CRC校验测试
CRC校验是帧的最后一层防线。接收端计算CRC,如果和帧尾的FCS不匹配,就丢弃该帧。测试CRC校验,核心就是构造错误CRC的帧。
用Scapy构造错误CRC:
from scapy.all import *
import struct
# 构造一个正常帧
frame = Ether(dst="ff:ff:ff:ff:ff:ff") / IP(dst="192.168.1.1") / ICMP()
# 手动修改FCS为错误值
raw_frame = bytes(frame)
wrong_fcs = struct.pack("<I", 0xDEADBEEF) # 故意写错
bad_frame = raw_frame[:-4] + wrong_fcs
sendp(bad_frame, iface="eth0")
小技巧:测试时不仅要验证错误CRC被丢弃,还要验证设备是否记录CRC错误计数。很多交换机的"show interface"命令里都有CRC error计数器,这个值应该增加。
另外,有一种特殊情况叫"CRC对齐错误"。如果帧的总长度不是整数字节(比如多了一个bit),接收端会报alignment error。这个在10M半双工环境下偶尔会出现,现在基本见不到了,但测试时还是建议覆盖一下。
4.3 交换机/网桥转发行为测试
交换机的核心功能就是根据MAC地址表转发帧。测试转发行为,说白了就是验证三件事:学得对不对、转得准不准、丢得干不干净。
4.3.1 MAC地址学习测试
测试步骤:
- 从端口1发送一个源MAC为A的帧
- 检查交换机的MAC地址表,确认A被学习到端口1
- 从端口2发送目标MAC为A的帧,验证帧被转发到端口1
- 老化时间测试:等待老化时间(默认300秒),再发送目标MAC为A的帧,验证被泛洪
我遇到过一个问题:某款交换机在MAC地址表满的时候,行为不符合标准。标准要求应该泛洪,但它直接丢包了。这种问题在压力测试下才暴露出来。
4.3.2 转发与过滤测试
这里要验证几个场景:
| 测试场景 | 输入 | 期望行为 |
|---|---|---|
| 单播已知 | 目标MAC在地址表中 | 只转发到对应端口 |
| 单播未知 | 目标MAC不在地址表中 | 泛洪到所有端口(除入端口) |
| 广播 | 目标MAC为FF:FF:FF:FF:FF:FF | 泛洪到所有端口(除入端口) |
| 组播 | 目标MAC为01:00:5E:xx:xx:xx | 取决于IGMP Snooping配置 |
测试时,我习惯用三台设备:一台发包、一台收包、一台做监听。监听端口用来确认帧是否出现在不该出现的端口上。
4.3.3 VLAN转发测试
如果交换机支持VLAN,那测试要更细致。核心原则:帧只能在同一个VLAN内转发。
测试方法:
- 配置端口1和端口2属于VLAN 10,端口3属于VLAN 20
- 从端口1发送广播帧,验证端口2收到,端口3收不到
- 从端口1发送目标MAC为端口3的帧,验证被丢弃
避坑指南:我曾经测试过一款设备,VLAN配置后端口3仍然能收到广播帧。查了三天,发现是芯片的VLAN表项没有正确写入。所以测试时一定要同时看软件配置和硬件表项是否一致。
4.4 本章知识体系
下面这张图是我自己整理的,把数据链路层测试的核心逻辑串起来了:
这张图把三个测试方向的关系理清楚了。你想想看,MAC地址过滤和交换机转发其实是同一枚硬币的两面——过滤是拒绝,转发是允许。而帧结构验证是这两者的基础,帧都不合法,后面的转发和过滤就无从谈起。
4.5 测试工具推荐
最后,我列一下自己常用的工具组合:
- Scapy:构造自定义帧,做MAC欺骗和CRC错误测试,免费且灵活
- Wireshark:抓包分析,验证帧结构是否正确
- Spirent TestCenter / IXIA:专业级性能测试,做大规模MAC学习、转发压力测试
- Linux bridge + netfilter:快速搭建测试环境,验证转发逻辑
嗯,数据链路层的测试就讲到这里。记住一句话:帧是网络通信的最小单元,把帧测透了,上层协议的问题往往就迎刃而解。
公众号:蓝海资料掘金营,微信deep3321