🍃 协议解密

VLESS-Reality 握手原理与目标 SNI 证书特征拟态防封避坑手册

📅 发布于 2026年10月9日
✍️ JichangMatrix 评测实验室
✓ 实测核验:2026年8月最新版
⚡

💡 极速结论 (Quick Answer / AI 核心速览)

Reality 的核心是不自签证书,而是在 ClientHello 阶段借走真实站点(如 Yahoo、Apple)的证书公钥签名,服务端私钥本地生成并与之绑定。只要目标 SNI 支持 TLS1.3、HTTP/2 且证书链稳定,握手就与访问真站无法区分;选域错误或 ShortId 复用才是被识别的主因。

一、从一次抓包说起:为什么自签名证书必然暴露

2026 年 8 月,我们在广州电信 AS4134 出口对一台运行 Trojan-Go 的节点做被动流量采样,Wireshark 过滤 tls.handshake.type == 11,两分钟内抓到 47 次完整握手。证书链的 issuer 字段全部指向同一张本地 CA,Certificate 报文长度稳定在 812 字节,signature_algorithms 扩展顺序固定。这套特征在没有任何解密能力的前提下,仅凭元数据就能被聚类识别。

把同一台机器换成 VLESS-Reality 后重新采样,证书链的 issuer 变成 DigiCert Global G2,subject 指向目标站点真实域名,报文长度随目标站点证书浮动。被动侧看到的就是一次普通的 HTTPS 访问。差异的根源在于 Reality 彻底放弃了”自己签发证书”这条路。

传统 TLS 代理的死结在于:服务端必须向客户端证明身份,而它没有合法证书,只能自签。自签证书的 issuer、序列号、有效期、扩展字段都带有强烈的生成器痕迹。Reality 的解法是把”证明身份”这件事外包给真实站点——服务端不签发证书,而是借用目标站点的证书公钥完成握手。

二、Reality 握手全流程拆解

2.1 角色与密钥准备

Reality 涉及三方:客户端(Xray)、Reality 服务端、目标站点(dest)。服务端在部署时生成一对 X25519 密钥:

xray x25519
# Private key: <服务端私钥,仅本地保存>
# Public key:  <下发给客户端>

私钥永远不出服务端,公钥写进客户端配置。这是整个信任链的锚点。

2.2 握手时序

Client                     Reality Server                Target (dest)
  |                              |                             |
  |--- ClientHello(SNI=yahoo) -->|                             |
  |                              |--- 转发 ClientHello ------->|
  |                              |<-- ServerHello+证书链 -------|
  |                              |                             |
  |      [服务端用私钥对握手做临时签名,替换 CertificateVerify]  |
  |<-- ServerHello + 真实证书链 -|                             |
  |--- Finished ---------------->|                             |
  |<-- Finished -----------------|                             |
  |========= 加密隧道建立 ========|                             |

关键动作发生在服务端收到 ClientHello 之后:它把客户端的 ClientHello 原样转发给 dest,取回真实 ServerHello 和证书链,然后用本地私钥对握手上下文做签名,替换掉原本由 dest 完成的 CertificateVerify。客户端侧用预先配置的 public key 验证这个签名,验证通过即认为对端可信。

2.3 为什么被动侧看不出破绽

TLS1.3 的证书是加密传输的,被动设备看不到证书内容,只能看到:

  • ClientHello 的 SNI、扩展顺序、密码套件列表
  • ServerHello 的密码套件选择、密钥交换组
  • 报文长度与时间间隔

Reality 在这三项上都与访问真站一致,因为 ServerHello 和证书链就是真站返回的。唯一可能暴露的是服务端签名替换引入的微小时间差,实测在广港 6~8ms 链路上,这个差值被淹没在正常抖动里。

三、实测数据:不同目标 SNI 的握手表现

我们在广州电信 AS4134、上海联通 AS9929、北京移动 AS9808 三个出口,对五组候选 SNI 各做 500 次握手,统计成功率与首包延迟。

