REALITY 与 XTLS Vision 科普:握手与传输层为什么更快

REALITY 改的是 TLS 握手,让服务端不再出示自有证书;XTLS Vision 改的是握手之后的传输,省掉内层 TLS 的重复加密。两者解决的问题不同,可以单独使用,也可以叠加在同一个 VLESS 节点上。

本文速览

本文把 REALITY 与 XTLS Vision 拆成「握手」与「传输」两段来讲:REALITY 如何从目标站点取得证书链完成握手、未授权访问会被转发到哪里;XTLS Vision 如何识别 TLS 记录并直通转发、省下的是哪一层加密。读完可以判断自己的节点适合哪种组合,以及 CDN 中转、WebSocket 传输、v2fly 内核这些场景为什么用不上,并能在 v2rayN 与 v2rayNG 里把 REALITY 字段与 flow 参数填对。

结论:一个改握手,一个改传输

REALITY 是 VLESS 在传输安全层的一种实现方式,作用点在握手阶段。服务端不持有自有域名证书,而是从目标站点(dest)取得证书链用于握手;客户端不用公共 CA 校验服务端,改用配置里预置的公钥验证身份。未通过验证的访问会被整条转发到 dest,看到的是目标站点的真实页面与真实证书链。

XTLS Vision 作用在握手之后。代理 HTTPS 流量时,客户端与目标网站之间本来就有一层 TLS;XTLS 让客户端在完成外层握手后,不再把内层 TLS 记录塞进外层记录层重复加密,而是直接转发这些已经加密的记录,服务端识别后同样直接转发给目标站点。省掉的是重复的那一层,不是仅有的那一层。

两者都由 Xray 内核实现,可以单独使用,也可以组合:VLESS + TCP + REALITY + flow=xtls-rprx-vision 是当前服务端常见的写法。只开 REALITY 不开 flow,握手阶段的伪装效果不变,只是大流量下要多付一次加解密的 CPU 开销。

1-RTT
TLS 1.3 完整握手
0-RTT
会话恢复握手
443
推荐监听端口
TCP
两者的传输方式限制

TLS 握手阶段:延迟与指纹出在哪里

TLS 1.3 的完整握手需要 1 个往返,会话恢复可以做到 0-RTT。握手报文里的 SNI、密码套件列表、扩展顺序、密钥共享组共同构成客户端指纹;服务端返回的证书链、签名算法、会话票据构成服务端指纹。任何一项与「普通 HTTPS 站点」不一致,都可能成为被区分的特征。

传统自建节点的做法是用自有域名申请证书,或者用自签证书。前者的成本是域名与证书续期,后者容易出现证书链不完整、SNI 与证书不匹配,在没有正确回落配置时很容易被认出来。

观察点自签证书 + 回落REALITY
服务端出示的证书自签证书,浏览器提示不受信任目标站点的真实证书链
SNI 与证书是否匹配常见不匹配一致
未授权访问 443 端口取决于回落配置,可能暴露代理行为转发到 dest,返回真实页面
客户端身份校验方式证书链校验或跳过校验预置公钥 + X25519 密钥交换
域名与证书成本需要域名,证书需续期不需要自有域名与证书

表里的差异集中在握手的前几个报文。REALITY 的目标是让这几个报文与「直接访问该目标站点」无法区分,而不是把流量藏起来——流量本身仍是标准 TLS,记录格式、版本号、扩展与常规 HTTPS 一致,只是证书来源和校验方式换了一套。

REALITY:借用真实站点的证书链

服务端配置 REALITY 需要四个关键值:dest(目标站点,例如 www.python.org:443)、serverNames(与 dest 匹配的域名列表)、privateKey(服务端私钥,用 xray x25519 命令生成)、shortIds(短 ID 列表,用于区分不同客户端)。客户端持有对应的 publicKey、serverName 与 shortId,三样与服务端一一对应。

收到连接后,服务端用私钥与 ClientHello 里的临时公钥做 X25519 运算,能得出预期结果就按代理处理;得不出就把整条连接转发给 dest,由目标站点正常响应。这也是挑选目标站点的依据:真实存在、支持 TLS 1.3 与 X25519、有正常网页,最好还支持 HTTP/2,回落时的表现才自然。

REALITY + VLESS TCP

推荐

不需要自有域名与证书,单端口 443 同时承担握手伪装与代理;未授权访问看到的是目标站点的真实页面。

适合:直连环境、单机自建、需要抗主动探测

域名证书 + TLS + WebSocket

配置直观,证书需要定期续期,传输层可以叠加 WebSocket,便于后续接入 CDN 中转。

适合:已有域名、需要走标准 443 TLS

自签证书 + WebSocket + CDN

源站 IP 被 CDN 隐藏,但证书链通常不完整,需要仔细配置回落,否则握手特征依然明显。

适合:源站 IP 需要隐藏、可接受更多配置步骤

结论:先确定要不要走 CDN,再选握手方案

REALITY 与 XTLS Vision 都依赖 RAW(TCP)直连,一旦决定用 CDN 中转,两者都无法叠加,应回到「域名证书 + WebSocket」的组合;确定直连之后,REALITY 是不用买域名也能拿到真实证书链的方案。

