TCP/IP(二):以太网与链路层——MAC 地址、帧与 ARP

写在前面

上一篇把分层模型讲完了:OSI 七层、TCP/IP 四层、实际用的五层,还有逐层封装。从这一篇开始,我们沿五层模型自底向上一层层展开。

最底下是物理层(比特、电信号、光纤),它没什么"协议"可讲,略过。再往上就是数据链路层——这一层要解决的问题是:在相邻两个节点之间,怎么把比特组织成可以识别、可以校验的数据单元传过去 。注意是"相邻"——同一根线两头的两台设备,链路层只管这一跳;跨网、跨子网的事留给上面的网络层。

这一篇聚焦工程上最主流的链路技术以太网(Ethernet),讲四件事:MAC 地址、以太网帧、交换机怎么转发、ARP 怎么把 IP 翻译成 MAC。


一、链路层到底管什么

把网络层交下来的 IP 包搬到"对面那台设备",链路层要做这几件事:

  • 成帧 —— 给 IP 包套上自己的头部和尾部(帧头 + 帧尾),告诉对面"这是一帧、从哪来、到哪去";
  • 物理寻址 —— 用 MAC 地址在同一链路上定位网卡;
  • 差错检测 —— 帧尾加一段校验码(FCS),接收方算一遍,错了就丢,不交给上层;
  • 介质访问控制 —— 决定谁能在共享介质上发数据(经典以太网用 CSMA/CD,全双工交换式以太网里基本退场)。

要特别强调一点:链路层大多数时候只做"检错 + 丢弃",不做重传。丢了的帧交给上层(比如 TCP)去补。这也是分层分工的体现——链路层保持简单、快。

一个常被忽略的点:Wi-Fi(IEEE 802.11)和以太网(802.3)是两条不同的链路层,但它们都承载 IP,所以你从 Wi-Fi 切到有线,上层协议毫无感知。这正是分层带来的好处。


二、MAC 地址:网卡的身份证

MAC(Media Access Control)地址是网卡的硬件地址,几个关键事实:

  • 长度 48 位(6 字节),标准名也叫 EUI-48,习惯写成 AA:BB:CC:DD:EE:FF 这种六段十六进制。
  • 传统的 48 位全局 MAC 地址常按 前 3 字节 OUI(Organizationally Unique Identifier,组织唯一标识符)+ 后 3 字节厂商分配部分来理解。IEEE 现在还提供 MA-M、MA-S 等更小的地址号段,因此“前三字节一定是厂商 OUI”适合作为经典模型,而不是覆盖所有现代分配方式的绝对规则。
  • 因此又叫"固化地址"(burned-in address)。但现在的 MAC 未必真的固化:虚拟机网卡、容器 veth、手机随机 MAC(隐私保护)、手工 ip link set 改的 MAC——都是"本地分配"的,不来自 OUI。

关键在于第一字节的最低两位,它们决定了这个地址的性质:

名称01
bit 0(最低位)I/G 位(Individual / Group)单播组播 / 广播
bit 1(次低位)U/L 位(Universal / Local)全局唯一(OUI)本地分配

记住几条推论:

  • 单播 MAC 的 I/G 位是 0,目标是某一块网卡;
  • 组播 MAC 的 I/G 位是 1,目标是"一组"网卡;
  • 广播地址 FF:FF:FF:FF:FF:FF 是组播的特例(全 1),目标是本链路上所有设备;
  • IPv4 组播映射到 MAC 时以 01:00:5E: 开头,IPv6 组播以 33:33: 开头——你抓包看到这两类前缀,就知道是组播流量。

你看到的虚拟机 / 容器 MAC 常以 02: 开头,正是因为第二位被置 1(U/L = 本地),第一位保持 0(单播)。这是"本地单播"地址的典型长相。


三、以太网帧:数据在链路上的信封

一个以太网帧长这样(从左到右逐字节发送):

1
2
3
4
5
+--------+-----+---------+---------+--------+----------------+-------+
|Preamble| SFD | Dst MAC | Src MAC |Type/Len|    Payload     |  FCS  |
|  7 B   | 1 B |   6 B   |   6 B   |  2 B   | 46 ~ 1500 B    |  4 B  |
+--------+-----+---------+---------+--------+----------------+-------+
   前导 + SFD 共 8 B,不计入帧长      从目的 MAC 到 FCS 才算帧:64 ~ 1518 B

