← 网络基础学习第 27 / 55 章进阶45 分钟

模块三 · 网络层:数据平面

IPv6

IPv4 地址不够用这件事,最终的解决方案是 IPv6。但 IPv6 不只是"地址变长了"—— 它顺手改掉了一批延续几十年的设计(广播被取消、ARP 被替换、路由器不再分片)。本章会实测本机的 IPv6 现状。

本章要解决的问题:IPv4 地址不够用这件事,最终的解决方案是 IPv6。但 IPv6 不只是"地址变长了"—— 它顺手改掉了一批延续几十年的设计(广播被取消、ARP 被替换、路由器不再分片)。本章会实测本机的 IPv6 现状。

本章的证据来源:历史实测记录(IPv6 地址列表、IPv6 连通性测试、链路本地地址的生成方式验证)。地址格式与规则出自 RFC 4291、RFC 8200、RFC 4861、RFC 7217。

先从一个例子理解概念

IPv4常见地址形式只有有限数量,IPv6换用了更大的地址空间。但先别背长数字,先认识哪些地址能在哪儿使用。

另一种IP格式:IPv6

IPv6是IP的另一版本,地址128位,常以冒号分隔的十六进制组书写。它与IPv4的包格式不同,不能只给IPv4多添几个数字就兼容。

只在这一段用:链路本地地址

链路本地地址只服务同一链路通信,IPv6常见以fe80开头。用于更大范围通信的全局单播地址是另一类;有前者不代表公网IPv6已可用。

查邻居和找路由器:NDP

NDP(邻居发现)使用ICMPv6消息完成邻居地址解析、路由器发现等工作。ICMPv6是IPv6对应的控制协议,不能直接套IPv4消息类型表。

设备怎样得到地址:SLAAC与接口标识

SLAAC(无状态地址自动配置)可根据路由器提供的前缀形成地址。接口标识是地址的一部分,可采用不同生成策略,不必直接来自MAC。

下面再用这些概念看原理、命令和结果。规范与官方资料列在本章末尾,类比只帮助理解,不代替协议规则。

先看 IPv4 为什么不够用

IPv4 地址是 32 位,总共能表示:

2³² = 4,294,967,296 个地址

大约 43 亿个。听起来不少,但:

  • 1990 年代互联网爆发时,全球人口已经超过 60 亿
  • 一个人往往不止一台设备(手机、电脑、平板、手表、电视……)
  • 还有大量地址被保留或浪费:分类编址时代的低效分配、私有地址段、多播段、实验用段

结果是:2011 年 2 月,IANA 把最后一批 IPv4 地址分配完了。2011-02-03的公告指IANA未分配IPv4地址池耗尽,不等于所有区域注册机构同时无地址,也不等于现存IPv4无法使用。ICANN 官方公告

为应对地址压力,人们陆续采用了以下方案;NAT和IPv6都早于2011年出现:

办法效果
NAT(下一章)让许多设备共用一个公网 IP,救急,但破坏了端到端通信
IPv6从根上解决地址数量问题,但推广很慢

为什么 IPv6 推广慢? 因为它和 IPv4 不兼容 —— 不是改几个字段的事,而是整个地址体系都换了。全世界的设备、软件、配置都要改。这就是为什么到了今天,很多网络仍然是 IPv4 为主。

位是什么概念

IPv6 地址是 128 位:

2¹²⁸ ≈ 340,282,366,920,938,463,463,374,607,431,768,211,456

约 3.4 × 10³⁸ 个地址。

换个说法体会一下:地球表面积约 5.1 × 10¹⁴ 平方米。如果把这些地址平均分到地球表面,每平方米能分到大约 6.6 × 10²³ 个 IPv6 地址(这里只作数量级比喻)。

这就是为什么 IPv6 的设计者不再考虑"节省地址" —— 他们可以给每台设备、每个虚拟机、每个容器都分一个全球唯一的地址,不需要 NAT。

地址怎么写

128 位写起来太长,所以用十六进制分组表示,共 8 组、每组 4 位十六进制数字:

2001:0db8:0000:0000:0000:ff00:0042:8329

缩写规则(两条,都很实用)

规则一:每组里的前导零可以省略。

2001:0db8:0000:...   →   2001:db8:0:...

