最开始,我以为是 Xray 的 Bug
最近在家里折腾软路由,我遇到了一个不好解决的问题。
这套系统底层是 Proxmox VE(PVE),上面跑着 OpenWrt 虚拟机;代理服务器放在 VPS 上,由 Xray-core 处理,入站用的是 VLESS + REALITY + TCP/RAW。配置本身挺常见,用起来却有点奇怪:部分客户端连上代理服务器后,TCP 连接明明已经建立,很快又被重置,而且换个网络环境,问题还不一定能复现。
我最先怀疑的自然是 Xray 或 REALITY。毕竟同一个节点,Clash、Shadowrocket、v2rayN 的表现不一样,在代理客户端里也不算罕见。协议版本、TLS 指纹、传输实现,都有可能影响连接。
这次最后靠把 H3C 的原厂固件刷成 OpenWrt 解决了使用问题。没想到这么少见的bug也能让我碰上,之前还一直盯着代理查。
不过,排查过程中翻到的那些资料,让我开始对 Xray 和 sing-box 感兴趣了。
从 REALITY 兼容性,翻到几年的开源争论
除了这次软路由故障,我之前升级 Xray 时,还遇到过另一种情况:相同的 VLESS + REALITY 节点,mihomo / Clash 能连,iOS 上的 Shadowrocket 却不能正常用。我试过 Chrome 120、Chrome 140 等 TLS 指纹,也没能马上解决。
软路由那次查到的是网络转发路径异常,升级后不同客户端的表现有差异,则更像是服务端与客户端的 REALITY 握手兼容性问题。后来翻 GitHub,我发现 2026 年 7 月到 9 月,Xray 社区刚好有过一轮相关争论。
服务端升级了,客户端为什么反而连不上?
争议涉及 TLS ClientHello 里的 X25519MLKEM768。这是 TLS 1.3 可以使用的一种混合密钥交换机制,把传统的椭圆曲线密钥交换与后量子密钥封装机制结合起来。Chrome 等浏览器逐渐采用新的密钥交换方式,模仿 Chrome 的 TLS 客户端,也得跟着更新握手特征。
麻烦在于,各种 REALITY 实现并没有同时更新。部分第三方客户端为了兼容还不支持相关机制的服务端,会调整或移除 ClientHello 中的某些内容。但这样改完以后,发出去的握手就可能和它声称模仿的真实浏览器不一样了。
Xray 在 2026 年的版本更新中加强了这方面的约束,尤其从 26.9.8 开始,服务端对相关 ClientHello 特征做了更直接的检查。结果就是,有些第三方客户端原来能连,服务端升级后却连不上了。
Xray 维护者 RPRX 更在意握手是否符合当前的安全设计:长期保留过时或异常的浏览器指纹,会削弱抗识别能力,客户端和服务端应该一起升级。Exclave 维护者 dyhkwong 则认为,REALITY 对特定 TLS 密钥交换结构依赖较强,升级会带来兼容性成本,服务端直接拒绝部分第三方客户端,也不是理想的互操作方式。
读下来,我觉得双方各有关注点。RPRX 强调当前握手的安全约束,dyhkwong 更关心协议怎么演进、客户端能有多少自主权,以及升级成本最后由谁承担。这些问题值得单独讨论,不能只看谁的措辞更激烈。
相关讨论见 Xray-core #6477 和 Exclave #480。
2023 年,已经有人在争论协议设计
继续往前翻,才发现分歧早就有了。Xray 的重要维护者 RPRX 和 sing-box 作者 nekohasekai,在这些协议的设计上一直有不同看法。
2023 年 9 月,nekohasekai 在个人博客发表《简述 XTLS 相关协议》,集中批评了 VLESS、XTLS Vision、REALITY 等设计。我比较在意其中几个具体问题。
一个是 VLESS 的协议格式。他质疑在二进制协议中用 Protobuf 表示部分扩展字段,认为这让结构变得复杂,也讨论了地址编码和 UDP 的处理方式。这些批评里有值得看的技术内容,不能因为语气冲就一概忽略。但协议该精简到什么程度,还得考虑实现难度、兼容性、扩展性和维护成本。某个字段用了字符串或 Protobuf,本身还不足以判断整个协议好坏。
文章里还有一处更正:作者最初认为,Xray 读取 UUID 时的 ReadFull 行为可能暴露主动探测特征,后来划掉并更正了这段批评。至少在这个问题上,他最初的判断并不成立。熟悉底层实现,也可能因为没有完整跟过调用路径而看错。
另一个是 XTLS Vision。nekohasekai 质疑它的复杂度,以及头部填充对反审查到底有多大帮助,还引用了尚未公开发表的检测研究。不过,他也明确承认,研究没有覆盖现实中的 GFW 行为,也没有足够证据表明真实审查系统已经大规模采用对应的机器学习检测方法。研究模型能识别某种流量,和真实防火墙正在用这种方法,得分开说。
还有 REALITY 与 ShadowTLS 的时间关系。ShadowTLS V3 的相关设计在 2023 年 2 月出现,REALITY 则在当年 3 月进入公开预发布版本。这个先后顺序可以用来追溯技术演进,但单凭日期不能认定抄袭。要判断两种设计有什么关系,还得比较代码来源、核心机制、公开设计文档和提交历史。
原文见 nekohasekai《简述 XTLS 相关协议》。
2025 年,争论变成了公开抵制
2025 年 5 月 22 日,开发者 doayapp 在 Xray-core 的 GitHub Discussions 发了《呼吁停止使用 Sing-box》。一项直接导火索,是 sing-box 官方文档对部分第三方客户端的批评:文档认为,一些借 sing-box 名义吸引用户的客户端存在代码质量和广告问题。
我能理解核心维护者的顾虑,开源核心毕竟没法替所有第三方图形客户端担保。可如果没有指出具体项目、代码和可复现的问题,直接评价其他开发者的动机或代码质量,也很容易吵起来。
后面的讨论越来越远,从项目商业化、社区理念,谈到是否尊重前人的成果,甚至猜测将来可能发生的不当行为。这部分在我看来,已经很难当作可以验证的工程问题来讨论了。
还有一点容易在转述时弄错:#4753 是 doayapp 发起的讨论,不能算成整个 Xray 项目的官方抵制决定。RPRX 在评论里也说,并不十分赞同发表这样的文章,不过仍然批评了 sing-box 作者的部分言论。他还担心过,如果代理生态只剩 Xray 一个重要项目,未必是好事。
讨论原文见 Xray-core Discussion #4753。
争议也发生在代理核心和管理面板之间
Xray 与 3x-ui 之间也有过类似冲突。2025 年 2 月,RPRX 在 net4people #448 中批评某些代理管理面板允许通过公网明文 HTTP 访问。
如果这样登录后台,密码、代理配置和私钥就可能在传输途中被旁路观察者截获。这个风险很具体,但不能因此说 VLESS 协议本身在泄露明文。底层加密做得再好,管理工具把认证信息暴露出去,整套系统一样可能出问题。相关讨论见 net4people #448。
看了这些争论,我觉得 Xray 和 sing-box 的开发者都有技术实力,也都指出过真实或值得讨论的问题。只是讨论着讨论着,对某个设计的批评就容易变成对整个项目、作者能力甚至动机的否定。
我作为用户,没必要跟着选阵营。相比谁说服了谁,我更想知道这些设计在实际审查环境里能起多大作用,于是又去看了伊朗的网络测量报告。
伊朗的封锁报告
谈到 REALITY、uTLS、NaiveProxy,经常能看到一些说得很满的话:“REALITY 可以防止主动探测。”“使用 Chromium 网络栈就无法被指纹识别。”“伊朗已经识别并封锁了 uTLS。”
TCP 连上了,TLS 仍然可能被拦
OONI 长期研究包括伊朗在内的多个国家的网络干预。2022 年伊朗大规模封锁网络时,它观察到了 DNS 查询异常、TCP/IP 连接失败,以及 TLS 握手被阻断的情况。
网络干预可以发生在不同位置。直接封目标 IP 是一种做法;查看 ClientHello 里的 SNI,按域名决定是否放行,是另一种。握手参数、连接行为、包长和时序,也都可能用来给流量分类。
2025 年 6 月,伊朗再次出现针对 WhatsApp 的访问干预。OONI 发现,在部分运营商网络中,TCP 可以建立连接,TLS 握手却在 ClientHello 之后超时。这符合 TLS 层面受到干预的表现,也提示可能存在 SNI 过滤。
这项测量说明,连接可以在 TCP 建立之后、应用通信开始之前被拦下来。但它并没有证明某一种代理协议被准确识别。具体结果见 OONI 的 WhatsApp 测量报告。
REALITY 节点连不上,不一定是协议被识别了
2023 年 12 月,Xray-core 的 Issue #2778 里有用户发布了伊朗 REALITY 节点被封锁的测试报告。报告描述了新建 VPS 和 REALITY 节点在使用一段时间后遭遇封锁的现象,并怀疑审查系统在分析流量行为。但作者也承认,没法百分之百确认具体机制。
假设我新开了一台 VPS,部署 REALITY,三天后连不上了,可能的原因至少有这些:
- VPS 的 IP 或整个网段被封了。
- TLS 握手有可识别特征。
- 长时间的流量行为或连接模式触发了检测。
- 服务端、客户端或中间网络出了故障。
只有“连不上”这个结果,还不能直接选定第二项。同样,有开发者提到“伊朗用户报告使用 uTLS 的 Go 代理被封锁”,也不等于伊朗已经证明能识别所有 uTLS 指纹。
测试细节见 Xray-core #2778。
国际连接都断了,协议也无能为力
2026 年 2 月 28 日,Cloudflare Radar 观察到伊朗新一轮全国性互联网中断,监测到的流量一度降至此前的 1% 以下。数据来自 Cloudflare 2026 年第一季度互联网中断报告。
以前我容易把抗审查想成协议和检测算法之间的较量,但审查方也可以直接采用更粗的办法。国际连接受到大规模限制时,REALITY 的认证再巧妙,NaiveProxy 再接近 Chrome,也没法凭空变出一条网络路径。
sing-box 的网络架构和协议伪装
看资料的过程中,我一度这样理解两者的区别:Xray 更倾向于修改 TLS、REALITY 等靠近应用层的协议特征,sing-box 则往 L3 网络层走,再借助 NaiveProxy 和 ECH,让代理流量接近正常互联网流量。
这个理解碰到了一些实际的技术方向,却把不同层次的事情放到了一起。
先说 OSI 七层模型。L2 是数据链路层,比如以太网;L3 是网络层,比如 IP 路由;L4 是传输层,比如 TCP、UDP。TLS 通常在传输层之上,为应用协议提供服务,不能简单算成 L2。所以,“sing-box 是 L3,REALITY 是 L2”这个说法不准确。
sing-box 怎样接管、处理网络流量,和代理连接怎样伪装,应该分别看。
TUN 和 Endpoint:流量怎么进来,又怎么出去
早期代理客户端通常通过 SOCKS 或 HTTP 代理接口接收应用请求,需要应用主动支持代理,或者使用操作系统的系统代理设置。TUN 模式则从虚拟网络接口接收 IP 数据包,再决定怎么处理其中的 TCP、UDP 等流量。
两种路径可以简化成这样:
传统应用代理
浏览器 / 应用
│
▼
SOCKS / HTTP 代理
│
▼
代理核心
│
▼
远程服务器
TUN / L3 透明代理
浏览器、应用、系统流量
│
▼
操作系统 IP 路由
│
▼
TUN 虚拟网络接口
│
▼
TCP/IP Stack
│
▼
DNS / 规则 / 路由决策
│
├── 直接访问
├── REALITY
├── NaiveProxy
└── WireGuard / 其他协议
sing-box 在这方面做了不少工作。sing-tun 支持透明代理、自动路由和网络栈处理,后来又引入了 Endpoint 抽象。从 sing-box 1.11 开始,WireGuard 等组件可以通过 Endpoint 同时接收和发送流量;之后还加入了 Tailscale、OpenVPN、OpenConnect、MASQUE 等 Endpoint 类型。
2026 年 9 月,作者又介绍了为 sing-tun 重新实现的 TCP/IP Stack,重点是减少包处理开销、降低内存占用、提高转发性能。看着这些功能,可以把 sing-box 理解为一个逐渐完善的跨平台网络流量处理框架,而不只是一个代理客户端。
不过,处理 L3 流量并非 sing-box 独有,Xray 也可以配合透明代理、路由和系统网络功能使用,只是架构和具体能力不同。接管了 IP 数据包,也不代表发往 VPS 的流量就更难识别。TUN 决定接管和转发哪些流量,最终选用的出站协议,才决定这些流量怎样在互联网上传输。
相关说明见 sing-box TUN 配置、Endpoint 架构和 sing-tun 自有 TCP/IP Stack 介绍。
REALITY
REALITY 主要处理 TLS 握手和服务端认证。它用经过修改的 TLS 实现,把认证机制放进真实 TLS 握手中,和给普通代理套一层 HTTPS、随意改几个 TLS 字段都不一样。
连接没有通过认证时,服务端可以把流量转发到预设的真实 TLS 目标,让主动探测者不容易直接看到代理服务的特征。对自建用户来说,方便之处在于:有一台 VPS 就可以部署,不一定要有自己的域名和公网可信 TLS 证书。
但它依然依赖具体的握手实现、认证机制和客户端行为,VPS 的公网 IP 也没有因此隐藏起来。在审查比较敏感的网络里,目标 SNI、目标 IP、握手行为,以及后续流量能不能彼此对应,仍然值得继续研究。
设计和配置见 XTLS/REALITY 官方说明。
NaiveProxy
klzgrad 从 2018 年开始发展 NaiveProxy,核心思路是复用 Chromium 的网络栈。
浏览器的网络特征不只体现在 ClientHello 的加密套件列表里,还包括 TLS 扩展、HTTP/2 行为、请求顺序、连接复用方式等。uTLS 可以模仿某些浏览器的 TLS 握手,但握手像了,后面的 HTTP 行为不一定也一样。
NaiveProxy 复用了更多 Chromium 的实现,通过 HTTP/2 或 HTTP/3 CONNECT 承载代理流量,再用连接复用、填充等机制减少部分统计特征。它也考虑了主动探测:可以借助 Caddy、HAProxy 等前置服务器,按认证信息做应用层路由,让未授权访问表现为普通网站服务。
因此,不能把两者简单分成“REALITY 防主动探测,NaiveProxy 做被动伪装”。它们都考虑了主动和被动识别,只是做法不同。具体设计见 NaiveProxy 官方 README。
ECH
ECH,也就是 Encrypted ClientHello,是 TLS 的一种标准化扩展。传统 TLS 1.3 已经加密了不少握手内容,但 ClientHello 里的 SNI 通常还是明文。ECH 把 ClientHello 分成外层和加密内层:实际访问的域名等敏感信息放在内层,外层保留建立连接需要的公开信息。
放在共享基础设施里,这种做法很有用。例如,一个 CDN 上的大量网站共用基础设施,外部观察者可能只看得出用户连到了某个 CDN 地址和公开名称,没法直接读取内层 SNI 来判断具体访问了哪个网站。
但 ECH 不会自动建出这样的共享环境,也不隐藏服务器 IP。我在独立 VPS 上部署 NaiveProxy + ECH,即使 ECH 握手成功,也不等于这台 VPS 突然拥有了 Cloudflare 那样大量正常网站访问作为背景。
外层 SNI、目标 IP、真实 TLS 行为和所处网络仍然要相互匹配。如果一个地址没多少正常 HTTPS 访问,能与代理通信混在一起的正常流量可能仍然有限。ECH 提供握手信息的隐私保护,大规模流量混合则要靠实际部署环境。
相关资料见 RFC 9849、Cloudflare 的 ECH 原理介绍和 sing-box TLS 与 ECH 配置。
Xray 和 sing-box
到这里,我才意识到,最初那个“哪个更好”的问题里,装了好几种比较。
Xray 和 sing-box 的比较涉及软件架构;REALITY 和 NaiveProxy 的比较,主要是网络伪装与认证机制;独立 VPS 和大型 CDN 的区别,则在网络基础设施,以及流量能混入多大的正常通信集合。把这些放在一起比,很容易答非所问。
现在我会用这张表区分它们:
| 技术 | 主要解决的问题 | 不能直接解决的问题 |
|---|---|---|
| sing-box TUN / Endpoint | 接管、处理、路由网络流量 | 让流量天然不可识别 |
| REALITY | TLS 握手伪装、服务端认证与抗主动探测 | 隐藏全部流量统计特征或服务器 IP |
| NaiveProxy | 减少与真实 Chromium 网络行为之间的差异 | 消除所有代理流量特征 |
| ECH | 加密内层 ClientHello,隐藏部分握手信息 | 隐藏目标 IP 与连接行为 |
| 大规模共享基础设施 | 扩大正常通信的流量集合 | 保证所有连接无法被分类 |
REALITY 更侧重构造具有真实 TLS 特征的认证连接,降低服务端在主动探测中被确认的风险;NaiveProxy 更侧重复用真实浏览器的网络实现,让代理通信在更多可观察的方面接近正常 HTTPS。这是设计重点的区别,两条路线也并不互斥。
2026 年的 sing-box 已经具备 L3 透明代理和 Endpoint 能力,集成了 NaiveProxy 出站,同时也支持 REALITY 等其他协议。选了 sing-box,并不代表一定在用 NaiveProxy,更不会自动获得 ECH 或大型 CDN 的流量匿名集合。Xray 也不是只能选一种 TLS 伪装方式。
审查系统如何判断
不解密,也能给连接分类
假设一张网络里有一百万条加密连接,其中一千条是代理流量。审查系统不一定要解密所有内容,也可以寻找一些外部可见的特征:罕见的 TLS 握手组合、特殊的包长分布、不符合常规行为的长期连接、目标 IP 与握手信息对不上的地方,或者主动探测时的特定响应。
某种特征只要能提高“这是一条代理连接”的判断概率,就有检测价值。但特征也可能误导:如果大量真实 Chrome 用户表现出同样的特征,一起拦掉,就会误伤正常访问。
所以,审查方也要考虑检测成本、识别准确度、阻断收益和误封代价。看见异常之后要不要拦,并不是同一个问题。
混入正常流量,为什么有时有效,有时没用?
把检测看成分类,会出现四种结果:
| 实际正常流量 | 实际代理流量 | |
|---|---|---|
| 允许 | 正确放行 | 漏检 |
| 阻断 | 误封 | 正确阻断 |
漏检和误封的代价,对审查方来说未必一样。如果它很在意正常业务被误伤,把代理流量混在大量正常流量里,就能增加精准识别的难度,也让阻断更难下手。可如果它愿意承担大面积误封,甚至直接切断国际网络,伪装再像,能起的作用也有限。
“融入正常流量”因此没有绝对保证,效果还取决于审查方想达到什么目的,又愿意付出多少代价。
不同设计
REALITY 用握手认证和未授权连接处理,让主动探测者更难直接确认代理服务。NaiveProxy 复用 Chromium 网络栈,减少代理通信与普通浏览器通信之间可观察的差异。ECH 加密内层 ClientHello,让一部分原本可以直接读取的信息不再以明文出现。
共享 CDN 等基础设施还可能扩大正常流量集合,让封 IP 或依赖某些粗粒度特征的做法带来更多误封。这些办法影响的是不同的检测条件,不能只排成一列,比较谁更隐蔽。审查规则变了,各种设计能发挥多大作用,也会跟着变。
后续尝试 sing-box
目前我还不准备直接迁移现有的 Xray 环境。它能满足我的使用需求,之前软路由的故障也已经排除。我打算让现有环境继续提供稳定服务,另开一个测试环境部署 sing-box,两边并行观察。
先从 sing-box 的网络架构看起。我想弄清 TUN、TCP/IP Stack、Endpoint 是怎么配合的,它们和 Linux 路由、NAT、DNS 又有什么关系。这些都用得上我的 OpenWrt、PVE 和家庭网络。最后即使不迁移,花时间学明白也有用。
接下来再比较出站协议。我想分别观察 Xray REALITY、sing-box REALITY、NaiveProxy 的握手、连接行为、性能和资源开销,尤其要分清实现差异和协议差异。同一个协议在不同核心里表现不同,应该先核对实现版本、配置、依赖和兼容性,再判断究竟哪里出了问题,不能马上归结为协议不安全。
之后再研究 ECH 和共享基础设施怎么部署:什么条件下能形成较大的流量匿名集合?还有哪些信息会暴露在网络上?换成真实 Chromium 网络栈,能观察到什么改善?这些都得做受控测量。在此之前,“指纹更像浏览器”还不能直接写成“抗封锁能力更强”。
我也不打算继续找一个能永久用下去的最强协议。浏览器升级、服务端协议变更、客户端兼容性和网络策略调整,都可能让现在好用的方案将来失效。相比押在某个协议上,我更希望自己能看懂系统,出了问题也知道怎么观察、定位和修复。
最后
回头看,起点只是一次软路由故障。我先怀疑代理客户端,抓包后才把注意力转到路由器的转发模式和公网连接状态。另一次 REALITY 兼容性问题,又让我翻起 Xray 和 sing-box 的 GitHub 讨论,接着看了 NaiveProxy、uTLS、ECH,以及伊朗网络审查的测量报告。
原来我想要的答案很简单:哪个代理核心更好? 回头看,要回答这个问题,至少得说清具体环境。软件架构影响流量怎样被处理,协议机制影响通信会露出哪些特征,部署环境决定这些特征周围有多少正常流量,审查策略又决定哪些特征会被利用。不能线性思维比个优劣,要系统性思维来权衡了。
主要参考资料
协议与实现
- XTLS/REALITY:官方实现与设计说明
- NaiveProxy:Chromium 网络栈与流量伪装机制
- sing-box:TUN 配置及 TCP/IP Stack
- sing-box:Endpoint 架构
- RFC 9849:TLS Encrypted Client Hello
- nekohasekai:三年后的 sing-box
开源争议与版本兼容性
- nekohasekai:简述 XTLS 相关协议,2023
- Xray-core #4753:呼吁停止使用 Sing-box,2025
- Xray-core #6477:REALITY 兼容性问题,2026
- Exclave #480:对 REALITY 兼容性变更的回应
- net4people #448:3x-ui 等 Web 面板的明文安全问题