logo NodeSeekbeta

CloudCone 迁移后网络问题修复说明

VPS 迁移后 TCP 能连上,但 TLS 握手永远超时。这次排查全程交给 pi agent(背后是 GLMkk-5.2)完成——从登录服务器、定位根因到修复并持久化,一条龙。

背景

CloudCone 发了公告说 VPS 要迁移。迁移完成后,部署在上面的 reddit-summary 服务状态变成了 unhealthy。

reddit-summary 是一个 Next.js 应用,连接 Neon(Serverless PostgreSQL)作为数据库。迁移后,公网 IP 发生了变化,应用日志开始报数据库连接错误。

我对 pi agent 说:"登录 CloudCone,重启下 reddit-summary。"

接下来的事情,全部是 agent 自主完成的。


经过

第一步:以为是 DNS

Agent 登录服务器,读容器日志,赫然写着:

Error: getaddrinfo EAI_AGAIN ep-xxx-pooler.c-2.us-west-2.aws.neon.tech

DNS 解析失败?Agent 立刻测试,结果 DNS 完全正常。继续往下查。

第二步:重启容器——还是不行

重启 reddit-summary 容器,应用日志显示 ✓ Ready in 0ms,但 curl localhost:8000/en 直接超时。

Agent 进入容器,发现是数据库连接卡住了——查询一直 pending,最终超时。

第三步:逐层排查——TCP 通,TLS 死

这是排查中最关键的一步。Agent 开始逐层测试到 Neon 数据库的连通性:

测试项 结果
DNS 解析 ✅ 正常
TCP 连接 Neon:5432 ✅ 成功
PG SSLRequest 握手 ✅ 收到 'S' 响应
TLS 握手 30 秒超时,卡死

TCP 能连上,PostgreSQL 协议层握手也正常,但 TLS 握手永远完不成

更诡异的是,这不是 Neon 独有的问题——所有 AWS 区域的 TLS 连接都超时

ec2.us-west-2.amazonaws.com:   ❌ 超时
ec2.us-east-1.amazonaws.com:   ❌ 超时
ec2.ap-northeast-1.amazonaws.com: ❌ 超时

而 Cloudflare 前端的站点却正常(ifconfig.me HTTP 200)。

第四步:排除嫌疑

Neon 的 IP 白名单? Neon 开启了公网访问,没有 IP 限制。DNS 返回的 IP 也完全一致,没有被劫持。

从其他服务器测试呢? Agent 换一台没有迁移的服务器测试同一个 Neon 数据库,TLS 握手完全正常。同样的数据库,别的机器能连,CloudCone 不能连。问题出在 CloudCone 迁移后的网络。

第五步:灵光一现——MTU

"TCP 能连上,但 TLS 握手超时"——Agent 识别出这个症状是 MTU 问题的典型表现。

TCP 握手用的是小包(SYN/SYN-ACK/ACK 都几十字节),PG 的 SSLRequest 只有 8 字节。但 TLS 握手中服务端要返回证书链,这是一个大包。如果路径中某处的 MTU 比预期低,大包就会被丢弃。

先测 MTU——带 DF 位的 ICMP ping 全部通过,1472 字节都没问题。ICMP 大包没问题,但 TCP/TLS 有问题。

区别在于:TCP 依赖 Path MTU Discovery (PMTUD),而 PMTUD 依赖 ICMP "需要分片" 消息。如果这些 ICMP 消息被屏蔽,TCP 就无法发现正确的 Path MTU。

Agent 直接验证——临时添加一条低 MTU 的路由:

$ ip route add <neon-ip> via <gateway> dev eth0 mtu 1200
$ python3 tls_test.py
TLS_OK: TLS_AES_256_GCM_SHA384  # ✅ 成功了!

实锤了。 降低 MTU 后 TLS 握手立即成功。

第六步:找到精确的 Path MTU

Agent 二分搜索定位边界:

MTU TLS 握手
1492 ❌ 超时
1480 ❌ 超时
1470 ✅ 成功
1450 ✅ 成功

Path MTU ≈ 1470(标准 1500 减去约 30 字节,这是 VXLAN/隧道封装的典型开销)。

第七步:修复——比想象中复杂

降低宿主机 eth0 的 MTU 到 1400:

$ ip link set eth0 mtu 1400

宿主机 TLS 连接恢复了。但 Docker 容器内的数据库连接还是超时!

Agent 发现原因:Docker 容器使用独立的网络命名空间,容器的虚拟网卡(veth)MTU 仍然是 1500。容器内 TCP 栈按 1500 计算分段大小,发出的数据包带 DF 位,超过路径 MTU 被丢弃。

先试了 iptables MSS clamping:

iptables -t mangle -A POSTROUTING -o eth0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

规则匹配了 SYN 包,但容器发出的数据包仍然超限——TCPMSS target 只修改 SYN 包的 MSS 选项,不会拆分已经生成的数据包。容器的 TCP 栈根本不知道实际 Path MTU 是多少。

最终方案:让 Docker 网络本身使用 MTU 1400。

Agent 在四个层面做了持久化配置:

1. 宿主机网卡     /etc/network/interfaces → mtu 1400
2. Docker daemon  /etc/docker/daemon.json → "mtu": 1400
3. Compose 网络   docker-compose.yml → networks.default.driver_opts.mtu: "1400"
4. iptables 兜底  TCPMSS --set-mss 1360 (netfilter-persistent 持久化)