规则二:连续的全零组可以用 :: 代替,但整个地址里只能用一次。

2001:0db8:0000:0000:0000:ff00:0042:8329
        ↓ 中间三组全零,压缩成 ::
2001:db8::ff00:42:8329

实测:本机的 IPv6 地址

InterfaceAlias      IPAddress                    PrefixLength PrefixOrigin SuffixOrigin
WLAN                fe80::fd00:98a4:4701:5b30%17          64 WellKnown    Link
FlClash             fe80::139c:e04d:5cd:696a%16          64 WellKnown    Link
vEthernet (WSL...)  fe80::9680:7eb5:5f54:447b%34          64 WellKnown    Link

两个值得解释的部分:

① fe80:: 是"链路本地"前缀。

fe80::/10 这一段的地址只能在同一个网段内使用,路由器不会把它转发出去。它的作用和 IPv4 的 169.254.x.x(《网络层》模块讲过的 APIPA)类似 —— 都是"没有配置时自己先有一个可用地址"。

② %17 是"区域索引"(zone index)。

链路本地地址的同一个地址值可能出现在多块网卡上(因为前缀都一样)。所以通信时必须指明"从哪块网卡出去",%17 就是接口编号。

历史实测记录确认了这一点 —— 同一个地址出现在多块网卡上:

InterfaceAlias                     IPAddress
vEthernet (WSL (Hyper-V firewall)) fe80::139c:e04d:5cd:696a%16     ← 注意这里
以太网 3                             fe80::139c:e04d:5cd:696a       ← 同一个地址
本地连接* 10                         fe80::139c:e04d:5cd:696a

但这里其实有个反常之处:fe80::139c:e04d:5cd:696a 明明是 FlClash 网卡的地址(上表第一行),却在别的网卡的邻居表里以 Unreachable 状态出现。

说明:系统曾经尝试从别的网卡去访问这个地址,失败了(因为链路本地地址不跨网段),留下了 Unreachable 记录。这类"看着奇怪但无害"的缓存残留,是真实系统里很常见的现象。

实测:本机 IPv6 不可用

地址列表里全是 fe80:: —— 没有任何全局 IPv6 地址。直接验证一下:

示例powershell
ping -6 2001:4860:4860::8888

实测结果:

Pinging 2001:4860:4860::8888 with 32 bytes of data:
PING: transmit failed. General failure.

transmit failed(发送失败)是关键 —— 不是"超时"(超时说明包发出去了但没回应),而是根本发不出去。历史地址清单没有全局IPv6地址;该次发送失败与缺少可用源地址/路由等原因相容,仍须查路由与错误码,不能只用这行输出确定根因。

与 IPv4 的关键差异

IPv6 不只是把地址加长,它顺手改掉了一批老设计:

方面IPv4IPv6为什么改
地址长度32 位128 位解决地址枯竭
广播有(255.255.255.255)取消,用多播代替广播会打扰全网;多播只发给订阅者
地址解析ARPNDP(用 ICMPv6 承载)可以做得更安全、更规范
头部校验和有去掉二层和四层都有校验,三层重复校验是浪费
分片路由器可以分片只有发送方能分片路由器分片开销大,而且被攻击者利用过
头部长度20~60 字节(可变)固定 40 字节 + 扩展头固定长度让路由器处理更快
NAT广泛使用设计上不需要地址够多,可以恢复端到端通信

几处值得单独说的:

① 取消广播是个不小的改动。 IPv4 里到处都在用广播(ARP 请求、DHCP 发现)。IPv6 换成了多播:只有真正订阅了某个多播组的设备才会收到。这减少了无谓的打扰。

② 路由器不再分片。 这是吸取教训的结果 —— IPv4 允许中间路由器分片,被攻击者利用来消耗资源。IPv6 规定只有发送方可以分片,路径中间的设备如果发现包太大,就丢弃并回一个 ICMPv6 通知,让发送方自己改小(这就是《全景与基础》模块讲的 PMTUD 机制,在 IPv6 里变成了强制要求)。

③ 去掉头部校验和是个"减法"。 二层有 FCS,四层(TCP/UDP)有各自的校验和,三层的校验和属于重复劳动,而且每经过一跳都要重算(因为 TTL 变了),拖慢路由器。去掉之后,路由器转发更快。

