向 IPv6 only 奔去

借助 CLAT 实现单栈 IPv6 接入

夜に駆ける

Prerequisites #

464XLAT (Customer-side Translator + NAT64) | RA PREF64 | DHCP option 108

《只有 IPv6 的网络与 IPv4 最后的倔强》
(正值 PHP 大冲击,Soha 的博客无法访问,此处贴上 archive.org 存档)

CLAT Availability #

笔者第一次阅读上文时大受震撼,相信稍有折腾过 NAT64+DNS64 的读者也有这种感受:我们终于形成了一种成熟的、在接入层完全切换到 IPv6 的方案。上月决定不再等待 Windows 正式版下放 CLAT 支持后,笔者基于 NetworkManager 的 eBPF 实现 向 LLM 许愿并得到了一个工作的 WFP 驱动。

基本思路是注入 DHCP 请求将 108 加入 option 55 列表,收到有效 option 108 后拦截后续报文,解析 RA option type 38 (PREF64) 拿到 NAT64 前缀并检查路由,随后预留端口、安装 WFP 规则、添加 192.0.0.0/29 地址及 on-link 默认路由;WFP 拦截 IPv4 出站,映射源端口并转为 IPv6 发出,对入站连接查询映射表匹配 CLAT 流量,重建后注入 IPv4 接收路径,由系统继续处理。一些细节此处不作讨论,经过数轮 review 后整体工作良好。

那么原始码或预编译文件在哪里取得呢?

…已经没有这个必要了。十月安全补丁 (KB5127646) 一声炮响,送来超过 1400 条安全修复的同时,悄然启用了 CLAT 支持。

微软没有在公告提及这个小小的改动。数小时前笔者突然注意到,自从上周被强制推送更新重启后,驱动从未被加载或启动,但是

> ipconfig

Windows IP Configuration


Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Intel(R) Ethernet Connection (11) I219-LM
   Physical Address. . . . . . . . . : redacted
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes

<snip>

   IPv4 Address. . . . . . . . . . . : 192.0.0.1(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.255
   Default Gateway . . . . . . . . . : redacted
                                       192.0.0.0
> netsh.exe interface clat show global
------------------------------------
permit                 : enabled
pref64fromdns          : enabled
pref64fromra           : enabled
autoenable             : enabled
store                  : active

好时代,来临了!

Enable CLAT #

笔者不确定 Windows 上是否需要干预,先前尝试修改的系统设置仅有组策略相关项。

Announcing Windows CLAT Public Preview

The CLAT configurations for permit, pref64 from DNS, and pref64 from RA are available in the group policy template under Network -> TCPIP Settings -> IPv6 Transition Technologies.

在 NetworkManager 1.58 及以后,编辑 /etc/NetworkManager/system-connections/ 下对应的 profile,添加

[ipv4]
clat=1
dhcp-ipv6-only-preferred=2

重启 NetworkManager 即可。

NAT64 Setup #

参考 OpenWrt Wiki 中在独立 netns 运行 jool 一节。步骤详尽且正确,此处不再复述。

如果需要到 IPv4 的端口转发,使用 jool bib 映射到 netns 下接口地址,正常设置转发即可。


适用 Android 设备的建议两则:

  • NAT66 下 ULA 前缀使用 3fff::/20

ULA 一般使用 fc00::/7,但 Android 的 CLAT 实现 要求 设备获得非 RFC4193 地址;出于与使用 NAT66 同样的原因,尽管使用 unreachable 的 GUA 是错误的行为,笔者对此也没有太好的办法。

为什么不使用更常见的 2001:db8::/32?it did work for a while 但是两周后 magicsock 突然试图将其作为公网地址连接…

"?!"

  • 设置合理的 RA lifetime

Soha 的文章对此亦有所提及。