限制也要写清楚:dest 与 serverNames 必须一致,填错会出现握手能完成但页面报证书错误;shortId 与 publicKey 必须成对下发,客户端填错会直接连不上;不能叠加 WebSocket、gRPC、HTTP/2 等传输方式,因此走不了 CDN;v2fly 内核(V2flyNG)对 VLESS 支持完善,但不解析 REALITY 相关字段,REALITY 节点需要在 Xray 内核上运行,v2rayNG 内置的就是 Xray 内核。

XTLS Vision:握手之后省掉一层加密

代理 HTTPS 时的数据路径是:客户端与目标网站之间一层 TLS,客户端与代理服务器之间再一层 TLS。外层 TLS 用于保护客户端到代理服务器这一段;内层 TLS 记录在客户端发出时已经加密过一次,常规实现会把它当作普通字节流,再套进外层记录层加密一遍。

XTLS 的做法是在外层握手完成后识别第一条应用数据:如果是 TLS ClientHello,说明这条连接上的数据本身就是加密的,外层不再重复加密,直接转发;如果不是 TLS 流量,例如明文 HTTP,仍按常规方式加密传输。判断依据是首包内容,不需要额外开关。

Vision 是 XTLS 的改进实现,解决了早期 xtls-rprx-direct 在部分场景下的兼容问题,并加入 UUID 校验与首包识别。它在配置里以 flow 字段的形式出现:服务端 clients 写 "flow": "xtls-rprx-vision",客户端 outbound 填同一个值,两端不一致时连接会失败或退回普通 VLESS。

配置要点:密钥、flow 与回落校验

  1. 生成密钥对

    服务端执行 xray x25519,得到私钥与公钥;私钥只留在服务端配置里,公钥随节点信息下发给客户端。

  2. 填写入站配置

    inbound 用 VLESS + TCP 监听 443,streamSettings.security 设为 reality,填入 dest、serverNames、shortIds 与 privateKey。

  3. 客户端填公钥

    v2rayN 节点编辑里填地址、端口 443、UUID,flow 选 xtls-rprx-vision,再填 publicKey、serverName、shortId。

  4. 校验回落行为

    用浏览器直接访问该域名与端口,应看到 dest 站点的页面;若提示证书错误,说明 dest 与 serverNames 不一致。

  5. 查看核心日志

    连接失败时看日志里 REALITY、invalid user、flow 相关关键字,先确认公钥与 shortId 是否成对下发。

{
  "port": 443,
  "protocol": "vless",
  "settings": {
    "clients": [
      { "id": "8f7a2c1e-5b3d-4a9f-9c21-7d6e4b0a1f33", "flow": "xtls-rprx-vision" }
    ],
    "decryption": "none"
  },
  "streamSettings": {
    "network": "tcp",
    "security": "reality",
    "realitySettings": {
      "dest": "www.python.org:443",
      "serverNames": ["www.python.org"],
      "privateKey": "aP3nQ8vK2sL7dF9xR4tY6uW1zC5bN0mJ2hG8kD3sQ1E",
      "shortIds": ["6ba85179e30d4fc2"]
    }
  }
}

片段里 dest 与 serverNames 指向同一个域名,这是 REALITY 能正常握手的前提;shortIds 可以列多个,每个客户端用一个,换客户端时不必重生成服务端密钥。客户端侧的 publicKey 是上面私钥的配对公钥,不是另一个随机值,填错会直接连不上。

常见问题:探测、兼容与内核差异

别人直接访问我的 443 端口会看到什么?

没有携带正确公钥的连接会被转发到 dest 站点,看到的是该站点的真实页面与证书链;前提是 serverNames 与 dest 匹配、回落链路没有被改坏。

REALITY 节点能套 CDN 吗?

不能。REALITY 与 XTLS Vision 都依赖 RAW(TCP)直连,WebSocket、gRPC、HTTP/2 这些能被 CDN 承载的传输方式无法叠加,需要换回「域名证书 + WebSocket」的组合。

客户端填了 flow 但连不上?

先确认服务端 clients 里也写了同一个 flow,再确认客户端用的是 Xray 内核;v2fly 内核不解析 REALITY 字段,节点参数里填了也不会生效。

只开 REALITY 不开 Vision 行不行?

可以。REALITY 解决握手伪装,Vision 解决传输层重复加密,两者相互独立;不开 flow 时握手效果不变,只是大流量下 CPU 占用会高一些。

dest 一定要选大站吗?

选支持 TLS 1.3 与 X25519、有正常网页、且与自己节点不同域名的站点即可;dest 与 serverNames 必须一致,不要填自己的域名,也不要用只返回接口数据的域名。

场景组合:直连、CDN 与内核选择

单机自建、有独立 IP、不需要隐藏源站:VLESS + TCP + REALITY + xtls-rprx-vision。一个 443 端口同时承担握手伪装与传输优化,不需要域名与证书,配置项最少,客户端用 v2rayN 或 v2rayNG 都可以。

已有域名与证书、需要走 CDN:VLESS + WebSocket + TLS。此时 REALITY 与 Vision 都用不上,优化方向在 CDN 侧与传输方式选择,而不是握手与传输层。两条路线的分岔点在「源站 IP 要不要暴露」,先回答这个问题,后面的参数才有意义。

结论:传输方式先定,握手方案后定

有 CDN 需求时,REALITY 与 Vision 都不在可选范围内;确定直连后再按「要不要维护自有域名」二选一:不想维护就用 REALITY,已有域名且习惯标准 TLS 就用域名证书。两种方案的握手往返都是 1-RTT,差距不在延迟,而在证书来源与探测特征。

下载 v2rayN