TL;DR:Trojan TLS 证书域名要和客户端 SNI 对上。握手失败时,先看证书 SAN、SNI、ALPN、客户端时间和 CA store;不要一上来改端口、改密码、换客户端。
Trojan 的排障容易走偏。日志里写 TLS handshake failed,很多人会去查订阅、端口或密码。实际 TLS 还没通过时,Trojan 应用层配置可能根本没有进入有效判断。先把证书链路查干净,后面的排查才有意义。
五项对照表
| 项目 | 正常状态 | 异常表现 |
|---|---|---|
| 证书 SAN | 包含客户端 SNI | hostname mismatch |
| SNI / server name | 填域名,不带协议 | 写成 IP、URL 或旧域名 |
| ALPN | 与服务端支持一致 | h2/http1 写法不匹配 |
| 客户端时间 | 与真实时间接近 | 证书未生效或已过期 |
| CA store | 信任签发链 | unknown authority |
先查这张表,比反复导入节点更快。
证书域名看 SAN,不只看 Common Name
现在证书校验主要看 Subject Alternative Name。你在客户端里写的 SNI,必须出现在证书 SAN 列表里。证书 Common Name 看起来对,不代表校验一定通过。
可以在本机用 OpenSSL 看:
openssl s_client -connect example.com:443 -servername example.com -alpn h2 </dev/null
重点看三处:
- 证书链是否完整。
- SAN 里是否包含
example.com。 - ALPN 协商结果是否符合预期。
如果把 -servername 换成客户端实际填写的值后失败,就说明问题在名称或证书,不是 Trojan 密码。
SNI 字段别写成 URL
不同客户端字段名不同:
| 客户端/核心 | 常见字段 |
|---|---|
| Mihomo/Clash | sni |
| sing-box | tls.server_name |
| Xray | serverName |
| v2rayN/NekoBox | SNI 或 server name |
无论字段名是什么,值都应是域名本身,例如 example.com。不要写 https://example.com,不要带路径,也不要随手填服务器 IP。若服务端证书签给 www.example.com,客户端却写根域,也可能失败。
ALPN 不一致会造成误判
Trojan 常见 ALPN 是 h2、http/1.1 或两者组合。服务端、反向代理和客户端写法不一致时,可能表现为能连上 TLS 但应用层很快断开。
排障时先用最常见组合,不要把 ALPN 当成性能开关随意改。若服务端前面还有 Nginx、Caddy 或其他 TLS 入口,要确认真正处理 TLS 的那一层支持对应 ALPN。
使用兼容 Clash / Singbox / V2Ray 的订阅时,也要看导出的 Trojan 字段是否保留了 SNI 和 ALPN。有些转换会丢字段,桌面端正常、移动端失败就常出在这里。
客户端时间和 CA store
证书有效期依赖本机时间。路由器、旧手机、虚拟机如果时间漂移,会把正常证书判断成未生效或过期。先同步时间,再继续查。
CA store 也会有差异。桌面系统信任的新根证书,某些旧 Android、精简 Linux 或容器镜像不一定有。表现通常是:同一 Trojan 配置在一台设备正常,另一台报 unknown certificate authority。这时要更新系统 CA 包,而不是关闭证书验证长期使用。
只把跳过验证当测试
skip-cert-verify 或类似开关能帮助判断问题是否在证书校验,但不要作为最终修复。如果关闭验证后连接恢复,说明证书域名、链路或 CA store 有问题。把开关再关回去,修证书本身。
最小排查顺序
- 用 OpenSSL 带
-servername检查证书。 - 核对客户端 SNI 是否在 SAN 里。
- 检查 ALPN 是否和服务端入口一致。
- 同步客户端时间。
- 更新系统 CA store。
- 最后再看密码、端口、传输层和规则。
按这个顺序排,能把「TLS 名称问题」和「Trojan 配置问题」分开。否则每改一次订阅都像在碰运气。