IPv6 代理不生效:双栈网络下 IPv4 与 IPv6 出口不一致的原因与排查
网络同时有 IPv4 和 IPv6(双栈)时,常见的“IPv6 代理不生效”其实是代理客户端只接管了 IPv4:访问支持 IPv6 的网站,系统优先走 IPv6 直连,流量根本没进代理。确认方法是分别看 IPv4 和 IPv6 的出口地址是否一致;处理上要么让代理客户端也接管 IPv6,要么让本机少用或不用 IPv6。下面按原因、确认、处理的顺序说明。
为什么双栈网络下代理会“失效”
Happy Eyeballs:系统默认偏向 IPv6
现代操作系统和浏览器在连接一个域名时,会同时查询 A(IPv4)和 AAAA(IPv6)记录。按照 Happy Eyeballs 算法(RFC 8305,前身是 RFC 6555),客户端会优先尝试 IPv6,只有在 IPv6 连接在很短时间内(RFC 8305 建议的默认值是 250 毫秒左右)没有建立起来时,才转去尝试 IPv4。
所以只要本机有可用的 IPv6 地址和默认路由,目标站点又有 AAAA 记录,连接大多会走 IPv6。国内不少家庭宽带和移动网络已经默认下发 IPv6 地址,很多机器一直处在双栈状态,只是平时没注意到。
哪些代理接管方式会漏掉 IPv6
代理是否受双栈影响,取决于它在哪一层接管流量。
| 接管方式 | 双栈下的表现 | 原因 |
|---|---|---|
| 系统代理 / 应用内 HTTP、SOCKS5 代理 | 通常不受影响 | 应用把域名直接交给代理,由代理端解析和连接,本机不发起 IPv6 连接 |
| 不读系统代理的程序(部分命令行工具、SDK) | 完全绕过代理,IPv4 和 IPv6 都直连 | 程序根本没走代理,与 IPv6 无关,但常被误判为 IPv6 问题 |
| TUN / 虚拟网卡模式,只配置了 IPv4 路由 | IPv4 走代理,IPv6 直连 | 虚拟网卡只接管 0.0.0.0/0,IPv6 默认路由仍指向物理网卡 |
| 代理客户端的 DNS 放行了 AAAA 记录 | 部分站点走 IPv6 直连 | 解析得到真实 IPv6 地址,而规则或路由没覆盖 IPv6 |
| 网关 / 软路由透明代理只处理 IPv4 | 局域网内所有设备都可能出现 IPv6 直连 | 防火墙规则只写了 iptables,没有写 ip6tables 或对应的 nftables 规则 |
最常见的现象:浏览器打开某个支持 IPv6 的站点,显示的地区与代理节点不一致;换一个只有 IPv4 的站点又正常;同一个页面刷新几次,结果时好时坏。最后这种情况是 Happy Eyeballs 在起作用:IPv6 偶尔慢一点,连接就回落到 IPv4。
还有一种情况不算故障:同一台机器访问不同服务时,出口不同。对于需要稳定出口的场景(例如调试 API 的地区路由、对比延迟),这会让测量结果无法复现。
怎么确认是 IPv6 绕过了代理
在浏览器里:用 /ip 对照 IPv4、IPv6 与多出口
打开 cdnping 的 IP 与环境检测,重点看三块:
- IPv4 / IPv6 检测:页面会分别给出 IPv4 和 IPv6 的出口情况。如果两者的地理位置、ASN 明显不同,例如 IPv4 显示为代理节点所在地的机房网段,IPv6 显示为本地运营商,基本可以确定是代理只接管了 IPv4。
- 多出口检测:页面会读取 Claude、ChatGPT、Grok 等站点的 Cloudflare trace,看访问不同站点时实际使用的出口。如果有的站点显示代理出口,有的显示本地出口,说明流量在不同路径之间分叉了。
- 大陆分流检测与 DNS 泄漏:分流规则和 DNS 配置也会造成出口不一致,可以顺带排除。DNS 泄漏的原理和判断方法见 DNS 泄漏与 WebRTC 泄漏。
如果要把检测结果发给同事或贴到 issue 里,可以在 /ip 生成带水印的结果图;生成前先打开隐藏 IP,图里就不会出现你的出口地址。页面上的浏览器指纹在本地计算,不会上传。
在终端里:用 curl -4 / -6 对照出口
浏览器之外的程序(命令行工具、SDK、IDE 插件)不一定和浏览器走同一条路,需要在终端里单独测一遍。Cloudflare 的 trace 接口会返回它看到的客户端 IP,适合做对照:
# 强制 IPv4
curl -4 -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
# 强制 IPv6
curl -6 -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
# 不加参数,看系统默认选了哪一个
curl -s https://www.cloudflare.com/cdn-cgi/trace | grep -E '^(ip|loc|colo)='
结果怎么读:
| 现象 | 判断 |
|---|---|
-6 报错 “Couldn't connect” 或无路由 | 本机没有可用 IPv6,问题不在这里 |
-4 显示代理出口,-6 显示本地运营商地址 | 代理只接管了 IPv4,属于本文讨论的情况 |
-4、-6 都显示本地地址 | 该程序没有走代理,先检查环境变量 HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 或改用 TUN 模式 |
-4、-6 都显示代理出口,且地区一致 | 双栈都已接管,出口不一致要从分流规则或 DNS 查起 |
不加参数时的 ip= 是 IPv6 地址 | 默认连接走了 IPv6,与 Happy Eyeballs 的行为一致 |
再补两条查看本机状态的命令:
# Linux:是否有全局 IPv6 地址和 IPv6 默认路由
ip -6 addr show scope global
ip -6 route show default
# macOS:查看各网卡的 IPv6 地址和 IPv6 路由表
ifconfig | grep inet6
netstat -rn -f inet6 | head -20
Windows 可以在 PowerShell 里执行 Get-NetIPAddress -AddressFamily IPv6 和 Get-NetRoute -AddressFamily IPv6 -DestinationPrefix ::/0。
如果你在排查调用 AI 接口的程序,可以把上面的 trace 地址换成目标 API 的域名,用 curl -4 -o /dev/null -w '%{remote_ip} %{time_connect}\n' 和 -6 各跑一次,看实际连上的地址和建连耗时。AGI Plan 是 cdnping 的商业合作方,用 AGI Plan 的读者可以用同样的方法对 agiplan.dev 做对照,再到 /status/agiplan 看 cdnping 镜像展示的 AGI Plan 可用率。
怎么修:四种处理办法与取舍
确认是代理只接管了 IPv4 之后,按下面的顺序考虑。一般先改代理客户端,影响范围最小;改系统和网关的影响依次变大。
办法一:在代理客户端里开启 IPv6 支持
多数支持 TUN 模式的客户端都有 IPv6 相关开关,名称通常是“IPv6”“启用 IPv6 路由”或在配置文件中给虚拟网卡加一个 IPv6 地址段。开启后,虚拟网卡会同时接管 ::/0,IPv6 流量也进入代理。
- 优点:本机网络保持完整,国内直连的站点仍然可以用 IPv6,不影响局域网内其他设备。
- 前提:代理链路本身要能处理 IPv6 目标。如果远端不支持 IPv6,常见做法是在客户端 DNS 中只返回 A 记录(不少客户端有“禁用 AAAA”或“仅 IPv4 解析”选项),让应用只发起 IPv4 连接。
- 注意:开启后要重新跑一遍上面的
curl -6对照,确认 IPv6 出口确实变了。
办法二:让系统优先使用 IPv4
不关掉 IPv6,只调整地址选择的优先级。这样遇到同时有 A 和 AAAA 记录的域名时,系统会先试 IPv4。
# Linux(glibc):在 /etc/gai.conf 中加入一行
precedence ::ffff:0:0/96 100
Windows 可以通过修改前缀策略实现,例如以管理员身份执行 netsh interface ipv6 set prefixpolicy ::ffff:0:0/96 60 4。macOS 没有同样简便的系统级开关。
- 优点:改动小,IPv6 仍然可用。
- 局限:只影响走系统解析器的程序;浏览器内置的 DNS-over-HTTPS、自带解析器的程序不一定遵守。只有 AAAA 记录的站点仍会走 IPv6 直连。
办法三:关闭系统 IPv6
效果最确定,副作用也最大。
# Linux 临时关闭(重启后恢复)
sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
# macOS 关闭 Wi-Fi 网卡的 IPv6(服务名以 networksetup -listallnetworkservices 为准)
sudo networksetup -setv6off Wi-Fi
# 恢复
sudo networksetup -setv6automatic Wi-Fi
Windows 可以在网卡属性中取消勾选“Internet 协议版本 6 (TCP/IPv6)”,或在 PowerShell 中使用 Disable-NetAdapterBinding -Name "以太网" -ComponentID ms_tcpip6。
- 优点:不再有 IPv6 直连的可能,出口行为最好预测。
- 代价:失去 IPv6 带来的直连路径,部分国内服务或运营商网络在 IPv6 下的表现可能更好;某些系统组件依赖 IPv6 环回或链路本地地址,全局关闭后可能出现难以定位的问题。微软的官方文档也不建议完全禁用 IPv6,推荐用前缀策略让 IPv4 优先。
- 建议:先用临时方式验证效果,确认问题解决后再决定是否持久化。
办法四:在网关或软路由上处理
如果局域网里的设备都受影响,问题多半出在网关的透明代理只写了 IPv4 规则。可以在网关上补齐 IPv6 的转发规则,或者在网关上关闭 IPv6 下发(不发 RA、不开 DHCPv6)。后者等于对整个局域网执行“办法三”,取舍相同。
四种办法对照
| 办法 | 影响范围 | IPv6 是否保留 | 适合谁 |
|---|---|---|---|
| 客户端开启 IPv6 | 本机 | 保留 | 客户端和远端都支持 IPv6 |
| 系统优先 IPv4 | 本机,仅系统解析器 | 保留 | 想少改动、先缓解问题 |
| 关闭系统 IPv6 | 本机 | 不保留 | 需要出口完全可预测 |
| 网关处理 | 整个局域网 | 视做法而定 | 多台设备同时出问题 |
以上办法只用于让本机的网络行为和你的配置一致,方便排障和测量,不涉及绕过任何服务的地区限制。使用境外服务时请遵守其服务条款和当地法律法规。
改完之后逐项检查
-
curl -4和curl -6的 trace 结果符合你的预期(一致,或-6已不可用) - 不加参数的
curl出口与浏览器一致 - /ip 页面的 IPv4 / IPv6 卡片与多出口检测没有出现分叉
- DNS 泄漏检测结果符合预期
- 在 首页测速 跑一次,对比改动前后各 API 的“首次连接”耗时,确认没有引入额外延迟
如果检测之后出口已经一致,但某个 AI 服务仍然打不开,问题可能不在本地网络。可以去 /down 看对应服务有没有其他用户报告,或在 /status 查看 cdnping 从 Cloudflare 边缘每 5 分钟一次的探测结果,再决定是继续排查本地,还是等待服务恢复。分流相关的概念可以接着读 分流(Split Tunneling)是什么。