干网络排障这行,总有新手拿着抓包软件问我:这显示的到底是“包”还是“帧”?还有人会把“链路层”和“网络层”混在一起分析,结果过滤条件写错、判断方向跑偏,查了半天才发现看的是不同层面的东西。这个困惑太常见了,所以我想围绕“从帧到包”这条主线,把链路层与局域网通信的核心机制掰开揉碎讲一遍,讲清楚帧是什么、包是什么、MAC怎么寻址、交换机怎么转发、ARP怎么工作,以及真正动手排查二层问题时应该从哪里下手。这篇文章适合刚接触网络基础、正在学抓包排障,或者对局域网通信机制一知半解想系统梳理一遍的人。
1. 帧与包:先把这个概念理清楚,后面才不白忙活
1.1 帧和包到底差在哪——从一次抓包说起
很多人第一次用抓包工具,看到一行一行的记录,习惯性地说“抓到一个包”。其实严格来讲,抓包软件在网卡上收到的每一个条目,是一个“帧”。帧是链路层的协议数据单元,而“包”或者说“数据报”,严格对应的是网络层(IP层)的协议数据单元。
关键区别在于,IP包是“内容”,帧是“包装”。当你的电脑要发送一个IP数据报时,这个数据报会往下传给链路层,链路层在它前面加上目的MAC地址、源MAC地址、类型字段,在它后面加上帧校验序列,然后才交给物理层变成比特流发出去。接收端收到后,先把帧头帧尾剥离,把中间的IP数据报提取出来,再往上交给网络层处理。
我用快递来打个比方:IP包是你要寄的那本书,帧是快递公司给它套上的纸箱、填的快递单、贴的封条。书的内容是网络层关心的,纸箱和快递单是链路层关心的。寄件人和收件人看的是书,快递员只看纸箱上的地址。
这个理解直接影响实际排障。比如在抓包工具里,你想过滤某个设备的流量,如果知道的是IP地址,就用ip.addr;如果你知道的是MAC地址,就得用eth.addr。很多人搞错过滤条件,其实根子就在于没分清自己要看的是“包”还是“帧”。有一次排查一个二层环路问题,对方一直用ip.addr过滤找源IP,结果看到大量来源相同、目的不同的广播帧,实际上问题出在链路层,该用eth.addr或直接看二层头部才对。
1.2 分层的本质:每一层只干自己该干的事
为什么非要区分得这么细?因为网络通信本身就是分层的。OSI七层模型也好,TCP/IP四层模型也好,核心思想都是“每一层只解决自己那一层的难题,把其他问题交给上下层”。
链路层解决的是“相邻节点之间怎么把比特流安全可靠地送到对端”。这里的“相邻节点”,指的是物理上直连或者在同一个二层广播域内的设备。链路层根本不关心数据要去哪个城市、走哪条路,它只负责把这一“车货”交到下一站。而网络层解决的是“数据怎么在多个网络之间找到路径”,它需要全局的拓扑信息,通过IP地址来寻址。
理解这一点,很多现象就说得通了。比如两个不同网段的设备,即使连着同一台交换机,也不能直接用MAC地址通信,因为交换机只知道“网线插在哪个口”,不知道“IP地址对应的路径”。跨网段通信必须经过网关,也就是路由器,由网络层做路由决策,再把包交给下一个链路的链路层重新封装成新的帧。
有个典型的认知误区是:认为交换机是“智能转发设备”,所以它能理解IP。实际上交换机主要工作在链路层,它看的是MAC地址,对IP地址最多做一点“顺带看一眼”的工作(比如某些三层交换机的某些功能)。真正理解IP、做路由决策的是路由器或三层设备。明白这个分工,排障时就不会拿着一台交换机非要查IP路由表了。
2. 链路层核心机制拆解:MAC、FCS与封装
2.1 以太网帧格式:从比特流到帧结构
以太网是链路层最常见的实现方式,它的帧结构很值得逐字段拆一遍。一个标准的以太网II帧,物理层会先发出7字节的前导码(全10101010的交替序列)和1字节的帧起始定界符,用来让接收方同步时钟、确认帧的开始。然后才是真正的帧本体:
| 字段 | 长度 | 说明 |
|---|---|---|
| 目的MAC地址 | 6字节 | 接收方的物理地址 |
| 源MAC地址 | 6字节 | 发送方的物理地址 |
| EtherType | 2字节 | 表示上层协议,如0x0800是IPv4、0x86DD是IPv6、0x0806是ARP |
| 数据 | 46-1500字节 | 网络层下发的数据报 |
| 帧校验序列FCS | 4字节 | CRC-32校验值,用于检测传输错误 |
这里面有几个数字值得记住。数据段最小是46字节,最大是1500字节(这1500就是常说MTU)。如果IP包太小,链路层会补零到46字节;如果IP包太大,超过1500,就需要分片。整个帧加上14字节的头部和4字节的尾部,最小是64字节,最大是1518字节。如果交换机端口开启了VLAN功能,会在源MAC和EtherType之间插入4字节的802.1Q标签,最大帧就变成1522字节。
为什么数据段非得有最小46字节?这是从历史沿袭下来的老规矩。早期以太网是共享介质、半双工工作,用CSMA/CD协议来避免冲突。一个站点发送数据后,如果发生冲突,必须在这个帧的传输过程中就能检测到,否则这个帧就被确认“成功发送”了。为了保证在最远的网络距离上也能检测到冲突,规定帧长不能小于64字节。所以即使上层数据很少,也要填充到46字节。今天全双工交换网络已经不存在冲突域了,但这个最小帧长约束仍然保留。
2.2 MAC地址寻址:局域网内的“门牌号”规则
MAC地址是链路层寻址的基础,一共48位,写作12个十六进制字符,比如00:1A:2B:3C:4D:5E。它分成两部分:前24位是厂商代码OUI,由IEEE分配给网卡制造商;后24位是厂商自己分配的序列号,理论上全球唯一。实际操作中,虚拟机和部分网卡支持修改MAC,但同一局域网内MAC冲突还是会真实影响通信。
MAC地址的第一个字节里,最低位(第8位)表示单播/多播:0是单播,1是多播。全1的48位FF:FF:FF:FF:FF:FF是广播地址,表示发给同一广播域内的所有设备。还有一个很容易忽略的字段是“本地管理位”,也就是第一个字节的倒数第二位,0表示全球唯一(由厂商分配),1表示本地自行管理。Windows下手动修改网卡MAC后,常会看到第二位变成1。
交换机转发数据靠的就是一张MAC地址表。这张表的核心内容是“MAC地址”和“端口”的对应关系。那MAC表是怎么建起来的?不是配置出来的,是交换机自己学习的。后面我会细说它的工作过程。
2.3 FCS与CRC:怎么知道一帧数据有没有坏
帧尾巴上的4字节FCS,用的是CRC-32算法。这个算法把整个帧(不含前导码和FCS本身)看作一个巨大的二进制数,除以一个固定的生成多项式(0x04C11DB7,反射形式是0xEDB88320),余数作为校验值附在帧尾。接收方收到帧后,用同样的方式重新计算,如果计算出的余数是0,说明数据在传输中没有被篡改;如果不是0,说明这一帧坏了,直接丢弃,由上层协议(比如TCP的重传机制)负责补救。
CRC-32的检错能力非常强:它能检测出所有奇数个比特错误、所有长度不超过32比特的突发错误,以及绝大多数更长的突发错误。但要注意,它并不能纠正错误,检测出错误后只能丢弃。这也是链路层“尽力而为”的表现——它保证的是“收到的帧大概率是完整的”,但不保证“一定能送达”。
如果抓包时看到大量“bad FCS”或者“frame check sequence”错误,基本可以断定物理链路有问题,可能是网线老化、水晶头接触不良、光模块信号衰减,或者两端双工模式不匹配。这种问题在网络层是看不出来的,因为IP层根本看不到FCS,只有在链路层抓原始帧才能发现。
3. 局域网通信是怎么“找到对方”的——ARP与交换机工作机制
3.1 ARP的完整工作链路
局域网里两台主机通信,网络层用的是IP地址,可链路层转发帧只认MAC地址。那怎么把IP地址翻译成MAC地址?这个翻译工作就是ARP协议干的。
我拿一个最经典的场景走一遍:主机A(IP为192.168.1.10)第一次要ping主机B(IP为192.168.1.20)。A知道B的IP,但不知道B的MAC,于是:
- A先查自己的ARP缓存表,发现没有B的映射。
- A在网络层构造好ICMP请求包之后,要先解决“把包封装进什么MAC帧里”。它不知道B的MAC,于是发一个ARP请求:源MAC是A自己的,目的MAC是
FF:FF:FF:FF:FF:FF,内容大致是“谁的IP是192.168.1.20?请把你的MAC地址告诉192.168.1.10”。 - 这个广播请求进入交换机,交换机发现目的MAC是广播地址,就把这个帧从除接收端口以外的所有端口转发出去。所以同一广播域内的所有设备都会受到这个请求。
- 主机B收到后,发现问的是自己,就回应一个ARP应答,这是单播帧,目的MAC是A的MAC,内容就是“192.168.1.20的MAC是XX:XX:XX:XX:XX:XX”。
- A收到应答,把IP和MAC的映射写入ARP缓存,然后才真正发出那个ICMP echo请求。
这个过程中容易忽略一个细节:B在收到A的ARP请求时,会把“192.168.1.10对应A的MAC”也写进自己的ARP缓存。为什么?因为B马上要回ARP应答,回完以后大概率还要跟A通信,提前学一步,能省一次广播请求。
这里还有几个ARP相关的知识点值得讲。第一,ARP缓存是有老化时间的,Windows系统一般是2到10分钟,Linux系统常见是30秒左右,不同系统差异很大,这会导致首次通信偶尔延迟或抓包时看到定期的ARP请求再刷新。第二,免费ARP(Gratuitous ARP),指主机启动或者IP地址变更后,主动广播一个ARP请求来询问自己的IP,目的不是让别人回答,而是告诉整个广播域“这个IP现在归我用了”,同时用于检测IP地址冲突。如果你抓包看到某台主机反复发免费ARP,那很可能是在抢IP或者在宣告主备切换。
还有一种情况很常见:主机A要访问另一个子网的主机C,它发现C不在自己的网段内,于是不直接请求C的MAC,而是把包交给默认网关。这时A发出的ARP请求,问的是网关的MAC地址,而不是C的MAC。很多人一抓包发现目标全在问网关,还以为有问题,其实这是完全正常的行为。
3.2 交换机是如何学习和转发帧的
交换机是局域网通信的核心设备,我来还原一台交换机从零开始学习的过程。
假设一台交换机刚上电,MAC地址表是空的。某天主机A从端口1发来一个帧,目的MAC是主机B。交换机会做三件事:
- 学习:把“源MAC = A的MAC”记录到表中,并绑定端口1。这样以后任何发往A的帧,交换机都知道该从端口1出去。
- 查表:交换机查找目的MAC在不在自己的MAC地址表里。
- 转发决策:如果表里有目的MAC的记录,交换机就把帧从对应的端口转发出去,这叫“精确转发”。如果表里没有,说明交换机还不知道目的设备在哪,它就把帧从除了接收端口以外的所有端口复制一份发出去,这叫“泛洪”。
接下来主机B收到帧,回复给主机A。交换机从端口2收到B的回包,又学到“B的MAC对应端口2”。等下一轮A发给B时,交换机查表发现B已经在端口2了,就只往端口2发,不再泛洪。
这里有几个细节容易踩坑。一是MAC地址表的条目不永久有效,通常老化时间是300秒(约5分钟),如果这期间设备不再发帧,交换机就删掉这个条目,下次通信又要重新泛洪。这是正常的,不是故障。二是有一种情况要特别警惕:如果交换机从端口1收到一个源MAC的帧,而MAC表里这个源MAC恰好已经对应端口1,那就刷新一下老化时间;但要是表里记录这个MAC对应端口2,端口1却又收到了同样源MAC的帧,这就是“MAC地址漂移”,说明网络里可能存在环路,或者有人插了不该插的线。
三是交换机对广播帧、组播帧的处理:只要目的MAC是多播或广播地址,交换机一律泛洪。所以在抓包时看到大量广播帧并不稀奇,但如果广播流量异常高、甚至占到总流量的百分之三四十,就要怀疑是不是有二层环路、ARP攻击或者某些设备在疯狂重传。四是交换机MAC表容量有限,如果表被恶意MAC泛洪攻击塞满,交换机会进入“故障保护”模式,对所有未知单播帧都泛洪,整个局域网效率直线下降,严重时跟用集线器没区别。这也是二层安全里必须做端口MAC限制(port-security)的原因。
4. 实战排查:链路层问题怎么定位
4.1 抓包如何区分帧与包
聊天讨论了不少理论,现在上点实操。真正到了抓包排障的时候,第一个要明确的还是“我到底该看帧还是看包”。
在抓包软件里,默认每一行记录本质上是一个帧。这行的“Length”字段,指的是整个以太网帧的长度,包含14字节的链路层头部和末尾的4字节FCS。所以你看到的IP包大小,和帧大小之间,总是差着18字节。如果你看到帧大小是1518,说明IP包几乎塞满了1500字节的MTU;如果你看到帧大小是64字节,那是一个最小的以太网帧,里面往往只装了极少量数据(比如TCP ACK,再加上各种可选头部就刚好凑到64字节)。
排查链路层问题时,我习惯这样操作:
- 先用
eth.addr == 某个MAC过滤,只观察这台设备的二层流量。 - 如果怀疑ARP异常,直接加过滤条件
arp,一眼就能看出谁在发大量ARP请求。 - 检查是否有“Duplicate IP address detected”之类的提示,这种报文通常是免费ARP冲突检测发出来的。
- 再看是否有
Bad checksum或FCS错误提示,如果频繁出现,基本锁定物理层问题。 - 结合帧长度做统计:大量长度64字节的小帧,往往是控制报文(ARP、TCP ACK)或者协议探测;大量1518字节的大帧,说明在跑大流量传输。
有一个真实案例,某单位网络隔一阵就卡顿几分钟,抓包一看,交换机上有一台设备在不断向一个已经不存在的单播MAC地址发送大量帧,目的MAC在MAC表里查不到,交换机只能不停泛洪,占满了下行带宽。从网络层看,这些帧没有对应任何正常的IP会话,纯属底层异常;从链路层看,帧长度、格式也没问题,就是目的MAC地址“没人要”。最后找到那台设备,发现是一个业务系统的后台服务在向旧网关地址发心跳,配置更新后问题消失。这个排查的关键点在于:不要一上来就看IP,先把目的MAC放进MAC表里查一查。
4.2 MAC地址表与环路问题
二层环路是局域网里非常经典的故障。环路产生的原因通常是把交换机的两根线做了冗余连接,却没启用生成树协议(STP/RSTP),或者生成树被误关闭。环路一旦出现,广播帧会在环路里无限循环转发,形成“广播风暴”,整个局域网几乎瘫痪。
排查二层环路的思路,我按优先级整理如下:
- 看交换机CPU负载:如果CPU利用率飙升,先怀疑环路或攻击。
- 看MAC地址表是否出现漂移:连续多次执行查看MAC表的命令,如果发现同一个MAC不断在不同端口之间跳动,基本可以肯定是环路。
- 抓包统计广播帧和未知单播帧数量:如果数量异常大,说明有帧在循环。
- 检查生成树状态:确认端口是否处于转发或阻塞状态,看看有没有端口一直不停切换状态。
- 用物理手段二分定位:拔掉可疑链路,观察广播流量是否下降。这个方法粗暴但有效,排查环路时往往比理论分析更快。
说一个我踩过的坑:实验室里为了冗余,用两根网线把两台交换机连起来,忘了开STP,结果整个实验网广播帧爆炸,远程设备全部失联。到现场一看,交换机端口指示灯疯狂闪烁,用命令看MAC表出现大量漂移记录。最后拔掉一根线,网络瞬间恢复。这个案例说明,STP不是可选项,是必须项。现在新交换机默认可能开启RSTP,但很多改过配置的设备会把生成树关掉,所以确认环境时需要自己检查一下。
4.3 常见问题速查表
| 现象 | 可能原因 | 优先排查手段 |
|---|---|---|
| 同网段主机ping不通 | ARP解析失败、IP冲突 | 先看arp -a有无对端条目;再抓包看有无ARP应答 |
| 全网广播流量异常高 | 二层环路、MAC泛洪攻击 | 查交换机MAC表漂移、检查STP状态、拔线二分 |
| 大流量传输频繁中断 | FCS错误增多、双工模式不匹配 | 抓包看bad FCS、检查两端协商速率 |
| 帧长度超过1518字节 | MTU设置不一致、巨型帧 | 检查两端MTU、关闭巨型帧或统一配置 |
| 交换机频繁泛洪 | MAC表被塞满、老化过快 | 查端口MAC数量、启port-security |
| 能上网但内网互相不通 | VLAN配置错误、端口类型不对 | 检查access/trunk端口与VLAN划分 |
还有一个排查小技巧想分享:当你觉得问题可能出在二层时,先不要急着分析IP层。拿一台电脑接在交换机上,用arp -a看网关、看目标机的MAC解析情况。如果ARP表里根本没有对方条目,就说明二层解析阶段已经失败了,再往上分析IP层纯属浪费时间。如果ARP有条目但依然不通,那再看看是不是端口安全、VLAN隔离等策略拦住了。这个顺序能帮你省掉很多无效排查。
我个人做实验的时候还有个习惯:每次搭完二层环境,第一件事就是清空所有设备的ARP缓存和交换机的动态MAC表,让整个网络“从零开始”学习一遍。这样做的好处是能观察到最完整的学习过程,排查问题时也能排除旧缓存带来的干扰。尤其在模拟器和实验平台里,这个操作只要几条命令就能完成,但对理解“从帧到包”的整个过程帮助特别大。
最后再聊一点实际感触。链路层的坑往往不像应用层那么直观,它藏得深,一出问题影响面却极大。但只要你盯着“帧”不放——看目的MAC、看FCS、看交换机的MAC表——大部分问题都能找到源头。网络这东西,分层理解得越透,排障越有底气。