向 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 的文章对此亦有所提及。