3x-ui 节点故障排查复盘

最后更新:2026-09-02
文章目录 15 个章节

这次遇到的现象是:3x-ui 面板能打开,订阅也能生成,但客户端里的 VLESS 和 Hysteria2 节点都无法使用。表面看起来像端口、防火墙或客户端配置问题,最后却是两个完全不同的协议层故障叠在一起。

本文隐去了服务器地址、端口、UUID、订阅 ID、密钥和登录凭据。命令中的域名、路径和端口都是示例,实际操作前请换成自己的值。

先说结论

  • VLESS + TCP + Reality 的服务进程和端口都正常,真正失败的是 Reality 伪装目标的 TLS 握手。目标站点的证书记录数超过 Xray Reality 当前可解析的上限,导致服务端在握手阶段直接断开连接。
  • Hysteria2 使用了自签名证书,证书的 CN/SAN 与订阅里的 SNI 虽然能对上,但客户端没有开启不安全模式,因此严格校验证书链时会拒绝连接。
  • 修复不能只看“端口是否监听”。最终必须分别验证 TCP/Reality 握手、QUIC/TLS 证书和真实客户端订阅,三者缺一不可。

环境与症状

故障服务器是 Debian 13,运行 3x-ui 3.7.0 和 Xray-core 26.7.28,配置了两类入站:

入站 传输 现象
VLESS TCP + Reality 节点显示在线,但客户端连接后立即断开
Hysteria2 QUIC/UDP + TLS 节点无法建立连接,严格校验模式报证书错误

面板本身可以访问,订阅链接也能返回内容。为了避免把“面板正常”误判成“节点正常”,我先从服务状态和监听状态开始。

第一步:先排除服务、端口和防火墙

在服务器上执行:

systemctl status x-ui --no-pager
ss -lntup | grep -E 'xray|x-ui|你的端口'
journalctl -u x-ui -n 100 --no-pager

这里要同时观察四件事:

  1. x-ui 是否为 active (running);
  2. Xray 是否真的监听了对应的 TCP 和 UDP 端口;
  3. 日志中是“没有监听”还是“已经收到连接但握手失败”;
  4. 云安全组、主机防火墙和运营商入口规则是否放行了正确的协议。

这次检查显示服务正常,TCP/UDP 端口都在监听,连接计数也有变化。也就是说,请求确实已经到达 Xray,继续盯着防火墙没有意义,应该转向协议日志和生成后的 Xray 配置。

第二步:定位 Reality 的握手失败

1. 不要只看面板,检查生成配置

3x-ui 保存的是面板数据,真正运行的是它生成的 Xray 配置。需要确认 realitySettings 中的目标、serverNames 和密钥来自同一套配置,例如:

{
  "realitySettings": {
    "target": "example.com:443",
    "serverNames": ["example.com"],
    "privateKey": "<redacted>",
    "shortIds": ["<redacted>"]
  }
}

客户端的 SNI 必须落在 serverNames 中,服务端和客户端的公钥、短 ID 也必须来自同一个入站。确认这些字段没有被订阅缓存或旧配置覆盖后,再看目标站点本身。

2. 目标站点的证书链也可能让 Reality 失效

我用 Xray 自带的 TLS 探测检查目标站点:

xray tls ping example.com:443

原配置的目标站点证书链包含约 8273 条记录,超过 Reality 当前实现可处理的 8192 限制。结果不是“证书不受信任”,而是 Reality 在解析握手材料时无法完成协商,客户端通常只看到 EOF、连接重置或握手超时。

这个问题很容易误判,因为服务器没有改配置,目标网站却可能因为 CDN、证书轮换或新增中间证书而突然变得不可用。Xray 项目的 #6356 问题记录 也记录了同类的证书链过长现象;Reality 的字段含义和目标选择可以对照 官方配置文档。

3. 用 A/B 测试确认,而不是凭感觉换配置

为了排除客户端软件、密钥和网络路径,我复制运行配置到临时文件,只改变 Reality 的目标站点:

cp /path/to/config.json /tmp/xray-check.json
xray run -c /tmp/xray-check.json

原目标依旧在握手阶段失败;换成另一台证书链较短、支持 TLS 1.3 的稳定站点后,服务端日志出现 uConn.Verified: true,再通过本地 SOCKS 代理发起请求也能得到服务器出口地址。这说明端口、防火墙、Reality 密钥和客户端链路都没有问题,故障点就是目标站点的握手材料。

修复时不要把某个域名当作永久答案。应该先用 xray tls ping 检查候选目标,再确认目标的 443 服务稳定、证书链可解析,并让 target 与 serverNames 保持一致。本文这次验证通过的候选目标只是一次 A/B 结果,后续仍应定期复测。

