“连不上”不一定是“被墙”:Xray 升级后,旧客户端内核握不上 REALITY

一个长期稳定的自建 VLESS + REALITY 节点,某天开始客户端全线 timeout。第一反应通常是“这个 IP 被 GFW 封了”——于是换网络、加中继、甚至准备换 IP。但在我们这次的排查里,IP 并没有被封:真正的变化发生在服务端——Xray 被升级到了新版本,而手上的旧客户端内核(Clash 用的 mihomo)已经握不上它的 REALITY 了。

这篇文章只讲我们实际验证过的事实:怎么把“被墙”和“客户端不兼容”分开,我们试过哪些办法、结果如何,以及——同样重要——哪些我们并没有证实

症状

  • 原本稳定的节点,突然开始大面积超时。
  • 换网络、换设备、换运营商,现象都差不多。
  • TCP 端口不一定完全不通,但客户端就是连不上。
  • 直觉上很像“IP 被盯上了”。

第一步:别急着判定“被墙”

关键的一点:“卡在 TLS / REALITY 握手”这个现象,被墙和协议不兼容都会产生,单看它分不出来。

还有两个常见误区要避开:

  • 普通 TLS 工具的失败不能当证据。对 REALITY 入站,curl / openssl s_client 本来就完不成握手(REALITY 会拒绝非授权握手),它们报错是正常的。
  • 要看内核自己的日志——xray / mihomo / sing-box 的连接日志,而不是外部工具的输出。

既然现象分不出来,就得做对照实验,把变量一个个拿掉。

决定性证据:在服务端本机走回环,换内核对照

这是整次排查里最有说服力的一步,也是我们真正确证的事实。

做法:在服务器本机,用不同的客户端内核、同样的参数,去连本机的 127.0.0.1 入站。这条路径不出公网、不经过任何跨境链路,等于把“网络封锁”这个变量直接拿掉,只剩下“客户端内核”这一个变量。

同一台机、同一时刻、同一个 127.0.0.1:443,结果是:

客户端内核(回环连本机入站) 结果
xray-core(与服务端同源、同版本) ✅ 握手成功
mihomo(与客户端同版本) ❌ 握手失败

结论很直接:这是“客户端内核 ↔ 服务端 Xray”的兼容性问题,跟 IP、跟网络封锁无关——因为这条路径根本没碰网络。回头一查,服务端的 Xray 确实在不久前被升级到了一个很新的大版本;而我们手上的旧客户端内核(至少本次测试的 mihomo / sing-box)跟不上它的 REALITY 了。

这也把“是不是被墙”摘了出去:回环这条路根本不出网络,等于把“封锁”这个变量排除在外。在我们这台机器上 IP 也确实没被封,于是问题就锁定在内核兼容性上。

我们在客户端侧试过的办法,都没把它救回来

很多人的第一反应是“升级一下客户端就好”。我们试了,对 mihomo / sing-box 不管用。以下都在服务端回环 / 链路上实测过:

尝试 结果
xray-core(直连 / 回环) ✅ 成功(唯一能过的)
mihomo 最新 stable + 最新 Alpha ❌ 失败
mihomo,7 种 uTLS 指纹逐个试 ❌ 全失败
mihomo,显式打开 support-x25519mlkem768 开关 ❌ 仍失败
sing-box(较新 uTLS 的版本) ❌ 失败

在我们这组测试里,唯一能稳定握上手的就是 xray-core,而且是在直连 / 回环下。所以实用的结论是:如果你直连节点、用的又是 Clash / mihomo,单纯升版本(包括打开那个常被怀疑的后量子开关)在我们这里没救回来——换一个 xray-core 内核的客户端,是我们这里唯一验证有效的办法。

如果你是经中继(proxy chain)连节点:客户端这条路走不通

有一类很常见的用法:节点是一个固定的境外出口,永远从一个墙外的前置跳板接进去,也就是 本地 → 前置跳板 → 境外出口 这条 proxy chain。

先说清楚:REALITY 本身并不是“不能被中继”——Xray 的 dialerProxy 本就支持链式拨号,把 REALITY 套在前置代理后面是常见用法。但在我们这台升级后的服务器上,我们试过的组合都没能让 REALITY 经中继跑通

  • xray-core 的 REALITY 经前置跳板转发到服务端——握手没成功(试过的两条中继表现还不一样:一条直接 EOF,一条到达服务端鉴权阶段后被判无效连接)。
  • 同一条中继转发普通 TLS 到同一端口却能通——说明中继能到达服务端、也扛得住 TLS——至少能把问题收窄到“这版 REALITY 经该中继转发”这一段(确切卡点我们没独立证实,见下文)。
  • 我们把客户端这边能试的组合(不同内核单独及混用、不同指纹、那个后量子开关)都试了,没有一个能让 REALITY 经中继接通

