IPv4 地址空间约 43 亿,早在 2019 年 11 月全球 IPv4 地址池就已彻底枯竭。IPv6 以 128 位地址空间(约 3.4 × 10³⁸ 个地址)成为下一代互联网的必然选择。理解 IPv6 的地址体系与过渡技术,是网络工程师从 IPv4 时代走向下一代的关键一步。
一、IPv6 地址体系总览
1.1 地址规模与表示
IPv6 地址为 128 位,写成 8 组 16 位十六进制段,以冒号分隔:
完整形式:
2001:0db8:0000:0000:0000:ff00:0042:8329
压缩形式(去掉前导零 + 一段连续的 0 用 :: 代替):
2001:db8::ff00:42:8329
IPv4 兼容写法(后 32 位写成点分十进制):
::ffff:192.168.1.1
一句话:
::只能在地址中出现一次,否则无法确定每段长度。
1.2 地址结构
IPv6 地址分为三部分:前缀(全局路由前缀)、子网 ID、接口 ID。
全局单播地址结构(典型 /48 分配):
| 2001:0db8 | 2a01: | 0001: | 0000:0000:0000:0001 |
| 全球前缀 | SLA(站点) | 子网 | 接口 ID(EUI-64/随机) |
| /48 前缀 | 16 位 | 16 位 | 64 位 |
1.3 地址类型与作用域
| 地址类型 | 前缀/特征 | 作用域 | 用途 |
|---|---|---|---|
| 全局单播 GUA | 2000::/3 | 全球 | 公网可达地址 |
| 链路本地 | fe80::/10 | 单条链路 | 邻居发现、无状态配置、路由下一跳 |
| 唯一本地 ULA | fc00::/7(常用 fd00::) | 站点内 | 内网私有地址,类似 IPv4 私网 |
| 环回 | ::1/128 | 本机 | 对应 IPv4 的 127.0.0.1 |
| 组播 | ff00::/8 | 链路/站点/全球 | 对应 IPv4 组播 224.0.0.0/4 |
| 任播 Anycast | 同单播地址 | 全局 | 最近节点(对应 Anycast 负载均衡) |
二、IPv6 寻址与配置
2.1 无状态地址自动配置(SLAAC)
SLAAC(Stateless Address Autoconfiguration)是 IPv6 的标志性能力:主机通过路由器通告(Router Advertisement)获取前缀,再自行生成接口 ID,无需 DHCP 服务器。
主机启动
│
▼
发送 RS(Router Solicitation,组播 ff02::2)
│
▼
收到 RA(Router Advertisement,含 /64 前缀 + 默认网关)
│
├── 前缀 2001:db8:100::/64 + 接口 ID(EUI-64 或随机)
│ │
│ └─→ 形成 GUA 地址
│
└── 重复地址检测(DAD):组播 NS 探测,无回应则确认唯一
# Linux 查看 IPv6 地址
ip -6 addr show eth0
# 输出示例:链路本地 + SLAAC 全局地址
# 3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP>
# inet6 fe80::5054:ff:fe12:3456/64 scope link
# inet6 2001:db8:100::5054:ff:fe12:3456/64 scope global
# 查看 IPv6 路由表
ip -6 route show
2.2 有状态配置(DHCPv6)
需要分配 DNS 服务器地址或精确控制地址时,使用 DHCPv6。通过 RA 中的标志位(M/O 标志)决定主机是否使用 DHCPv6:
RA 标志组合:
- M=0, O=0:纯 SLAAC
- M=0, O=1:SLAAC + DHCPv6 提供其他配置(DNS)
- M=1, O=1:纯 DHCPv6(有状态)
一句话:SLAAC 解决「地址」问题,DHCPv6 解决「DNS 等其他参数」问题,两者常配合使用。
三、IPv6 与 IPv4 的核心差异
3.1 协议栈对比
| 维度 | IPv4 | IPv6 |
|---|---|---|
| 地址长度 | 32 位 | 128 位 |
| 报头复杂度 | 含选项,不固定 | 固定 40 字节基本头 + 扩展头链 |
| 广播 | 有(255.255.255.255) | 无,用组播替代 |
| 分片 | 路由器可分片 | 仅源主机分片(PMTUD) |
| 校验和 | 头部有校验和 | 头部无校验和(交给上下层) |
| NAT | 普遍存在 | 设计初衷是避免 NAT |
| 邻居发现 | ARP | ICMPv6 ND(NS/NA/RS/RA) |
| 自动配置 | DHCP | SLAAC + DHCPv6 |
3.2 头部结构对比
IPv4 头部(20 字节可变):
| Ver | IHL | TOS | Total Length |
| Identification | Flags | Frag Offset |
| TTL | Protocol | Header Checksum |
| Source Address (32 bit) |
| Dest Address (32 bit) |
| Options... |
IPv6 基本头(固定 40 字节):
| Ver | Traffic Class | Flow Label |
| Payload Length | Next Header | Hop Limit |
| Source Address (128 bit) |
| Dest Address (128 bit) |
Next Header 链:IPv6 用扩展头实现分段、路由、AH/ESP 等,每个扩展头用 Next Header 字段指向下一个:
IPv6 基本头 → Hop-by-Hop 选项 → 路由头 → 分段头 → 目的选项 → TCP/UDP
四、双栈部署方案
4.1 双栈架构
过渡期最稳妥的方案是双栈(Dual Stack):同一节点同时运行 IPv4 与 IPv6,DNS 同时解析 A 与 AAAA 记录,应用优先走 IPv6(Happy Eyeballs 算法)。
客户端(双栈)
│ ├─→ DNS 返回 A + AAAA 记录
│ ├─→ Happy Eyeballs 并行探测
│ ├─→ IPv6 可用 → 走 2001:db8::/64
│ └─→ IPv6 不通(快速回退)→ 走 IPv4 192.0.2.x
4.2 DNS 双栈配置
# BIND 双栈记录示例
zone "example.com" IN {
type master;
file "db.example.com";
};
# db.example.com
$TTL 86400
@ IN SOA ns1.example.com. admin.example.com. (2026092701 7200 3600 1209600 300)
@ IN NS ns1.example.com.
@ IN NS ns2.example.com.
@ IN A 192.0.2.10 ; IPv4 记录
@ IN AAAA 2001:db8:100::10 ; IPv6 记录
ns1 IN A 192.0.2.10
ns1 IN AAAA 2001:db8:100::10
www IN A 192.0.2.10
www IN AAAA 2001:db8:100::10
4.3 服务端监听双栈
# Linux 双栈监听(IPv6 socket 默认同时接受 IPv4 映射连接)
# 关闭 IPv4-mapped 的开关在 /proc/sys/net/ipv6/bindv6only=0(默认双栈)
ss -tln
# LISTEN 0 511 *:80 0.0.0.0:* (IPv4)
# LISTEN 0 511 [::]:80 [::]:* (IPv6 双栈)
# Nginx 双栈监听
server {
listen 80;
listen [::]:80; # IPv6
server_name example.com;
}
4.4 Happy Eyeballs(RFC 6555/8305)
双栈客户端最怕「IPv6 有配置但实际不通」造成的秒级卡顿。Happy Eyeballs 并行发起 IPv6/IPv4 连接,谁先成功用谁:
# Python 双栈连接回退示例
import socket
def connect_dual(host, port, timeout=1.0):
# 获取 A + AAAA 记录,先排 IPv6
addrs = socket.getaddrinfo(host, port, family=socket.AF_UNSPEC,
type=socket.SOCK_STREAM)
addrs.sort(key=lambda a: a[0] != socket.AF_INET6) # IPv6 优先
for family, _, _, _, sockaddr in addrs:
try:
with socket.socket(family, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect(sockaddr)
return s
except OSError:
continue
raise OSError("both IPv6 and IPv4 failed")
五、NAT64/DNS64 转换机制
5.1 NAT64 原理
纯 IPv6 网络需要访问 IPv4 服务时,用 NAT64 在中间把 IPv6 报文翻译成 IPv4 报文。与 NAT 类似,维护 IPv6→IPv4 地址映射表:
IPv6 客户端 ──→ 2001:db8:64::a.b.c.d ──→ NAT64 网关 ──→ 192.0.2.x (IPv4 服务)
↑ │
合成地址前缀 │ 维护 v6→v4 映射表 │
(64:ff9b::/96) └───────────────────┘
NAT64 使用专门前缀 64:ff9b::/96(Well-Known Prefix)合成 IPv6 地址,把 IPv4 地址嵌在低 32 位:
# 手算一个 NAT64 地址:IPv4 192.0.2.25
# 192.0.2.25 → 0xc0.0x00.0x02.0x19 → c000:0219
# NAT64 地址 = 64:ff9b::c000:219
ping6 64:ff9b::c000:219
一句话:NAT64 解决「IPv6 客户端访问 IPv4 服务」,是纯 IPv6 网络的出口转换器。
5.2 DNS64 协同
DNS64 与 NAT64 配合:客户端只有 IPv6,当它解析到只有 A 记录的域名时,DNS64 合成一个 AAAA 记录(NAT64 前缀 + IPv4 地址),让客户端走 IPv6 到 NAT64 网关:
IPv6 客户端
│ 查询 AAAA example.com
▼
DNS64 解析器
│ example.com 只有 A: 192.0.2.25
│ 合成 AAAA: 64:ff9b::c000:219
▼
IPv6 客户端 → NAT64 网关 → IPv4 服务
# 在 BIND 中启用 DNS64(dns64 特性需源码编译支持)
dns64 64:ff9b::/96 {
clients { any; };
exclude { any; };
};
六、隧道过渡技术
6.1 隧道分类
隧道把 IPv6 报文封装在 IPv4 中传输,适用于 IPv6 孤岛间互联:
| 隧道类型 | 特点 | 现状 |
|---|---|---|
| 6to4 | 使用 2002::/16 前缀,自动获取 IPv4 内嵌地址 | 已淘汰(RFC 7526 弃用) |
| Teredo | 解决 6to4 的 NAT 穿越,基于 UDP 封装 | 已废弃 |
| ISATAP | 企业内部 IPv4 网络承载 IPv6 | 已废弃 |
| 6in4 (static) | 手动配置 IPv4-in-IPv6 隧道 | 仍用于点对点 |
| GRE | 通用路由封装,承载多种协议 | 仍广泛使用 |
6.2 6to4 原理(历史上典型的自动隧道)
6to4 地址生成:
IPv4 地址 192.0.2.1 → 十六进制 c000:0201
6to4 前缀 = 2002:c000:0201::/48
6to4 路由器封装:
[IPv4 头 | IPv6 头 | 数据]
外层 IPv4:src=192.0.2.1, dst=192.0.2.2
内层 IPv6:src=2002:c000:0201::1, dst=2002:c000:0202::2
6to4 的致命缺陷是依赖公开的 6to4 中继、路径绕路且不可靠,已在 RFC 7526 中正式宣布弃用。现在实战更多使用可控的 GRE/6in4:
# Linux 配置 6in4 静态隧道(示例,实际地址需向隧道商申请)
ip tunnel add sit1 mode sit remote 198.51.100.1 local 192.0.2.1
ip link set sit1 up
ip -6 addr add 2001:db8:1::1/64 dev sit1
ip -6 route add ::/0 dev sit1
# 查看隧道状态
ip -s link show sit1
6.3 Teredo(RFC 4380)
Teredo 把 IPv6 报文封装在 UDP 中,可以穿越常规 NAT:
IPv6 主机 → Teredo 服务器(UDP 3544)→ Teredo 中继 → IPv6 主机
│ NAT 穿透(UDP hole punching)
Teredo 因性能差、复杂、依赖公共服务,已基本退出生产使用。过渡技术的主线已收敛为「双栈为主、NAT64/DNS64 兜底、可控隧道点对点补充」。
七、云环境 IPv6 实践
7.1 云厂商支持现状
| 云场景 | 典型做法 |
|---|---|
| VPC 双栈 | 子网分配 IPv6 CIDR,实例获得 GUA |
| 负载均衡 | ALB/NLB 支持 IPv6 监听,后端 IPv4/IPv6 |
| CDN | 边缘节点双栈,源站可仅 IPv4 |
| 对象存储 | 终端节点支持 IPv6 访问 |
| Kubernetes | ipFamily: IPv4+IPv6 双栈 Service/Pod |
| DNS | Route53/阿里云云解析支持 AAAA |
7.2 Kubernetes 双栈配置示例
# k8s Service 双栈
apiVersion: v1
kind: Service
metadata:
name: app-svc
spec:
ipFamilyPolicy: PreferDualStack # RequireDualStack / SingleStack
ipFamilies:
- IPv6
- IPv4
selector:
app: web
ports:
- port: 80
protocol: TCP
targetPort: 8080
7.3 云上排障常用命令
# 确认本机有 IPv6 地址与默认路由
ip -6 addr
ip -6 route show default
# 测试公网 IPv6 连通性(ping 谷歌的 DNS)
ping6 -c 3 2001:4860:4860::8888
# 测试 TCP 连接(指定 IPv6 地址)
curl -6 -v https://www.google.com
# 查看 IPv6 socket
ss -6 -tlnp
八、迁移排障
8.1 常见问题定位
| 现象 | 可能原因 | 排查命令/方法 |
|---|---|---|
| IPv6 不通但 IPv4 正常 | 路由缺失/防火墙未放行 | ip -6 route show default、traceroute6 |
| 访问网站超时 | 有 AAAA 记录但路径不通 | 检查 Happy Eyeballs 回退是否生效 |
| 隧道丢包严重 | 外层 IPv4 MTU 过小 | 调整隧道 MTU,ping -6 -s 1400 分段测试 |
| DAD 冲突 | 手动配置了重复地址 | 查看日志 `dmesg |
| 路由器通告未收到 | RA 被禁止/链路问题 | tcpdump -i eth0 icmp6 and 'ip6[40] == 134' |
8.2 抓包诊断
# 抓 ICMPv6 邻居发现(NS/NA/RS/RA)
sudo tcpdump -i eth0 'icmp6'
# 只看 DAD 探测
sudo tcpdump -i eth0 'icmp6 && ip6[40] == 135'
# 查看 IPv6 邻居表
ip -6 neigh show
# 清除邻居缓存重新学习
ip -6 neigh flush all
一句话:IPv6 排障的起点永远是「地址、默认路由、邻居表、防火墙」四件套,缺一不可。
九、总结
| 主题 | 关键知识点 | 实践建议 |
|---|---|---|
| 地址体系 | 128 位、GUA/ULA/链路本地/组播 | 用 /64 划子网,避免手工分配 |
| 自动配置 | SLAAC + DHCPv6 | 默认 SLAAC,需要 DNS 再加 DHCPv6 |
| 双栈 | A + AAAA、Happy Eyeballs | 过渡期第一选择,风险最低 |
| NAT64/DNS64 | 64:ff9b::/96 合成 | 纯 IPv6 网络访问 IPv4 服务的兜底 |
| 隧道 | 6to4/Teredo 已弃用 | 点对点用 6in4/GRE,勿依赖自动隧道 |
| 云实践 | VPC 双栈、K8s 双栈 Service | 新业务直接开通双栈 |
IPv6 不是「把地址变长」,而是对 IP 协议体系的一次重新设计:去掉了广播与 NAT,带来了 SLAAC 与更大的地址空间。过渡时代的主旋律是双栈平滑演进:让 IPv6 与 IPv4 长期共存,用 NAT64 兜底、用可控隧道打通孤岛,逐步降低对 IPv4 的依赖。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。