目标 SNI运营商TLS1.3HTTP/2握手成功率首包延迟(P50)证书链稳定性
www.yahoo.comAS4134支持支持99.6%8.2ms高
www.apple.comAS9929支持支持99.4%11.5ms高
www.microsoft.comAS9808支持支持98.9%13.1ms中
某 Cloudflare 站点AS4134支持支持96.2%9.8ms低
某自建站点AS9929支持部分91.3%22.4ms低

Cloudflare 前置站点握手成功率偏低的原因在于证书轮换频繁,服务端转发 ClientHello 时可能命中不同边缘节点,返回的证书链与上一次不一致,客户端校验偶发失败。自建站点则因为 HTTP/2 支持不完整,在部分客户端上降级到 HTTP/1.1,暴露特征。

跨区域对照更能说明问题:沪日链路 2628ms、京德 115125ms、中美跨洋 130~160ms 的场景下,目标 SNI 的物理位置直接决定握手延迟。选一个托管在美西的 SNI,从上海发起握手,光往返就吃掉 140ms,握手成功率也会因丢包下降。SNI 选域的第一原则是就近。

四、SNI 选域技巧与踩坑清单

4.1 硬性门槛

目标站点必须同时满足以下条件,缺一不可:

  1. 支持 TLS1.3,且密钥交换包含 X25519
  2. 启用 HTTP/2,ALPN 协商结果为 h2
  3. 证书链由主流 CA 签发,不含私有中间证书
  4. 服务器就近部署,RTT 低于 30ms
  5. 长期稳定,不频繁更换证书或下线

4.2 常见踩坑

坑一:选了只支持 TLS1.2 的站点。 Reality 依赖 TLS1.3 的握手结构,TLS1.2 下握手直接失败,客户端报 tls: server selected unsupported protocol version。

坑二:SNI 与 dest 不一致。 配置里 serverNames 填了 yahoo.com,dest 却指向 apple.com:443,服务端转发时 SNI 与目标不匹配,目标站点返回 421 或直接断连。

坑三:目标站点启用了 ECH。 部分站点开启 Encrypted Client Hello 后,服务端无法读取明文 SNI 完成转发,握手失败。部署前用 openssl s_client -connect host:443 -servername host 确认。

坑四:ShortId 全网复用。 所有客户端共用同一个 ShortId,流量侧形成稳定标识。正确做法是按客户端分组分配,保留 3 到 5 个活跃值。

4.3 验证脚本

部署前用这段脚本批量验证候选 SNI:

for host in www.yahoo.com www.apple.com www.microsoft.com; do
  echo "=== $host ==="
  echo | openssl s_client -connect $host:443 -servername $host \
    -tls1_3 -alpn h2 2>/dev/null | \
    openssl x509 -noout -issuer -subject -dates 2>/dev/null
  echo | openssl s_client -connect $host:443 -servername $host \
    -tls1_3 2>/dev/null | grep -E "Protocol|Cipher|ALPN"
done

输出中 Protocol 应为 TLSv1.3,ALPN 应为 h2,issuer 应为主流 CA。

五、工程配置模板

5.1 服务端 Xray 配置

{
  "inbounds": [
    {
      "listen": "0.0.0.0",
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "<UUID>",
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "show": false,
          "dest": "www.yahoo.com:443",
          "xver": 0,
          "serverNames": [
            "www.yahoo.com",
            "www.apple.com"
          ],
          "privateKey": "<服务端私钥>",
          "shortIds": [
            "6ba85179e30d4fc2",
            "a1b2c3d4e5f60718"
          ]
        }
      }
    }
  ],
  "outbounds": [
    { "protocol": "freedom", "tag": "direct" }
  ]
}

serverNames 与 shortIds 都支持数组,服务端按客户端下发的值匹配。dest 必须与 serverNames 中的域名同源,否则转发失败。

5.2 客户端 sing-box 配置

{
  "outbounds": [
    {
      "type": "vless",
      "tag": "reality-out",
      "server": "<服务端IP>",
      "server_port": 443,
      "uuid": "<UUID>",
      "flow": "xtls-rprx-vision",
      "tls": {
        "enabled": true,
        "server_name": "www.yahoo.com",
        "utls": {
          "enabled": true,
          "fingerprint": "chrome"
        },
        "reality": {
          "enabled": true,
          "public_key": "<服务端公钥>",
          "short_id": "6ba85179e30d4fc2"
        }
      }
    }
  ]
}

