📚 第四章 IP协议
📄 一句话概括

fe80::/10 是「每块网卡自动带」的地址,不用配置、不用服务器。 它只在同一链路上有效,路由器不转发,但邻居发现全靠它。

📝 本节和前面几节的关系

4.6.4 的特殊地址表里提过 fe80,这一节把它讲透。 第三章的 MAC 地址是它的原料,这一节讲「MAC 怎么变成地址」。

一、它是什么

链路本地地址的前缀是 fe80::/10,实际实现里固定用 fe80::/64。 关键特征是「自动生成」:网卡一启用,系统就给自己配一个,不需要 DHCP、不需要人工。

项 值 说明
前缀 fe80::/10 规范写法,实际按 /64 用
作用域 同一链路 路由器不转发
生成方式 EUI-64 或随机 不需要服务器
是否必需 必需 每块网卡都有

第二行「路由器不转发」是它的定义:带 fe80 目的地址的包,出了这块网卡就不该存在。 所以它不能用来「跨网段通信」,但正好适合「找邻居」。 第四行「必需」容易被忽略: 就算你有全球地址,fe80 也照样存在——因为「发现邻居、找路由器」这些动作都要用它。

二、EUI-64:从 MAC 算出来

三步,一步不能少:中间插 FF:FE、第一字节异或 02、拼到 fe80:: 后面。

步骤 结果 为什么
原 MAC 9C:B6:D0:0D:D5:0F 48 位
插 FF:FE 9C:B6:D0:FF:FE:0D:D5:0F 补到 64 位
异或 02 9E:B6:D0:FF:FE:0D:D5:0F 翻转 U/L 位

第二行「插 FF:FE」是把 48 位撑到 64 位: 48 加 16 正好 64,而 FF:FE 这两个字节在正常 MAC 里不会出现, 所以「看到 FF:FE 就知道这是拼出来的」。 第三行「异或 02」纯粹是「翻译」:MAC 里那一位的含义和 IPv6 的 U/L 位正好相反, 所以必须翻一下,否则「全球唯一」会被理解成「本地管理」。

三、现在为什么很少见

因为隐私问题:EUI-64 把网卡 MAC 直接编进地址,等于「走到哪儿都报身份证号」。 同一个 MAC 生成的 fe80 地址永远不变,所以「跨网络追踪同一台设备」变得很容易。

方式 地址稳不稳定 隐私
EUI-64 永远不变 差
随机(隐私扩展) 定期变 好

第二行现在是主流:Windows 从 Vista 起默认随机,Android 一直不支持 EUI-64。 所以你在本机看到的 fe80 地址后面那 64 位,多半是随机的,和 MAC 无关。 这也带来一个副作用: 「靠 fe80 地址判断是不是同一台机器」不再可靠—— 因为地址会变。要认机器得靠别的办法(比如主机名或证书)。

四、它撑起了哪些功能

三件大事,全靠它:

功能 干什么 为什么必须用它
邻居发现(NDP) 代替 ARP 找 MAC 还不知道对方全球地址
路由器发现 找默认网关 启动时什么都没有
地址自动配置 拿前缀拼地址 先要有链路级通信

第一行是「ARP 的替代品」:IPv4 用广播 ARP,IPv6 用多播 NDP, 而 NDP 的报文本身就走 fe80 地址。 所以「没有 fe80 就没有 IPv6」这句话不算夸张。 第三行是个「先有鸡还是先有蛋」的问题:要自动配置地址,得先能通信;要能通信,得先有地址。 fe80 就是打破这个循环的那把钥匙——它不需要任何前提。

五、动手 Demo:MAC 地址怎么变成接口标识

拿本机 WLAN 的 MAC 走一遍 EUI-64 的三步,看结果是不是 fe80 开头的地址。 注意第三步:9C 异或 02 变成 9E。

mac = '9c:b6:d0:0d:d5:0f'
b = [int(x, 16) for x in mac.split(':')]
mid = b[:3] + [0xff, 0xfe] + b[3:]
eui = [mid[0] ^ 0x02] + mid[1:]
print(':'.join('%02X' % x for x in eui))

实跑输出:

--------------------------------------------------------------------
MAC 地址怎么变成接口标识
--------------------------------------------------------------------
**EUI-64 的规则三步**:**中间插 FF:FE、把第一字节的 U/L 位取反、拼到前缀后面。**

**第一步,原来的 MAC:9C:B6:D0:0D:D5:0F**
**第二步,中间插入 FF:FE:9C:B6:D0:FF:FE:0D:D5:0F**
**第三步,第一字节 9C 异或 02 得 9E:9E:B6:D0:FF:FE:0D:D5:0F**

**拼成地址就是**:
**fe80::9eb6:d0ff:fe0d:d50f**

**为什么第一字节要异或 02**:
**MAC 地址里那一位是「全局/本地」标志,语义和 IPv6 的 U/L 位正好相反。**
**9C 里「值为 2 的那一位」是 0,异或之后变成 1**——**这一步纯属「翻译」,不含任何信息。**

**但今天很少看到这种地址了**:**Windows 和 Android 默认用「随机接口标识」(隐私扩展)**,
**因为 EUI-64 会把网卡 MAC 暴露给所有访问过的网站**——**等于「走到哪儿都带着身份证」。**
**所以现在 `fe80::` 后面的 64 位,多数是随机的,和硬件无关。**

b[:3] + [0xff, 0xfe] + b[3:] 这一行就是「插在正中间」:前三个字节、FF FE、后三个字节。 用切片拼接比自己写循环清楚得多,也不容易错位。 mid[0] ^ 0x02 这个异或只改一位: 0x9C 是 1001 1100,异或 0000 0010 得 1001 1110,也就是 0x9E。 看着只变了一点点,但「全球/本地」的含义正好反过来。 最后拼出来的 fe80::9eb6:d0ff:fe0d:d50f 里能看到 FF:FE: 所以「地址里有 ff:fe」就是「这是从 MAC 生成的」的标志。 反过来说,看不到 ff:fe 的 fe80 地址,多半是随机生成的。

30 秒实验

  1. 算一下:MAC 00:11:22:33:44:55 生成的接口标识是什么?
  2. 想一下:为什么 fe80 地址不能跨网段用?
  3. 想一下:随机接口标识会带来什么运维上的麻烦?

常见误区

  1. 以为「fe80 地址需要手工配」。 自动生成,网卡一启用就有。
  2. 以为「fe80 地址能上网」。 不能,路由器不转发这个前缀。
  3. 以为「fe80 后面的 64 位一定是 MAC」。 现在多是随机的,隐私扩展是默认行为。
自测三问(点开对答案) 1. 链路本地地址的前缀是什么? —— **fe80::/10**,实际实现按 /64 用。 2. EUI-64 的三步是什么? —— **中间插 FF:FE、第一字节异或 02、拼到前缀后面。** 3. 为什么现在多用随机接口标识? —— **EUI-64 会把 MAC 暴露给所有通信对象**,等于「走到哪儿都带着身份证」。

下一节讲「自己划一块内网」:唯一本地地址。

相关笔记