重建容器网络后,容器内的 veth 接口 MTU 变为 1400,TCP 栈正确感知到较低的 MTU,所有连接恢复正常。


结果

服务恢复

检查项 结果
reddit-summary 容器 ✅ healthy
数据库连接 ✅ 276ms / 930 条记录
HTTP 健康检查 ✅ HTTP 200

重启验证

Agent 主动提议重启 VPS 验证持久化。重启后所有配置自动生效,容器自启动恢复,无需任何手动干预。


总结

根因:CloudCone VPS 迁移后,底层网络引入了 VXLAN 或类似的隧道封装,使实际 Path MTU 从 1500 降到了约 1470。同时 ICMP 分片消息被屏蔽,导致 PMTUD 失败。表现为 TCP 连接正常但大包传输失败——服务端返回的 TLS 证书链(大包)被静默丢弃,所有到 AWS 的 TLS 连接超时。

关键教训

  1. "TCP 通但 TLS 超时" ≈ MTU/PMTUD 问题。 这个症状非常有辨识度,值得记住。
  2. ICMP ping 测 MTU 可能骗你。 ICMP 可能走不同路径或不设 DF 位。真正的问题是 TCP 大包在转发时被丢弃。
  3. Docker 容器的 MTU 需要单独配置。 宿主机 MTU 改了不够,容器的虚拟网卡、bridge 网络、compose 网络都要同步。最可靠的方式是在 Docker daemon 和 compose 网络层面设置 "mtu": 1400
  4. iptables TCPMSS clamping 不是万能的。 它只改 SYN 包的 MSS 选项,对容器内 TCP 栈已经生成的大数据包无效。必须从网络接口 MTU 层面解决。

排查路径图

服务 unhealthy
  └── 日志: DB 连接超时
       └── DNS 正常、TCP 正常、PG 握手正常
            └── TLS 握手超时 ← 关键症状
                 └── 所有 AWS 区域都超时,Cloudflare 正常
                      └── 别的机器能连,CloudCone 不能连
                           └── 降低路由 MTU → TLS 成功 ← 实锤 MTU 问题
                                └── 宿主机修复 + Docker 网络修复 → 完全恢复

整个过程,Agent 自主完成了登录、诊断、修复、持久化、重启验证——从最初的一句指令到最终修复,中间没有人工介入。VPS 迁移后网络出问题,如果 TCP 能通但 TLS/HTTPS 卡住,第一个该查的就是 MTU。

12
  • 我记得早有人说了改mtu到1420了
    =。=

  • image
    当时直接秒回的

  • 到期一定会和这家说再见,永远不会再买。

  • 这 cc 是不是得修复

  • @sinstar #1 哈哈,不太注意。只能说cloudcone太草台了,还得浪费我token给它擦屁股~~

  • tm 的我的3天了还没上线。

  • 学到了,ai威武~

    为什么迁移后 MTU 出了问题

    正常情况下,网络包的 MTU 是 1500 字节。数据包从你的服务器发出去,沿途任何一
    段链路的 MTU 如果低于 1500,路由器会回发一个 ICMP "包太大,需要分片" 消息,
    你的 TCP 栈收到后就会自动降低发送的包大小。这个机制叫 PMTUD(Path MTU
    Discovery)。

    迁移后发生了什么:

      你的服务器 (MTU 1500)
          │
          │  发出 1500 字节的包
          ▼
      CloudCone 内部隧道 (VXLAN 封装,实际只能过 ~1470 字节)
          │
          │  包太大 → 丢弃
          │  应该回发 ICMP "需要分片" 消息 → 但被屏蔽了!
          ▼
      互联网 → 目标服务器
    
    1. CloudCone 迁移后,底层网络加了 VXLAN 隧道封装,每个包多了约 30 字节开销,
      实际 Path MTU 从 1500 降到了 ~1470
    2. ICMP 分片消息被屏蔽,导致 PMTUD 失效——TCP 栈永远不知道实际只能过 1470 字
    3. 于是 TCP 以为能发 1500 字节的包,但超过 1470 的包被静默丢弃

    为什么是"小包通、大包死"

    ┌────────────────────┬─────────────────┬──────────────────────┐
    │ 包类型 │ 大小 │ 结果 │
    ├────────────────────┼─────────────────┼──────────────────────┤
    │ TCP 握手 (SYN/ACK) │ ~几十字节 │ ✅ 通过 │
    ├────────────────────┼─────────────────┼──────────────────────┤
    │ PG SSLRequest │ 8 字节 │ ✅ 通过 │
    ├────────────────────┼─────────────────┼──────────────────────┤
    │ TLS 证书链 │ 可达 1400+ 字节 │ ❌ 超过 1470,被丢弃 │
    └────────────────────┴─────────────────┴──────────────────────┘

    所以表现为:TCP 连接成功,但 TLS 握手永远完不成。

    为什么修改 MTU 能修复

    把服务器 MTU 从 1500 降到 1400,TCP 栈从一开始就只发 1400 字节以内的包,根本
    不会触发那个坏掉的隧道瓶颈,绕开了 PMTUD 失效的问题。

    简单说就是:隧道让路变窄了,ICMP 通知机制又坏了,那我就主动把车改小,不等你
    通知了。

  • 多谢!解决了相同的问题。

  • 我敲,改完宿主机还得该容器配置,阿三不管了嘛 xhj017

  • 真的纯纯垃圾 还买了个30$一年的想着稳定了 稳个锤子...

12

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有63707位seeker

🎉欢迎新用户🎉