这是 IPv6 改造里最常见的一个坑,也是最容易被忽略的。

服务器有 IPv6 地址,防火墙也放行了,但 IPv6 用户还是连不上。原因在服务本身:它只监听了 IPv4。

表现是什么

IPv6 TCPing 对 443 端口测试,结果是连接被拒绝,或者直接超时。

拒绝说明包到了目标,但那个地址的端口没有服务。超时说明包被丢弃。两种结果都可能出现,取决于操作系统和防火墙的具体行为。

关键是:IPv4 侧一切正常,网站对大多数用户可用,问题很难被主动发现。

为什么 0.0.0.0 不行

0.0.0.0 是 IPv4 的通配地址,表示监听本机所有 IPv4 地址。它不包含 IPv6。

IPv6 的通配地址是 ::。只绑定 0.0.0.0 的服务,IPv6 连接进不来。

很多人以为 0.0.0.0 就是“所有地址”,这是 IPv4 时代的习惯,在双栈环境里不成立。

Nginx 怎么改

最常见的是 Nginx。只写 listen 443 ssl; 时,它只监听 IPv4。

要加一行 listen [::]:443 ssl;,或者把两行都写上。改完 reload,不是 restart 才生效。

Apache 要确认 Listen [::]:443,Node 服务要绑定 :: 而不是 0.0.0.0,Python 的 HTTPServer 也有类似参数。

怎么确认改对了

在服务器上执行 ss -lntp,看 443 端口的监听地址。

出现 [::]:443 或 *:443,说明 IPv6 在听。只有 0.0.0.0:443,说明还没配好。

然后用 IPv6 TCPing 从外部测一次,握手成功才算真的通了。本地 curl -6 也能验证,但只能代表服务器自己。

一个例外

有些服务用 :: 监听时会同时接受 IPv4 连接,这是操作系统的双栈行为,取决于 net.ipv6.bindv6only 设置。

不确定的话,最稳的做法是显式写两行监听,IPv4 和 IPv6 各一行,行为最可预期。