2、以太网帧与MAC地址:MAC地址结构,以太网帧格式,ARP协议工作原理

聊完粘包拆包,咱们得先搞清楚数据在网络上到底是怎么“打包”的。你想想看,应用层的数据要发出去,得一层层往下封装。到了数据链路层,就绕不开以太网帧和MAC地址。这一节,我就带你把这层底裤扒干净。

2.1 MAC地址结构

MAC地址,也叫物理地址、硬件地址。说白了,就是网卡在出厂时被烧录的一个唯一标识。我刚开始做嵌入式开发时,总觉得这东西跟IP地址差不多,后来踩了坑才明白——它俩完全不是一个层面的东西。

MAC地址长什么样?48位,6个字节。通常用十六进制表示,比如 00:1A:2B:3C:4D:5E。前3个字节是OUI(组织唯一标识符),由IEEE分配给厂商;后3个字节是厂商自己分配的序列号。

MAC地址结构拆解:

  • 第1字节最低位(bit 0):I/G位。0表示单播,1表示组播。
  • 第1字节次低位(bit 1):G/L位。0表示全局唯一(由IEEE分配),1表示本地管理。
  • 前3字节(OUI):厂商代码。比如00:1A:2B是某厂商的。
  • 后3字节(NIC):接口序列号。由厂商自行分配,保证不重复。

我曾经在调试一个网络设备时,发现两台设备的MAC地址一模一样。查了半天,原来是某小厂烧录时没按规范来,直接复制了。嗯,这种坑,遇到了你就知道MAC地址唯一性有多重要。

小技巧:抓包时看到MAC地址第一个字节是奇数(比如01:xx:xx:xx:xx:xx),那一定是组播或广播地址。广播地址就是全F:FF:FF:FF:FF:FF:FF。

2.2 以太网帧格式

数据在以太网上传输,必须封装成帧。目前最常用的是Ethernet II帧格式,也叫DIX帧。IEEE 802.3也有自己的帧格式,但实际网络中99%都是Ethernet II。

以太网帧长什么样?我直接给你画出来:

+----------------+----------------+----------------+----------------+----------------+----------------+
|  前导码 (7B)   | 帧定界符 (1B)  | 目标MAC (6B)   | 源MAC (6B)     | 类型/长度 (2B) | 数据 (46-1500B) |
+----------------+----------------+----------------+----------------+----------------+----------------+
|                                                                                               |   FCS (4B)    |
+-----------------------------------------------------------------------------------------------+---------------+

字段说明:

字段 长度 说明
前导码 7字节 用于同步时钟,内容是10101010...的交替位
帧定界符(SFD) 1字节 固定为10101011,标志帧开始
目标MAC地址 6字节 接收方网卡的MAC地址
源MAC地址 6字节 发送方网卡的MAC地址
类型/长度 2字节 Ethernet II中表示上层协议类型(如0x0800=IP),802.3中表示数据长度
数据 46-1500字节 上层协议数据(IP包),不足46字节需填充
FCS 4字节 帧校验序列,使用CRC32校验整个帧(不含前导码和SFD)

注意:数据字段最小46字节,最大1500字节。1500就是MTU(最大传输单元)。如果IP包超过1500字节,就得分片。我在做视频传输优化时,就遇到过MTU设置不当导致大量分片重传的问题,性能直接掉一半。

这里有个细节:类型字段如果值大于等于0x0600(1536),就是Ethernet II帧,表示上层协议类型;如果小于等于0x05DC(1500),就是802.3帧,表示数据长度。实际抓包时,你看到的几乎都是Ethernet II帧。

2.3 ARP协议工作原理

现在问题来了:我知道目标IP地址,但不知道目标MAC地址,怎么把帧发出去?这就是ARP协议要干的事。

ARP(Address Resolution Protocol),地址解析协议。它的作用很简单:根据IP地址获取MAC地址。我当年第一次接触这个协议时,觉得它太简单了,不就是问一下嘛。后来做网络诊断时才发现,ARP攻击、ARP欺骗、ARP缓存超时……坑多着呢。

