ping6.net
迁移

NAT64 和 DNS64:将仅 IPv6 网络连接到 IPv4

部署 NAT64 和 DNS64,允许仅 IPv6 客户端访问仅 IPv4 服务。涵盖架构、配置和故障排除。

ping6.net2024年12月14日7 min read
IPv6NAT64DNS64migrationtransitionnetworking

仅 IPv6 的未来#

双栈——同时运行 IPv4 和 IPv6——是标准的迁移方法。但永远维护两个并行网络并不是目标。终点是仅 IPv6 基础设施,仅在必要时访问遗留 IPv4。

这种转变已经发生在移动网络中。主要运营商在智能手机上运行仅 IPv6 堆栈。T-Mobile、AT&T 和 Verizon 几年前从其 LTE/5G 网络中消除了 IPv4。你的手机有一个 IPv6 地址。当你访问仅 IPv4 网站时,NAT64 和 DNS64 透明地处理转换。

企业网络遵循相同的路径。仅 IPv6 降低了复杂性,消除了 IPv4 地址耗尽问题,并简化了路由。但完全消除 IPv4 目前还不现实——太多服务仍然仅支持 IPv4。NAT64 和 DNS64 弥合了这一差距,允许仅 IPv6 网络访问 IPv4 互联网。

TL;DR - 快速摘要

要点:

  • NAT64 将 IPv6 数据包转换为 IPv4;DNS64 从 A 记录合成 AAAA 记录
  • 众所周知的前缀 64:ff9b::/96 将 IPv4 地址嵌入到 IPv6 空间中
  • 移动网络广泛使用此技术(T-Mobile、AT&T、Verizon 是仅 IPv6)
  • DNS64 破坏 DNSSEC——合成记录与签名区域不匹配

跳转至: NAT64 和 DNS64 如何协同工作了解架构,实施选项了解部署,或限制了解已知问题。


NAT64 和 DNS64 如何协同工作#

NAT64 在网络层执行协议转换。DNS64 合成触发此转换的 IPv6 地址。它们作为一对工作——没有 NAT64 的 DNS64 是无用的,没有 DNS64 的 NAT64 需要手动配置。

转换流程#

以下是当仅 IPv6 客户端访问仅 IPv4 服务时发生的情况:

┌─────────────────────────────────────────────────────────────────┐
│ 1. 客户端查询 www.ipv4only.example.com 的 DNS                  │
│    查询类型:AAAA(IPv6 地址)                                   │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 2. DNS64 服务器查询上游 DNS                                      │
│    接收:A 记录 → 198.51.100.10(仅 IPv4)                       │
│    不存在 AAAA 记录                                              │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 3. DNS64 合成 AAAA 记录                                          │
│    组合 NAT64 前缀 + IPv4 地址                                   │
│    结果:64:ff9b::198.51.100.10                                 │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 4. 客户端接收合成的 IPv6 地址                                    │
│    向 64:ff9b::198.51.100.10 发送数据包                          │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 5. NAT64 网关拦截数据包                                          │
│    识别 64:ff9b::/96 前缀                                        │
│    提取嵌入的 IPv4:198.51.100.10                                │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 6. NAT64 转换 IPv6 → IPv4                                        │
│    更改数据包头                                                  │
│    执行有状态 NAT(跟踪会话)                                     │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 7. IPv4 数据包发送到目标                                         │
│    源:NAT64 网关 IPv4 地址                                       │
│    目标:198.51.100.10                                           │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│ 8. 返回流量转换回来                                              │
│    NAT64 查找会话                                                │
│    转换 IPv4 → IPv6                                              │
│    转发到客户端                                                  │
└─────────────────────────────────────────────────────────────────┘

客户端只看到 IPv6。仅 IPv4 服务只看到 IPv4。NAT64 和 DNS64 不可见地处理转换。

众所周知的前缀#

标准 NAT64 前缀是 64:ff9b::/96(RFC 6052)。这个众所周知的前缀告诉每个人"IPv4 地址嵌入在这里"。

IPv4 地址嵌入的工作方式如下:

IPv4 地址:   198.51.100.10
十六进制:    C6.33.64.0A
NAT64 前缀:  64:ff9b::
组合:        64:ff9b::c633:640a
扩展:        64:ff9b::198.51.100.10(常用表示法)

IPv6 地址的最后 32 位包含 IPv4 地址。应用程序永远看不到这个——它纯粹是转换基础设施的内部。