逐字段说明:

字段大小作用
前导 Preamble7 字节交替的 1010... 比特,让接收方做时钟同步
SFD1 字节帧起始定界符,10101011,标志帧开始
目的 MAC6 字节接收方网卡地址
源 MAC6 字节发送方网卡地址
类型 / 长度2 字节见下文
载荷 Payload46 ~ 1500 字节上层来的数据(一般就是 IP 包)
FCS4 字节CRC32 校验,错了整帧丢弃

几个要点:

前导和 SFD 不算帧长。对经典、无 VLAN 标签的 Ethernet II 帧,“最小帧 64 字节”指的是从目的 MAC 到 FCS:6+6+2+46+4 = 64;“最大帧 1518 字节”是 6+6+2+1500+4 = 1518。802.1Q VLAN 标签会再增加 4 字节,一些网络还支持厂商相关的 Jumbo Frame。最小帧设 64,是历史原因——为了让冲突信号能在 CSMA/CD 里来得及传回发送方。

类型 / 长度的双关:这个字段如果 ≤ 1500 表示"载荷长度"(IEEE 802.3 风格),如果 ≥ 1536(0x0600) 表示"上层协议类型"(Ethernet II 风格)。现代 IP 流量几乎都走 Ethernet II,所以你看到的都是类型。常见的 EtherType:

EtherType协议
0x0800IPv4
0x0806ARP
0x86DDIPv6
0x8100802.1Q VLAN 标签

经典以太网常见的 MTU = 1500 字节,指的是能够承载的网络层数据包上限。这是当前链路给网络层的约束:一个 IP 包(含 IP 头)超过该链路 MTU 就得想办法——下一篇会讲 IP 分片和 PMTUD。PPPoE、隧道或 overlay 会吃掉额外头部空间,Jumbo Frame 则可能提供更大的 MTU,实际值应以路径和接口配置为准。

FCS 只检错不纠错。错了直接丢,网卡层面就丢了,上层(TCP)感知到丢包再重传。


四、交换机 vs 集线器:冲突域与广播域

这块容易混,先把两个概念钉死:

  • 冲突域(collision domain):共享同一介质、可能发生冲突的一组设备。集线器所有端口是同一个冲突域;交换机每个端口是独立的冲突域。
  • 广播域(broadcast domain):一个广播帧能扩散到的范围。没划 VLAN 时,一台交换机的所有端口是同一个广播域;路由器能隔断广播域。

集线器(hub) 是物理层设备,本质是"中继器":一个端口收到电信号,原样复制到所有其他端口。所以它不认 MAC、不认帧,所有端口抢同一根介质,靠 CSMA/CD 避冲突。今天基本被淘汰。

交换机(switch) 是链路层设备,核心是一张 MAC 地址表(也叫 CAM 表),记录"哪个端口号 ↔ 哪个 MAC"。转发逻辑:

1
2
3
4
5
6
7
8
收到一帧(端口 P,源 MAC = S,目的 MAC = D):

1. 学习:把 (S → P) 记进 MAC 表(已有就刷新老化时间)
2. 转发:
   - 若 D 在表中,且对应的端口就是 P → 过滤,不回发(避免环路回弹)
   - 若 D 在表中,对应端口是 Q(≠ P)→ 只从 Q 发出去(单播转发)
   - 若 D 不在表中 → 泛洪(flood):从除 P 外所有端口发出去
   - 若 D 是广播 / 组播 → 泛洪(组播在高级交换机里有 IGMP snooping 精细化,先不展开)

所以交换机的两个本事:靠源 MAC 学习,靠目的 MAC 转发;查不到就泛洪兜底。这让它比集线器高效得多——大多数流量只走目标端口,不再全网广播。

一句话区分:集线器是"大喇叭"(同一冲突域、同一广播域),交换机是"分机总机"(每端口一个冲突域,全机一个广播域)。要切广播域,得上路由器或 VLAN。


五、ARP:IP 怎么翻译成 MAC

现在问题来了:主机 A 要往同子网的主机 B 发一个 IP 包,A 知道 B 的 IP,但帧头要写的是 B 的 MAC,A 一开始并不知道 B 的 MAC 是什么。这就靠 ARP(Address Resolution Protocol,地址解析协议)。

完整流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
A(IP=10.0.0.2,MAC=a)  ──→  B(IP=10.0.0.5,MAC=b)  同子网