所以在“必须走中继”的场景里,客户端这条路我们没能走通。对症的做法是从服务端入手:把出口那一跳换成一个能被正常中继的协议(纯 TCP、两端内核都支持就行)。换掉之后,经前置跳板接入即可恢复。

顺带排除一个坑:在我们试过的 TCP 类中继上,Hysteria2 这类 UDP 协议也不合适。它是 UDP/QUIC,经 TCP 类中继要做 UDP-over-TCP 封装,而我们试的商业中继并不还原这种封装,照样超时。UDP 系协议(Hy2 / TUIC)更适合直连,要这样经 TCP 类中继转发往往不顺。

我们没有证实的部分(同样要讲清楚)

为了不把推测当结论,下面这些我们并没有坐实:

  • 没有证实“元凶就是后量子”。社区里常见一种归因:把这一轮“Xray 升级后旧客户端连不上”算到新版默认带上的后量子能力头上(如 X25519MLKEM768 密钥交换、以及可选的 ML-DSA-65 认证)。这与我们看到的现象不矛盾、也是重点怀疑对象;但我们这台服务器的入站当时其实没有显式的后量子字段,而且把客户端的 support-x25519mlkem768 打开也没用。所以我们能下的最稳结论只到——“新版 Xray 的 REALITY 与旧客户端内核不兼容”,至于具体卡在哪个特性,没有独立验证。
  • 没有证实 REALITY 经中继失败的确切机理。一个合理的猜测是:REALITY 的鉴权信息嵌在 ClientHello 里、对 TCP 分帧敏感,经中继重新分段后被破坏了——但这只是推断,我们也没排除中继自身实现的影响。

结论:一套可复制的判断流程

  1. “卡在握手”既不能证明是 GFW、也不能证明不是——别靠现象拍脑袋。
  2. 服务端本机走 127.0.0.1 回环、换不同客户端内核对照:如果结果按内核分成败,就能确认存在协议兼容性问题,且这一部分换 IP、加中继都解决不了(这条路径不碰网络,封锁与否被排除在外)。
  3. 如果只有 xray-core 能连,多半是服务端 Xray 升级后、旧客户端内核没跟上。直连场景 → 换 xray-core 内核的客户端;走中继场景 → 从服务端把出口换成能被中继的协议。

一句话:这类故障也许不是“IP 被墙”,而是“服务端升级了、客户端没跟上”。在下结论、急着换 IP 之前,先用回环对照把“协议不兼容”这条单独验掉。

参考资料

  1. XTLS / Xray-core, PR #4915 “REALITY protocol: Add optional Post-Quantum ML-DSA-65 verification”(后量子认证的来源)
    https://github.com/XTLS/Xray-core/pull/4915
  2. XTLS / Xray-core, transport/internet/reality/reality.gomain 分支会漂移,复核时建议钉到具体 release tag)
    https://github.com/XTLS/Xray-core/blob/main/transport/internet/reality/reality.go
  3. MetaCubeX / mihomo v1.19.9 release(加入 support-x25519mlkem768
    https://github.com/MetaCubeX/mihomo/releases/tag/v1.19.9
  4. sing-box documentation, “TLS Shared Fields”
    https://sing-box.sagernet.org/configuration/shared/tls/
  5. NIST FIPS 203, “Module-Lattice-Based Key-Encapsulation Mechanism Standard”
    https://csrc.nist.gov/pubs/fips/203/final
  6. NIST FIPS 204, “Module-Lattice-Based Digital Signature Standard”
    https://csrc.nist.gov/pubs/fips/204/final

致谢与署名

本文的排查与初稿由 Claude Code 完成:复现“全线 timeout”、区分“TCP 连通性”与“握手失败”、在服务端走 127.0.0.1 回环用不同客户端内核做对照实验,把病根定位到「新版 Xray REALITY 与旧客户端内核不兼容」,并实测发现这版 REALITY 经我们试过的中继转发都跑不通(同一条中继转发普通 TLS 却能过)。

站点维护者(本博客作者)做了几处关键决断与一手事实纠正——尤其是坚持“这个 IP 其实没被封”的判断(正是它把方向从“绕中继对抗封锁”拉回到“换协议 / 对齐版本解决兼容性”),并在 Windows / iOS 上做了实测验证。

技术准确性、逻辑严谨度与引用规范的审校由 codex(OpenAI Codex) 完成:对论断逐条复核(包括把若干超出证据的措辞收紧),并校准了术语与参考文献。