你可以使用自定义前缀而不是众所周知的前缀。常见选择包括组织特定的前缀,如 2001:db8:64::/96。这允许流量工程(以不同方式路由 NAT64 流量),但需要更改 DNS64 配置。

DNS64 深入分析#

DNS64 是具有特殊转换逻辑的 DNS 服务器。当仅存在 A 记录时,它拦截 AAAA 查询并合成响应。

DNS64 逻辑流程#

查询 example.com 的 AAAA

查询上游 AAAA

AAAA 记录存在?─ 是 ─→ 返回 AAAA 记录(本机 IPv6)



查询上游 A

A 记录存在?─ 否 ─→ 返回 NXDOMAIN



合成 AAAA = 前缀 + IPv4

返回合成的 AAAA

关键行为:

  • **本机 IPv6 优先:**如果 AAAA 存在,DNS64 返回不变。没有合成。不涉及 NAT64。
  • **仅 IPv4 回退:**仅当 AAAA 不存在时才发生合成
  • **缓存 TTL 保留:**合成记录从 A 记录继承 TTL
  • **DNSSEC 复杂性:**合成破坏 DNSSEC 验证(稍后详述)

DNS64 配置示例#

BIND 9:

options {
    // ... 其他选项 ...
    dns64 64:ff9b::/96 {
        clients { any; };
        mapped { !192.168.0.0/16; !10.0.0.0/8; any; };
        exclude { 64:ff9b::/96; ::ffff:0:0/96; };
        suffix ::;
    };
};

