3. 数据链路层:以太网帧格式、MAC地址解析、ARP协议工作原理
数据链路层,说白了就是解决「同一物理链路下,数据该怎么传、传给谁」的问题。我刚开始接触网络时,总觉得IP地址才是主角,后来被一个ARP问题折腾了一整晚,才意识到MAC地址和链路层才是真正的「地基」。这一章,咱们就把地基打牢。
3.1 以太网帧格式——数据在网线上到底长什么样?
你想想看,当你的Linux主机发出一段数据,它最终要在网线上变成一串电信号。但光有信号不行,接收方得知道:这包数据从哪来、到哪去、是什么类型、有没有传错。以太网帧就是干这个的。
标准的以太网帧(Ethernet II,也叫DIX帧)格式如下:
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 目的MAC地址 | 6 | 接收方的物理地址 |
| 源MAC地址 | 6 | 发送方的物理地址 |
| 类型/长度 | 2 | 0x0800表示IPv4,0x0806表示ARP |
| 数据载荷 | 46~1500 | 上层协议数据(IP包等) |
| 帧校验序列(FCS) | 4 | CRC校验,检测传输错误 |
这里有个细节我提醒一下:数据载荷最少46字节。如果上层数据不够,就要填充(Padding)。为什么?因为以太网协议规定帧长度不能小于64字节(从目的MAC到FCS),这是为了冲突检测机制能正常工作。我在调一个嵌入式网卡驱动时,就遇到过因为填充不对导致丢包的情况,查了半天才发现是驱动没做填充。
关键点:以太网帧的最小长度是64字节,最大是1518字节(不含前导码)。这个限制决定了IP包的最大传输单元(MTU)通常是1500字节。
3.2 MAC地址——网络设备的「身份证」
MAC地址是48位的,通常写成六组十六进制数,比如 00:1a:2b:3c:4d:5e。前24位是组织唯一标识符(OUI),由IEEE分配给厂商;后24位是厂商自己分配的序列号。
但这里有个常见的误解:MAC地址并不是全球唯一的。虽然理论上每个网卡出厂时烧录的MAC是唯一的,但操作系统可以修改它。我在做虚拟化平台时,经常需要手动给虚拟机分配MAC地址,只要保证在同一广播域内不冲突就行。
MAC地址有三种类型:
- 单播地址:目的MAC的第一个字节最低位为0,表示发给单个设备。
- 多播地址:最低位为1,表示发给一组设备(比如IGMP、STP协议用的)。
- 广播地址:全1,即
ff:ff:ff:ff:ff:ff,表示发给同一广播域内的所有设备。
实用技巧:在Linux下用 ip link show 或 ifconfig 查看MAC地址。想临时改MAC?ip link set dev eth0 address 00:11:22:33:44:55 就行。但别在生产环境乱改,小心被运维追着打。
3.3 ARP协议——IP地址怎么找到MAC地址?
这是数据链路层的核心问题。你的Linux主机知道目标IP(比如192.168.1.1),但网卡只认MAC地址。谁来做这个翻译?ARP(地址解析协议)。
ARP的工作原理其实很简单,就四个字:问一圈,记下来。
3.3.1 ARP请求与响应
假设主机A(IP: 192.168.1.10,MAC: AA:AA:AA:AA:AA:AA)想和主机B(IP: 192.168.1.20)通信:
- A先查自己的ARP缓存表,看有没有B的MAC地址。
- 没有?那就发一个ARP请求广播:
谁的IP是192.168.1.20?请告诉AA:AA:AA:AA:AA:AA。 - 广播帧的目的MAC是
ff:ff:ff:ff:ff:ff,同一网段的所有主机都能收到。 - 主机B一看,咦,问的是我的IP,于是回复一个ARP响应(单播):
我就是,我的MAC是BB:BB:BB:BB:BB:BB。 - A收到后,把B的IP和MAC对应关系写入ARP缓存,然后开始正常通信。
整个过程,我用一张图来展示:
3.3.2 ARP缓存与老化
每次ARP解析完成后,结果会缓存在内核的ARP表中。你可以用 arp -n 或 ip neigh show 查看:
# ip neigh show
192.168.1.1 dev eth0 lladdr 00:11:22:33:44:55 REACHABLE
192.168.1.20 dev eth0 lladdr bb:bb:bb:bb:bb:bb STALE
192.168.1.100 dev eth0 lladdr cc:cc:cc:cc:cc:cc DELAY
状态说明:
- REACHABLE:刚用过,确认可达。
- STALE:超过一段时间没用了,但还没删。
- DELAY:正在确认是否还活着。
- FAILED:解析失败。
缓存默认超时时间通常是30~60秒(具体看内核参数 gc_stale_time)。为什么要老化?因为网络拓扑会变,设备可能换网卡、关机、换IP。我遇到过一个问题:一台服务器换了网卡,MAC变了,但其他机器的ARP缓存还是旧的,导致通信中断了十几分钟。后来我养成了习惯——换网卡后手动清一下ARP缓存:ip neigh flush all。
3.3.3 免费ARP(Gratuitous ARP)
这是一种特殊的ARP请求:源IP和目标IP都是自己。它有什么用?
- 检测IP冲突:主机启动时发一个免费ARP,如果收到响应,说明有人用了同样的IP。
- 更新其他设备的ARP缓存:比如你做VRRP(虚拟路由冗余协议)时,主备切换后新主机会发免费ARP,告诉所有人「网关的MAC变了」。
安全提醒:ARP协议本身没有认证机制,任何人都可以伪造ARP响应。这就是ARP欺骗攻击的原理——攻击者冒充网关,截获你的流量。防范方法:在关键网段配置静态ARP条目,或者使用DAI(动态ARP检测)。
3.4 实战:用tcpdump抓一个ARP包看看
光说不练假把式。咱们在Linux上抓个ARP包看看:
# 终端1:抓取ARP包
tcpdump -i eth0 -e -vv arp
# 终端2:触发ARP请求(比如ping一个不存在的IP)
ping -c 1 192.168.1.200
你会看到类似这样的输出:
14:23:45.123456 aa:aa:aa:aa:aa:aa > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42:
Request who-has 192.168.1.200 tell 192.168.1.10, length 28
14:23:45.123789 (无响应,因为IP不存在)
注意看:ethertype 0x0806 就是ARP协议的类型字段。目的MAC是全f的广播地址。如果目标存在,你会看到一条单播的ARP响应。
我的习惯:排查网络不通时,第一步就是抓ARP包。如果ARP请求发出去没人理,那问题大概率在二层(物理链路、VLAN配置、交换机端口安全等)。如果ARP能解析成功但ping不通,再往三层查。
3.5 本章小结
数据链路层是网络通信的「最后一公里」。以太网帧规定了数据怎么封装,MAC地址解决了设备标识问题,ARP协议则把IP和MAC桥接起来。这三个概念是连在一起的——你理解了帧格式,就知道ARP请求是怎么封装在广播帧里的;你理解了MAC地址,就知道ARP缓存里存的是什么。