本文把 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 开销。
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。
- 收益:满速下载时省掉一次对称加密与解密,CPU 占用下降,软路由与低功耗设备上最明显;
- 收益:大流量场景下吞吐更接近裸 TCP,首包直通后延迟抖动更小;
- 代价:只对 TLS 流量生效,明文 HTTP 仍走常规加密;
- 代价:必须两端都填 flow,且客户端内核需要支持 Vision;
- 代价:与 REALITY 一样只能走 RAW 传输,不能叠加 WebSocket 与 gRPC。
配置要点:密钥、flow 与回落校验
生成密钥对
服务端执行 xray x25519,得到私钥与公钥;私钥只留在服务端配置里,公钥随节点信息下发给客户端。
填写入站配置
inbound 用 VLESS + TCP 监听 443,streamSettings.security 设为 reality,填入 dest、serverNames、shortIds 与 privateKey。
客户端填公钥
v2rayN 节点编辑里填地址、端口 443、UUID,flow 选 xtls-rprx-vision,再填 publicKey、serverName、shortId。
校验回落行为
用浏览器直接访问该域名与端口,应看到 dest 站点的页面;若提示证书错误,说明 dest 与 serverNames 不一致。
查看核心日志
连接失败时看日志里 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,差距不在延迟,而在证书来源与探测特征。