第三步:定位 Hysteria2 的证书问题

Hysteria2 的服务端配置指向了一张本地自签名证书,证书的 CN/SAN 是某个公共域名;订阅导出的 SNI 也使用了这个名字,但客户端没有 insecure 或证书 pin。于是会出现这样的链路:

  1. UDP 端口可达,说明网络层没有完全阻断;
  2. QUIC 能收到握手,但 TLS 证书链不受信任;
  3. 严格校验的客户端拒绝连接,表现为“节点不可用”。

临时测试可以在客户端显式关闭校验,但生产配置不应该依赖自签名证书。更稳妥的做法是使用可信 CA 签发的证书,并确保证书 SAN 覆盖订阅里的 SNI:

{
  "tlsSettings": {
    "serverName": "your-domain.example",
    "certificates": [
      {
        "certificateFile": "/path/to/fullchain.pem",
        "keyFile": "/path/to/privkey.pem"
      }
    ]
  }
}

3x-ui 不同版本对 Hysteria2 字段的外层结构可能略有差异,上面的片段只强调证书、SNI 和完整链之间的关系;实际修改应以面板生成的配置为准,不要整段照抄覆盖其他字段。

如果暂时只能使用 IP 访问,就申请包含该 IP 的证书,并把 SNI、证书 SAN 和服务端 serverName 统一成这个 IP;同时确认 ACME 续期任务正常。域名证书通常更容易迁移,也更适合长期维护。

修复时的安全流程

1. 先备份,再停服务

直接修改 3x-ui 数据库或生成配置前,先做可恢复备份:

backup_dir="/root/x-ui-backup-$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$backup_dir"
cp -a /etc/x-ui/x-ui.db* "$backup_dir/"
systemctl stop x-ui

如果使用面板修改,备份仍然有价值;如果确实需要改 SQLite,务必在停止服务后做事务更新,不要一边让 x-ui 写 WAL 一边手工改库。

2. 修改两处协议配置

  • Reality:换成经过 TLS 探测的候选目标,target 和 serverNames 同步修改,保留原有私钥、短 ID 和客户端公钥关系。
  • Hysteria2:把自签名证书替换为可信证书,证书文件使用完整链(fullchain),私钥权限保持最小化,serverName 与证书 SAN、订阅 SNI 一致。

3. 重启并检查生成结果

systemctl start x-ui
systemctl is-active x-ui
ss -lntup | grep -E '你的 TCP 端口|你的 UDP 端口'
journalctl -u x-ui -n 100 --no-pager

不要只看到 active 就结束。还要检查生成后的 Xray 配置,确认旧目标、旧证书路径和旧 SNI 没有残留。

4. 重新获取订阅并做真实路径验证

修改入站后,客户端里的旧订阅仍可能缓存旧配置。重新获取订阅,确认以下字段:

  • VLESS 的地址、端口、UUID、公钥、短 ID 和 SNI;
  • Hysteria2 的地址、端口、密码、SNI 和证书校验模式;
  • 客户端没有继续使用旧的订阅快照或旧节点。

最后分别通过实际客户端访问一个简单的公网地址。服务端回环测试只能证明服务能工作,不能替代手机、桌面端或旁路由上的真实链路测试。

这次故障留下的检查清单

层级 要回答的问题 常用证据
进程 x-ui/Xray 是否运行? systemctl、journalctl
监听 TCP/UDP 端口是否正确打开? ss -lntup
网络 云防火墙和主机防火墙是否放行对应协议? 安全组、iptables/nftables
协议 是 TCP/QUIC 到不了,还是握手失败? Xray/Hysteria 日志
TLS SNI、SAN、证书链是否一致且受信? xray tls ping、证书检查
配置 面板和生成配置是否一致? 生成后的 JSON
客户端 是否已经拉到新订阅? 导出的节点字段、真实访问

最后总结

这次排查最重要的经验,是把“节点不能用”拆成可观察的层:端口监听不等于协议握手成功,证书能加载也不等于客户端会信任,面板显示正常更不等于订阅已经刷新。

Reality 的目标站点是外部依赖,目标证书链变化可能在没有改服务器配置的情况下造成故障;Hysteria2 则必须把证书链、SNI 和客户端校验策略当成一个整体维护。以后遇到类似问题,先保留证据,再一次只改变一个变量做 A/B 测试,通常比反复重装面板更快找到根因。

另外,任何公开文章、工单或截图都不要包含 root 密码、私钥、UUID、订阅链接和完整配置。若凭据曾经出现在聊天记录或截图中,排障完成后应立即轮换密码并重新生成相关密钥。

参考: