在纯 IPv6 终端上,SSH 等仅支持 IPv4 的工具无法直连 IPv4 地址,必须手工拼接 NAT64 前缀(如 `64:ff9b::1.3.3.7`)。Linux 的 `LD_PRELOAD` 机制允许在运行时拦截 `socket()`、`connect()` 等网络系统调用,将 IPv4 连接自动转换为带 NAT64 前缀的 IPv6 地址,从而在不修改应用代码的前提下实现透明访问。
**原理与工具链:**
作者在 Ubuntu 上部署 Tayga NAT64 网关(运行于 RockPro64 SBC),终端仅保留 IPv6 地址。当应用调用 `connect(1.3.3.7)` 时,内核返回“Network is unreachable”。TNAT64(已收录于 Debian/Ubuntu 官方仓库)提供动态库 `/usr/lib/tnat64/libtnat64.so`,通过 `export LD_PRELOAD=/usr/lib/tnat64/libtnat64.so` 注入进程,拦截 `socket()`、`connect()`、`getpeername()`、`getsockname()` 四个符号,将目的地址重写为 `64:ff9b::` 前缀拼接的 IPv6 映射地址,随后交由内核走 NAT64 网关完成 IPv4 通信。
**部署与调试:**
安装仅需 `sudo apt install -y tnat64`。启用时需同时设置三个环境变量:`LD_PRELOAD` 指定库路径,`TNAT64_DEBUG=10` 与 `TNAT64_DEBUG_FILE=/tmp/tnat64.log` 开启调试日志。生效后,同一终端会话内直接执行 `ssh 1.3.3.7` 即可建立连接,日志文件记录每次拦截的原始地址、重写后地址及系统调用返回值,便于排查失败案例。
**适用边界与风险:**
原文明确建议仅对“存在明确 IPv6 支持缺陷”的应用启用。因 `LD_PRELOAD` 仅拦截动态链接的 libc 符号,静态链接或直接发起系统调用的程序(如 Go 语言二进制)不受影响;且部分应用对文件描述符、地址族变更敏感,可能触发未预期的 `errno` 或协议不匹配。生产环境需先在测试会话验证日志无异常,再考虑纳入启动脚本。
对运维而言,TNAT64 以零代码改动、零内核补丁的方式填补了 IPv6 单栈终端的“长尾兼容”缺口,特别适合开发机、跳板机等可控环境;但在高并发、多线程或对延迟敏感的服务中,仍需评估拦截层带来的额外开销与潜在兼容性风险。
原文: APNIC Blog(2023-06-21)|编译自 APNIC Blog,事实以原文为准。
来源:APNIC Blog