NDP:用 ICMPv6 代替 ARP

IPv6 没有 ARP,取而代之的是 NDP(Neighbor Discovery Protocol,邻居发现协议)。它用 ICMPv6 承载,做的是同一件事:

功能IPv4 的做法IPv6 的做法
解析地址ARP 请求(广播)邻居请求(多播到特定组)
应答ARP 应答(单播)邻居通告
缓存状态Reachable / Stale / …完全相同的一套状态
实测:IPv6 的邻居表和 IPv4 用的是同一套状态机powershell
Get-NetNeighbor -AddressFamily IPv6
IPAddress                LinkLayerAddress        State
fe80::139c:e04d:5cd:696a 00-00-00-00-00-00       Unreachable

Unreachable + 全零 MAC —— 和《ARP》那一章看到的一模一样。这说明"维护一个带状态的邻居缓存"这件事,是两种协议共同的需求,只是实现手段换了。

NDP 比 ARP 多出来的能力:

  • 路由器发现(自动找到网关,不需要手工配置)
  • 地址自动配置(SLAAC —— 设备自己根据网络前缀生成地址)
  • 重复地址检测(开机时先确认这个地址没被别人占用)

实测:链路本地地址不是从 MAC 推导的

这是一个关于隐私设计的有趣细节。

IPv6 早期标准(RFC 2464)规定:链路本地地址的后 64 位由网卡的 MAC 地址推导,这叫 EUI-64。规则是:

  1. 把 MAC(48 位)从中间劈开
  2. 在中间插入 FF:FE
  3. 把第一个字节的第 1 位取反

本机 WLAN 的 MAC 是 44:38:E8:0A:55:23,按这个规则算:

MAC:        44:38:E8:0A:55:23
插入 FF:FE: 44:38:E8 : FF:FE : 0A:55:23
第一位取反: 46:38:E8 : FF:FE : 0A:55:23
→ 应该得到: fe80::4638:e8ff:fe0a:5523

但本机实际观测到的地址是:

fe80::fd00:98a4:4701:5b30

两者不同。 这与使用不透明接口标识相容,但未核对永久MAC和地址生成策略,不能由此证明采用RFC 7217。

为什么这很重要

如果按 EUI-64 生成地址,那么任何人看到你的 IPv6 地址,就能反推出你的 MAC 地址,进而查出你的设备厂商和型号。而且因为地址里带着 MAC,无论你走到哪个网络,地址的后半段都一样 —— 这等于给了追踪者一个永久标识。

对隐私来说这是灾难。所以后来的标准(RFC 7217)改用基于秘密值和网络等输入生成的不透明稳定接口标识:后缀按规定的输入和函数生成,不直接暴露MAC(但对同一台设备、同一个网络保持稳定,便于管理)。

双栈:现在怎么和 IPv4 共存

现实中 IPv6 不可能一夜替换 IPv4,所以有几种共存方式:

方式原理现状
双栈设备同时有 IPv4 和 IPv6 地址,按目标选最主流,本机就是(有 IPv4,也有链路本地 IPv6)
隧道把 IPv6 包封装在 IPv4 包里传(6to4、Teredo)过渡方案,用得越来越少
NAT64 / DNS64让只有 IPv6 的设备能访问 IPv4 资源运营商侧主要方案

本机的情况:IPv4 完整可用,IPv6 只有链路本地 —— 属于"装了 IPv6 协议栈,但网络没有提供 IPv6 服务"这种最常见的中间状态。

常见误解

误解一:"IPv6 就是地址变长了一点"

改的远不止地址长度:广播被取消、ARP 被 NDP 替换、路由器不再分片、头部校验和被去掉、头部变成固定长度。这些改动的影响加起来,比"地址变长"大得多。

误解二:"IPv6 没有 NAT,所以不安全"

NAT 本来就不是安全机制。 它带来的"外网连不进来"只是副作用,不是保护。真正的安全来自防火墙规则和认证加密。IPv6 环境下仍然可以用防火墙做同样的事 —— 而且因为没有 NAT,端到端通信恢复了,反而更简单。

误解三:"到 IPv6 就没有 ARP 了,所以没有地址解析了"