参数:

  • clients:哪些客户端获得 DNS64(通常是 any
  • mapped:要转换的 IPv4 地址(排除 RFC 1918 私有地址)
  • exclude:永远不合成的 IPv6 范围
  • suffix:自定义 IPv4 在地址中嵌入的位置(高级)

Unbound:

server:
    module-config: "dns64 validator iterator"
 
dns64:
    dns64-prefix: 64:ff9b::/96
    dns64-synthall: no
  • dns64-synthall:即使 AAAA 存在也是否合成(通常为 no)

PowerDNS Recursor:

# 在 recursor.conf 中
enable-dns64: yes
dns64-prefix: 64:ff9b::/96

DNS64 发现#

客户端需要知道哪个 DNS 服务器提供 DNS64。通常通过以下方式配置:

路由器通告(SLAAC):

# radvd.conf
interface eth0 {
    RDNSS 2001:db8::53 {
        AdvRDNSSLifetime 300;
    };
};

DHCPv6:

option dhcp6.name-servers 2001:db8::53;

现代操作系统接受来自 RA 和 DHCPv6 的 DNS 服务器。

NAT64 深入分析#

NAT64 是有状态转换——它像传统 NAT44 一样维护会话状态。每个客户端连接在 NAT64 网关的状态表中获得映射。

有状态转换#

NAT64 网关跟踪:

  • IPv6 源地址和端口
  • IPv4 目标地址和端口
  • 转换的 IPv4 源地址和端口
  • 协议(TCP/UDP/ICMP)
  • 会话计时器
会话表条目:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
IPv6 客户端侧          │  IPv4 服务器侧
━━━━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━━━━━━━━
2001:db8:100::45:1234  │  203.0.113.5:6789
  (客户端 IPv6:端口)   │    (NAT IPv4:端口)
                       │        ↕
                       │  198.51.100.10:80
                       │  (目标 IPv4:端口)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
协议:TCP
状态:已建立
超时:7440 秒

当返回流量到达 203.0.113.5:6789 时,NAT64 查找会话并转换回 2001:db8:100::45:1234。

协议转换#

NAT64 转换的不仅仅是地址——它在 IPv4 和 IPv6 数据包格式之间转换:

IPv6 数据包:

[ IPv6 头 | TCP/UDP/ICMP 头 | 有效载荷 ]

转换为 IPv4:

[ IPv4 头 | TCP/UDP/ICMP 头 | 有效载荷 ]

转换包括:

  • **TTL/跳数限制:**递减并复制
  • **分片:**IPv6 分片 → IPv4 分片(具有 MTU 注意事项)
  • **ICMP:**ICMPv6 → ICMPv4(消息类型映射)
  • **校验和:**为新协议头重新计算

寻址池#

NAT64 需要 IPv4 地址用于出站连接。小型部署使用单个 IPv4 地址和端口超载(如家庭路由器)。大型部署使用池。

# 小型:单个 IPv4
NAT64 池:203.0.113.5/32
最大客户端:约 65,000 个并发会话
 
# 大型:IPv4 池
NAT64 池:203.0.113.0/24
最大客户端:约 1600 万个并发会话

地址耗尽问题适用——NAT64 面临与 NAT44 相同的端口限制。

实现选项#

存在多个 NAT64 软件实现,从轻量级到运营商级。

TAYGA:轻量级用户空间#

TAYGA 是用于 Linux 的简单用户空间 NAT64 守护程序。适用于小型部署和测试。

安装:

apt-get install tayga
 
# 创建 TUN 接口
ip tuntap add name nat64 mode tun
ip link set nat64 up
ip addr add 192.168.255.1/24 dev nat64
ip addr add 2001:db8:ffff::1/96 dev nat64

配置(/etc/tayga.conf):

tun-device nat64
ipv4-addr 192.168.255.1
ipv6-addr 2001:db8:ffff::1
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
data-dir /var/lib/tayga

启动和路由:

systemctl start tayga
 
# 通过 TAYGA 路由 NAT64 前缀
ip route add 64:ff9b::/96 dev nat64
ip route add 192.168.255.0/24 dev nat64
 
# 启用转发
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv4.ip_forward=1

优点:简单、轻量级、易于设置 缺点:有限的性能(用户空间)、无集群、最小功能

Jool:内核模块#

Jool 将 NAT64 实现为 Linux 内核模块,提供更好的性能。

安装:

# 添加存储库(Debian/Ubuntu)
apt-get install linux-headers-$(uname -r)
apt-get install jool-dkms jool-tools
 
# 加载模块
modprobe jool

配置:

# 创建 NAT64 实例
jool instance add "default" --netfilter --pool6 64:ff9b::/96
 
# 添加 IPv4 地址池
jool -i "default" pool4 add --tcp 203.0.113.5 1024-65535
jool -i "default" pool4 add --udp 203.0.113.5 1024-65535
jool -i "default" pool4 add --icmp 203.0.113.5 1024-65535
 
# 启用
jool -i "default" global update enabled true

路由:

ip route add 64:ff9b::/96 via 2001:db8::1

优点:高性能(内核空间)、活跃开发、良好文档 缺点:内核模块复杂性、内核更新的偶尔兼容性问题

云提供商 NAT64#

主要云平台提供托管 NAT64:

AWS(通过仅出口互联网网关的 NAT64):

AWS 不提供本机 NAT64,但你可以在 EC2 实例上部署 Jool 或 TAYGA。存在一些第三方 AMI。

替代方案:使用双栈,IPv6 仅内部网络和 IPv4 用于外部访问。

Google Cloud Platform:

GCP 提供带 NAT64 支持的 Cloud NAT(测试版):

# 创建 NAT64 子网
gcloud compute networks subnets create nat64-subnet \
  --network=my-network \
  --region=us-central1 \
  --range=10.0.0.0/24 \
  --enable-nat64
 
# 配置 Cloud NAT
gcloud compute routers nats create my-nat64 \
  --router=my-router \
  --region=us-central1 \
  --enable-nat64 \
  --nat64-prefix=64:ff9b::/96

Azure:

Azure 支持 IPv6,但不提供托管 NAT64。使用带 Jool 或 TAYGA 的 Linux VM 部署自己的。

优点(托管服务):无维护、可扩展、集成监控 缺点:云特定、配置灵活性较低、潜在成本

测试 NAT64/DNS64 部署#

验证端到端连接:

# 测试 DNS64
dig AAAA ipv4.google.com @2001:db8::53
 
# 应该返回带 NAT64 前缀的合成 AAAA
# 示例:64:ff9b::8.8.8.8

如果没有 AAAA 记录,DNS64 不工作。

NAT64 连接测试#

使用特殊测试域 ipv4only.arpa

# 从仅 IPv6 客户端
ping6 ipv4only.arpa
 
# 应该通过 NAT64 接收回复
# 域解析为 192.0.0.170,合成为 64:ff9b::192.0.0.170

如果 ping 失败,NAT64 网关不可达或未转换。

监控和故障排除#

检查 NAT64 会话状态:

Jool:

jool -i "default" session display
 
# 显示活动会话
# 查找:客户端 IPv6、转换的 IPv4、目标

TAYGA:

cat /var/lib/tayga/dynamic.map
 
# 显示地址映射

高会话计数表示大量使用或潜在问题(连接泄漏)。

流量分析#

在转换前后捕获流量:

# 捕获到 NAT64 前缀的 IPv6 流量
tcpdump -i eth0 -n 'ip6 and dst net 64:ff9b::/96'
 
# 捕获转换的 IPv4 流量
tcpdump -i eth1 -n 'ip and src 203.0.113.5'
 
# 比较以验证转换

寻找:

  • 到达 NAT64 但未转换的数据包
  • 转换发生但数据包未转发
  • 不对称路由(返回流量未到达 NAT64)

安全注意事项#

NAT64 引入了超出典型 NAT 的安全影响。

地址空间扫描#

NAT64 前缀使 IPv6 中的 IPv4 地址可预测。攻击者可以扫描 64:ff9b::/96 以发现你正在访问哪些 IPv4 服务。

**缓解:**使用网络特定的 NAT64 前缀而不是众所周知的前缀,限制暴露。

绕过访问控制#

IPv4 访问控制(防火墙规则、ACL)可能不考虑来自意外 IPv6 来源的 NAT64 转换流量。

**缓解:**将安全策略应用于 NAT64 网关,而不仅仅是端点。

NAT64 作为攻击放大器#

仅 IPv6 网络上的攻击者可以使用 NAT64 对 IPv4 目标发起攻击,可能绕过基于 IPv4 的速率限制或黑名单。

缓解:

  • 每个源的速率限制 NAT64 会话
  • 记录所有 NAT64 转换以进行滥用调查
  • 应用与 IPv4 NAT 相同的安全策略

测试 NAT64 连接

使用我们的DNS 查询工具查询 DNS64 服务器并验证 AAAA 合成,使用Ping 工具测试通过 NAT64 的连接。

何时使用 NAT64/DNS64 与双栈#

决策框架:

┌─────────────────────────────────────────────────┐
│ 你能运行双栈吗?                                 │
└─────────────────────┬───────────────────────────┘

          ┌───────────┴──────────┐
          │                      │
         是                     否
          │                      │
          ▼                      ▼
   ┌─────────────┐     ┌─────────────────────┐
   │ 使用        │     │ 为什么不能?         │
   │ 双栈        │     │                     │
   │             │     │ • IPv4 耗尽          │
   │ (更简单,   │     │ • 架构简化           │
   │  问题更少)  │     │ • 移动网络           │
   └─────────────┘     │ • 云原生             │
                       └──────────┬──────────┘


                         ┌────────────────────┐
                         │ 使用 NAT64/DNS64   │
                         │                    │
                         │ 如果需要添加 464XLAT:│
                         │ • 仅 IPv4 应用      │
                         │ • 硬编码 IP          │
                         └────────────────────┘

NAT64/DNS64 适用于:

  • IPv4 地址耗尽是真正的约束
  • 你正在构建新基础设施(绿地)
  • 移动网络或云原生架构
  • 单栈的运营好处超过转换复杂性

双栈适用于:

  • IPv4 地址可用
  • 混合遗留和现代基础设施
  • 兼容性是最高优先级
  • 团队熟悉双栈

相关文章#

常见问题#

如果我有双栈,我需要 NAT64 吗?

不需要。双栈网络不需要 NAT64,因为 IPv4 和 IPv6 连接都是本机存在的。NAT64 专门用于仅 IPv6 网络访问仅 IPv4 目标。如果你有双栈,客户端使用 IPv4 直接访问 IPv4 服务器,使用 IPv6 直接访问 IPv6 服务器。

我可以在没有 DNS64 的情况下使用 NAT64 吗?

技术上是的,但不切实际。没有 DNS64,客户端需要通过在 NAT64 前缀中嵌入 IPv4 地址来手动构建合成的 IPv6 地址。这需要应用程序或用户知道 NAT64 前缀并执行手动转换。DNS64 自动化这一点,使 NAT64 透明。始终一起部署它们。

为什么我的 DNSSEC 验证在 DNS64 下失败?

DNS64 合成不存在于权威 DNS 区域中的 AAAA 记录。这些合成记录没有 DNSSEC 签名,导致验证失败。你可以在 DNS64 解析器上禁用 DNSSEC 验证,使用小心处理 DNSSEC 的 DNS64 实现(选项有限),或接受 DNSSEC 签名的仅 IPv4 域不会验证。这是一个已知的限制,目前没有完美的解决方案。

NAT64 和 NAT44 有什么区别?

NAT44 将 IPv4 转换为 IPv4(更改源地址,如家庭路由器所做的那样)。NAT64 在 IPv6 和 IPv4 之间转换(完全更改协议)。两者都维护会话状态并面临类似的端口耗尽问题。NAT64 更复杂,因为它必须转换数据包格式、处理 ICMP 类型映射并处理 IPv4 和 IPv6 之间的 MTU 差异。