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 秒实验
- 算一下:MAC 00:11:22:33:44:55 生成的接口标识是什么?
- 想一下:为什么 fe80 地址不能跨网段用?
- 想一下:随机接口标识会带来什么运维上的麻烦?
常见误区
- 以为「fe80 地址需要手工配」。 自动生成,网卡一启用就有。
- 以为「fe80 地址能上网」。 不能,路由器不转发这个前缀。
- 以为「fe80 后面的 64 位一定是 MAC」。 现在多是随机的,隐私扩展是默认行为。
自测三问(点开对答案)
1. 链路本地地址的前缀是什么? —— **fe80::/10**,实际实现按 /64 用。 2. EUI-64 的三步是什么? —— **中间插 FF:FE、第一字节异或 02、拼到前缀后面。** 3. 为什么现在多用随机接口标识? —— **EUI-64 会把 MAC 暴露给所有通信对象**,等于「走到哪儿都带着身份证」。下一节讲「自己划一块内网」:唯一本地地址。
- ☐ (本节完,下一节 4.6.7 唯一本地地址)