1. A 查本地 ARP 缓存,没有 10.0.0.5 的条目
2. A 发一个 ARP 请求(ARP Request):
   - 以太网帧目的 MAC = FF:FF:FF:FF:FF:FF(广播)
   - 内容:"谁有 10.0.0.5?把 MAC 告诉 10.0.0.2(MAC=a)"
3. 同子网所有主机都收到这个广播,但只有 B 发现"问的是我的 IP"
4. B 回一个 ARP 应答(ARP Reply):
   - 以太网帧目的 MAC = a(单播,只给 A)
   - 内容:"10.0.0.5 的 MAC 是 b"
5. A 把 (10.0.0.5 → b) 存进 ARP 缓存,带老化时间(几分钟到几十分钟不等,各系统不同)
6. 之后 A 直接用 b 当目的 MAC 发 IP 包,不再广播

两个细节值得注意:

请求广播、应答单播。请求是喊一嗓子(广播),应答是悄悄回(单播)。

跨子网时 ARP 找的是网关,不是目标。如果 B 在另一个子网,A 不会去解析 B 的 MAC——A 会把 IP 包(目的 IP 仍是 B)封装成发给默认网关(路由器)MAC 的帧。路由器收到后拆开 IP 头,再决定下一跳怎么转发,下一跳又是一次新的"ARP 找下一跳 MAC"。

这正好呼应分层:IP 地址端到端不变(全程都是 B),MAC 地址逐跳变(每一段链路换成当时那一跳的 MAC)。抓包时如果你看到 IP 目的始终是某台远端主机,而以太网源 / 目的 MAC 一段段在变,就是这个原因。

ARP 欺骗(ARP spoofing):因为 ARP 没有认证,谁都能冒充应答。攻击者发一个伪造的 ARP 应答,把"网关 IP"指向自己的 MAC,受害主机的流量就被骗到攻击者那里,形成中间人。防御手段:静态 ARP 绑定、交换机的动态 ARP 检测(DAI)、监控异常 MAC 翻转等。


六、既然有了 IP,为什么还要 MAC

这是学网络几乎人人会问的问题——既然 IP 也能定位主机,干嘛还弄一个 MAC?

答案是分层分工,两者解决的问题不在一个层面:

  • MAC 标识一块网卡:扁平、硬件级、不可路由,只在同一条链路上有意义。换了链路(比如从有线换无线)MAC 也跟着换。
  • IP 标识主机在网络中的位置:有结构、可聚合、可路由,跨链路全程有效。

打个比方:MAC 像身份证号,唯一但不告诉你人在哪;IP 像邮寄地址,有结构、能路由 。寄一封信,信封上写的是地址(IP),但信件在每一站实际交接时,邮递员要看的是"这一段交给谁"(逐跳的 MAC)。

另一个现实理由是软硬件解耦

  • 网卡坏了换一块(MAC 变了),IP 不用动,上层连接的逻辑不受影响;
  • 机器从这台物理机迁移到那台(虚拟化迁移),IP 可以保留,由新的网卡(新 MAC)承载。

如果 IP 和硬件地址是同一个东西,这种灵活性就没了。分层让"网络位置(IP)“和"硬件身份(MAC)“独立变化,这正是分层架构的回报。


小结

  • 链路层在相邻两节点之间成帧、寻址、检错;不做可靠重传,交给上层;
  • 常见 MAC 地址为 48 位,传统 MA-L 分配可理解为 OUI + 厂商分配部分;第一字节的 bit 0 是单播 / 组播位,bit 1 是全局 / 本地位;广播 = FF:FF:FF:FF:FF:FF
  • 经典无标签 Ethernet II 帧 = 前导 + SFD +(目的 / 源 MAC + 类型 + 载荷 + FCS),载荷 46 ~ 1500 字节,常见 MTU = 1500;VLAN 和 Jumbo Frame 会改变边界;
  • 交换机靠源 MAC 学习、靠目的 MAC 转发,查不到就泛洪;每端口一个冲突域,全机一个广播域;
  • ARP 用广播请求 + 单播应答把 IP 翻译成 MAC;跨子网时解析的是网关 MAC;IP 端到端不变,MAC 逐跳变

下一篇,我们升一层,进入网络层的核心——TCP/IP(三):IP 协议——数据报、头部与分片


参考:

Licensed under CC BY-NC-SA 4.0