有,只是换了名字和协议:NDP 做的正是 ARP 的事。而且它用的是多播(只打扰相关设备)而不是广播,还能顺便做路由器发现和地址自动配置。

误解四:"有 fe80:: 地址就说明 IPv6 能用"

不能。 fe80:: 是链路本地地址,只在本网段内有效。历史实测记录就是反例:有 fe80:: 地址,但 ping -6 到公网直接 transmit failed。"有 IPv6 地址"和"有 IPv6 互联网接入"是两回事。

本章小结

结论类型
IPv4 共约 43 亿个地址,2011年IANA未分配池耗尽,不等于所有IPv4地址都不能再分配或使用标准/公开记录
IPv6 地址 128 位,约 3.4 × 10³⁸ 个标准
地址写法 8 组十六进制,可省略前导零,:: 只能用一次标准
fe80::/10 是链路本地地址,只在同网段有效标准
%17 是区域索引,指明从哪块网卡出去标准
实测:本机所有接口只有 fe80:: 地址,无全局 IPv6实测
实测:ping -6 公网返回 transmit failed,证明无 IPv6 接入实测
IPv6 取消广播、用 NDP 代替 ARP、路由器不再分片、去掉头部校验和标准
实测:IPv6 邻居表沿用与 ARP 相同的状态机(含 Unreachable)实测
历史地址与当前MAC的EUI-64推导值不同,具体生成策略未核实观察与限制
RFC 7217定义不透明稳定接口标识;地址生成策略不能仅由单个地址确定标准与限制

自测题

7 题 · 先自己答,再展开对照

  1. 2001:0db8:0000:0000:0000:0000:0000:0001 的最简写法是什么?
    2001:db8::1。 步骤:省略各组的前导零(0db8 → db8),然后把连续的全零组用 :: 压缩(中间 5 组全零压缩成 ::)。注意 :: 在整个地址里只能用一次。
  2. fe80:: 开头的地址能用来访问互联网吗?为什么?
    不能。 fe80::/10 是链路本地地址,路由器不会把它转发出去,它的作用范围仅限同一个网段。要访问互联网必须有全局单播地址(通常是 2000::/3 段)。历史实测记录就是反例:有 fe80:: 地址但 ping -6 到公网返回 transmit failed。
  3. IPv6 里那个 %17 是干什么的?
    区域索引(zone index),用来指明从哪块网卡发出。 因为链路本地地址的前缀都一样,同一个地址值可能出现在多块网卡上,所以通信时必须指明出口接口。%17 就是那个接口的编号。
  4. IPv6 取消了广播,那原来用广播做的事情(比如地址解析)怎么办?
    用多播代替。 原来 ARP 用广播问"谁是 X",现在 NDP 用多播发邻居请求 —— 只有加入了对应多播组的设备(也就是相关的那几台)才会收到并处理,其他设备不受打扰。这是"广播 → 多播"这个改动的一个典型收益:减少无谓的打扰。
  5. 为什么 IPv6 规定"只有发送方可以分片",而不像 IPv4 那样允许路由器分片?
    IPv6路由器不分片,过大报文以ICMPv6 Packet Too Big通知发送端;分片仅由源节点执行,重组在目的端。不能把路由器分片和终端重组资源混在一起。
  6. IPv6 早期标准用 EUI-64 生成地址,后来为什么改了?这解决什么问题?
    基于MAC的Modified EUI-64可能暴露接口标识;RFC7217给出按网络等输入生成的不透明稳定标识方案。它不是所有系统都必须采用的唯一算法,也不同于临时地址机制。
  7. 一台机器有 fe80:: 地址,能不能说明它可以用 IPv6 上网?
    不能。 fe80:: 只是链路本地地址,说明 IPv6 协议栈是启用的、能进行同网段通信,但不代表有 IPv6 互联网接入。要访问互联网,还需要全局单播地址和 IPv6 默认网关 —— 历史实测记录就是只有前者没有后者(ping -6 直接 transmit failed)。

参考资料与适用范围

修订核对日期:2026-10-13。规则按所列协议与实现范围理解;文中的原始命令输出是历史观察,不表示本次重新实测。跨版本、代理/隧道及不同捕获位置需要另行核对。

正文源自 m3-04-IPv6.md · 共 13 节 · 7 道自测题