IPv6 开关实录:关掉,再打开
这台 VPS 的 IPv6 被关过一次,后来又打开了。两次操作都踩到同一个坑:改 IPv6 时 SSH 会掉。 文章记录当前实际参数、两次切换的完整步骤,以及那个掉线的原因。
当前的 IPv6 参数
| 项目 | 值 |
|---|---|
| 地址 | 2602:f656:101:18::e129:7f20 |
| 前缀长度 | /48(2602:f656:101::/48) |
| 默认网关 | 2602:f656:101::1(on-link) |
| 链路本地地址 | fe80::5054:ff:fe5c:7d0b/64 |
| 配置方式 | 静态,写在 /etc/network/interfaces |
| 网卡 / MTU | ens3 · 1500 |
| DNS | 8.8.8.8 · 1.1.1.1(rotate) |
| 状态 | disable_ipv6 = 0,双栈监听 80 / 443 |
关闭时做了什么
cat > /etc/sysctl.d/99-disable-ipv6.conf <<'EOF'
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
sysctl -w net.ipv6.conf.all.disable_ipv6=1
sysctl -w net.ipv6.conf.default.disable_ipv6=1
sysctl -w net.ipv6.conf.lo.disable_ipv6=1
效果是立刻的:ip -6 addr 里的全局地址与默认路由消失,curl -6 会报
Cannot assign requested address,IPv4 完全不受影响。
重新打开时踩的坑
直觉是把 sysctl 设回 0 就完事,但地址不会自己回来 —— disable_ipv6=1 只是移除了地址,
ifupdown 的"已配置"状态还停在旧值,所以把 sysctl 放开之后必须手动补地址与路由,
否则 ip -6 addr 依旧是空的:
rm -f /etc/sysctl.d/99-disable-ipv6.conf
sysctl -w net.ipv6.conf.all.disable_ipv6=0
sysctl -w net.ipv6.conf.default.disable_ipv6=0
sysctl -w net.ipv6.conf.lo.disable_ipv6=0
sysctl -w net.ipv6.conf.ens3.disable_ipv6=0
# 补回静态地址与默认路由(不要 ifdown/ifup,会把 IPv4 一起断掉)
ip -6 addr add 2602:f656:101:18::e129:7f20/48 dev ens3
ip -6 route add default via 2602:f656:101::1 dev ens3
地址加进去后会短暂处于 tentative 状态(DAD 重复地址检测),几秒后变成 preferred
才开始转发。验证标准是三条:
ip -6 addr show ens3 # 出现 inet6 ... scope global preferred
ping -6 -c2 2602:f656:101::1 # 网关 0% 丢包
curl -6 -s -o /dev/null -w '%{http_code}\n' https://www.cloudflare.com/cdn-cgi/trace # 200
重启后无需手动干预:/etc/network/interfaces 里的 iface ens3 inet6 static
会在 auto ens3 拉起时一起配置。
为什么每次切换 IPv6 都掉 SSH
查看连接后发现关键细节:SSH 会话是由 sshd 的 [::]:51439 双栈套接字接受、
以 v4-mapped 形式承载的 IPv4 连接(ss -tnp 里对应 sshd fd=4,
对端显示为 207.57.74.47:57590)。
一旦 disable_ipv6 被改写,内核会重置这批双栈套接字上的连接 —— 于是 IPv4 的 SSH 跟着断。
这跟"IPv6 关掉会影响 IPv4"没关系,纯粹是套接字族的问题。
下次要在生产机上动 IPv6,先把 sshd 收敛到只监听 IPv4(AddressFamily inet或显式ListenAddress 0.0.0.0),再操作;或者直接用云厂商的 VNC 控制台兜底。
域名侧:AAAA 记录
机器开启双栈只是第一步,域名解析里还必须有一条 AAAA 记录,客户端才会尝试 IPv6:
speedtest.heodiy.com. A 207.57.74.47
speedtest.heodiy.com. AAAA 2602:f656:101:18::e129:7f20
只有 A 记录时,curl -6 与浏览器都会直接走 IPv4;
想强制验证 IPv6,可以不经过 DNS,直接命中字面量地址:
curl -k -H 'Host: speedtest.heodiy.com' -o /dev/null \
-w '%{http_code}\n' 'https://[2602:f656:101:18::e129:7f20]/st/ping.txt'
-k 跳过即可;正常通过域名访问不受影响。