ARP工作原理分几步:

  1. 查询ARP缓存:先看本地ARP缓存表里有没有目标IP对应的MAC地址。有就直接用,没有就发ARP请求。
  2. 发送ARP请求:广播一个ARP请求包。目标MAC地址填全F(广播地址),问“谁的IP是192.168.1.1?请告诉我你的MAC地址”。
  3. 目标回复:IP地址匹配的设备,单播回复一个ARP应答包,告诉对方自己的MAC地址。
  4. 更新缓存:请求方收到应答后,把IP-MAC映射写入ARP缓存,并设置超时时间(通常2-10分钟)。

ARP报文格式:

+----------------+----------------+----------------+----------------+
| 硬件类型 (2B)  | 协议类型 (2B)  | 硬件地址长度(1)| 协议地址长度(1)|
+----------------+----------------+----------------+----------------+
| 操作码 (2B)    | 发送方MAC (6B) | 发送方IP (4B)  | 目标MAC (6B)   |
+----------------+----------------+----------------+----------------+
| 目标IP (4B)    |
+----------------+
字段 长度 典型值
硬件类型 2字节 1表示以太网
协议类型 2字节 0x0800表示IPv4
硬件地址长度 1字节 6(MAC地址长度)
协议地址长度 1字节 4(IPv4地址长度)
操作码 2字节 1=ARP请求,2=ARP应答
发送方MAC 6字节 发送者的MAC地址
发送方IP 4字节 发送者的IP地址
目标MAC 6字节 请求时填0,应答时填目标MAC
目标IP 4字节 要解析的IP地址

ARP缓存表示例:

192.168.1.1    00:1A:2B:3C:4D:5E    动态    2分钟
192.168.1.2    00:1A:2B:3C:4D:5F    动态    5分钟
192.168.1.100  00:1A:2B:3C:4D:60    静态    永不过期

我曾经遇到过一个问题:公司内网突然大面积断网,排查发现是有人伪造了网关的ARP应答,导致所有设备的ARP缓存都被污染了。这就是典型的ARP欺骗攻击。从那以后,我养成了在关键设备上配置静态ARP条目的习惯。

避坑指南:ARP请求是广播,但ARP应答是单播。如果你抓包发现大量ARP请求重复发送,说明网络中有设备在频繁查询,可能是ARP缓存超时设置太短,或者有ARP扫描行为。

下面这张图,我把MAC地址、以太网帧、ARP协议的关系串起来了:

以太网帧封装与ARP解析流程 应用层数据(HTTP/FTP等) TCP/UDP头部 + 应用数据 IP头部 + TCP/UDP数据(目标IP已知,目标MAC未知) ARP请求(广播) 目标MAC: FF:FF:FF:FF:FF:FF 问:谁的IP是X.X.X.X? ARP应答(单播) 目标MAC: 请求方MAC 答:我的MAC是XX:XX:XX:XX:XX:XX 以太网帧头部(目标MAC + 源MAC + 类型0x0800)+ IP数据 + FCS

从这张图可以看得很清楚:上层协议(IP)需要知道目标MAC地址才能封装以太网帧。如果不知道,就触发ARP协议去问。问到了,缓存起来,下次直接用。

重要提醒:ARP只用于IPv4。IPv6使用NDP(邻居发现协议)来完成类似功能。另外,ARP工作在数据链路层和网络层之间,但它本身不依赖IP,只依赖MAC地址。嗯,这个边界要搞清楚。

最后总结一下这一节的核心要点:

  • MAC地址:48位,前3字节OUI+后3字节NIC,第1字节最低位标识单播/组播。
  • 以太网帧:Ethernet II格式最常用,包含目标MAC、源MAC、类型、数据、FCS。MTU=1500字节。
  • ARP协议:广播请求,单播应答。结果缓存在ARP表中,有超时时间。静态ARP可以防欺骗。