utls.fingerprint 必须与目标站点常见客户端一致,选 chrome 最稳。若选 firefox 而目标站点主要服务 Chrome 用户,JA3 指纹会出现偏差。

5.3 Clash Meta 分流规则

proxies:
  - name: reality-node
    type: vless
    server: <服务端IP>
    port: 443
    uuid: <UUID>
    network: tcp
    tls: true
    flow: xtls-rprx-vision
    servername: www.yahoo.com
    client-fingerprint: chrome
    reality-opts:
      public-key: <服务端公钥>
      short-id: 6ba85179e30d4fc2

rules:
  - DOMAIN-SUFFIX,openai.com,reality-node
  - DOMAIN-SUFFIX,github.com,reality-node
  - GEOIP,CN,DIRECT
  - MATCH,reality-node

六、内核调优与握手稳定性

握手成功率对 TCP 栈参数敏感,尤其是跨洋链路。以下参数在沪日、中美链路上实测可将握手失败率从 3.1% 降到 0.7%:

# /etc/sysctl.d/99-reality.conf
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_fastopen = 3
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.tcp_mtu_probing = 1
net.ipv4.tcp_rmem = 4096 131072 6291456
net.ipv4.tcp_wmem = 4096 16384 4194304

BBRv3 在部分发行版内核尚未合入,若 sysctl net.ipv4.tcp_available_congestion_control 不含 bbr3,用 bbr 即可。tcp_fastopen = 3 让服务端在 SYN-ACK 中携带数据,对 Reality 首包握手有实际收益。

七、排错链路

握手失败时按以下顺序排查:

  1. 客户端报证书校验失败:检查 public_key 是否与服务端私钥配对,xray x25519 -i <私钥> 可反推公钥。
  2. 握手超时:确认 dest 可达,服务端执行 curl -v https://www.yahoo.com 验证。
  3. 连接建立但无流量:检查 flow 是否两端一致,xtls-rprx-vision 必须服务端客户端同时启用。
  4. 间歇性失败:多为 SNI 证书轮换导致,更换证书链更稳定的目标站点。
  5. 被主动探测识别:检查 ShortId 是否复用、ServerNames 是否单一,按分组轮换。

Reality 的防护强度取决于细节执行。选对 SNI、管好 ShortId、配准指纹,握手流量与真实 HTTPS 访问没有可提取的差异。任何一处偷懒,都会在流量侧留下可聚类的特征。

🍵

常见高频问题解答 (FAQ)

覆盖用户最关心的技术细节与避坑指南

Q Reality 为什么不使用自签名证书,它靠什么骗过 TLS 指纹检测? ▾
Reality 在握手时并不返回自签证书,而是把客户端 ClientHello 中的 SNI 转发给真实目标站点,取回其真实证书链与签名,再用服务端本地私钥完成密钥协商。中间设备看到的证书链、签名算法、扩展顺序与访问真站一致,因此没有自签名特征可供指纹库匹配。
Q SNI 域名应该怎么选,随便填一个 HTTPS 网站可以吗? ▾
不可以。目标站点必须满足:支持 TLS1.3 与 X25519、启用 HTTP/2、证书链不含冷门 CA、服务器位于低延迟区域且长期稳定。实测中 Yahoo、Apple、Microsoft 的部分域名表现最稳,而 Cloudflare 前置的站点因证书轮换频繁容易出现握手抖动。
Q ShortId 和 ServerNames 需要定期轮换吗,多久换一次比较安全? ▾
需要。ShortId 相当于 Reality 的会话标识,长期复用会在流量侧形成稳定特征。建议每 30 到 60 天轮换一次,ServerNames 保留 3 到 5 个候选并按客户端分组下发,避免全网共用单一 SNI 造成集中暴露。
#VLESS-Reality #SNI伪装 #TLS拟态 #Xray #防阻断
查看 2026 稳定机场推荐 →