V2ray协议爆发了重大安全漏洞
本文转自DolorHunter 并作补充
服务器端的 V2ray 更新到 v4.23.4 以及之后的版本可以解决这一问题, 请大家尽快更新.
这可能是 V2ray 自 15 年发布 v1.0.0 以来面临的最大危机.
六一前后, 有大量网友反应自己的裸 V2ray 配置(Vmess+TCP 的默认配置)失效了, 我本来也没太当回事, 毕竟过几天就是 535 了, 断一断网是老传统, 并没有什么好说的. 不过有一点与以往不同, 这次被阻断的用户都是使用默认配置.
V2ray 的默认配置是 Vmess+TCP. 虽然中庸普通, 但它并不是一个容易被阻断的配置. 之前被阻断的 V2ray 配置通常都是些 KCP/mKCP 或是 QUIC 这类的基于 UDP 协议的配置. UDP 通信数据特征明显, 因此容易被 GFW 逮个正着. 而 TCP 是可靠协议, 而且目前大量的网络数据也是基于 TCP 协议, 因此 TCP 协议一直都还算安全.
我的认知里Vmess协议有个安全性排名: Vmess+TCP/WS/HTTP2+TLS > Vmess+TCP/WS/HTTP2 > Vmess+KCP/mKCP/QUIC. 如果用白话来解释就是带TLS的配置是最高一档90分优秀, 中间配置60分及格凑合, 最后一档是不及格. 我一直认为, 只要不用 KCP/mKCP/QUIC 爆炸三兄弟, 还是能舒心上网的. 然而我的预判出了大错误.
发现重大安全漏洞
QV2ray-dev 社区首先发声. 六一当天, QV2ray-dev 警告用户不要使用 Vmess+TCP, 部分 Vmess+WS 及部分 Vmess+ws+TLS(insecure) 的配置组合. 他解释到 GFW 正在进行主动探测, 在 30s 内就可以接近 100% 的探测出你是否使用 Vmess+TCP 的配置, 其他配置亦可以受到波及. 并且此问题并无解决方案, 解决该问题可能需要重新设计 Vmess 协议.
看到了这条消息后, 当下到 V2ray 社区逛了一圈, 发现事态比想象中的严重许多. p4gefau1t 发了一个名为 v2ray的TLS流量可被简单特征码匹配精准识别(附PoC) 的帖子. 过后十几小时又发了个名为 vmess协议设计和实现缺陷可导致服务器遭到主动探测特征识别(附PoC) 的帖子. 这两个帖子在短短几小时内已经获得了数十个回复, 并且多为负责此项目的大牛.
p4gefau1t 首先发现仅凭tls client hello的cipher suite字段,就可以非常准确地将v2ray流量和正常浏览器流量区分开来。
他通过 这篇文章 中提到了使用机器学习训练的模型可对v2ray的tls+ws流量进行识别,准确率高达0.9999. 后来, 经过本地测试,可以复现。并且不限于tls+ws,对tls+vmess等组合也同样有效。其他tls流量如浏览器流量等,全程没有出现误报情况。因此初步怀疑是v2ray使用的utls进行client hello伪造出现的问题。
通过抓包对比真实的chrome与utls的client hello,发现两者基本一致,但与v2ray的存在较大差别,其中包括suite和extension的差别。此后,我们将utls的chrome的cipher suite patch到v2ray中后,此模型无法识别v2ray的tls流量。所以我们可以初步认为,模型很可能是学习了tls client hello的特征,导致流量被识别。
他发现识别tls client hello并不需要使用机器学习的方法,简单的DPI即可实现,因此在gfw部署的成本很低。并且,由于这组cipher suites太过特殊,我们可以仅凭cipher suites进行准确识别。
Cipher Suite 的特征有多特殊呢? 帖子下的网友随手撸一个从 0x90 偏移量开始的 memcmp 都能精准高效识别“特征码”:cca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302
甚至可以利用 iptables 进行明文匹配…… 帖内多个网友用其他配置也多次复现成功, 都得到了相同的特征码.
这个漏洞可以说是十分棘手. 几乎可以说只要 GFW 想, 随时可以全国断网, 并且不分配置(不管有没有 TLS 都是死路一条).
p4gefau1t 在十几个小时后又发了一个帖子. 这次他构造出了更具杀伤性的PoC, 仅需16次探测即可准确判定vmess服务,误报可能性几乎为0,校验的缓解措施均无效。唯一的解决方案是禁用vmess或者重新设计协议。
16 字节 |
X 字节 |
余下部分 |
认证信息 |
指令部分 |
数据部分 |
Vmess 协议前16字节为认证信息,内容为和时间、用户ID相关的散列值。根据协议设计,每个16字节的认证信息auth的有效期只有30秒。而问题出在指令部分。指令部分使用了没有认证能力的aes-cfb方式,因此攻击者可以篡改其中内容,而仍然能被服务器接受。
1 字节 |
16 字节 |
16 字节 |
1 字节 |
1 字节 |
4 位 |
4 位 |
1 字节 |
1 字节 |
2 字节 |
1 字节 |
N 字节 |
P 字节 |
4 字节 |
版本号 Ver |
数据加密 IV |
数据加密 Key |
响应认证 V |
选项 Opt |
余量 P |
加密方式 Sec |
保留 |
指令 Cmd |
端口 Port |
地址类型 T |
地址 A |
随机值 |
校验 F |
前16字节的认证信息可以被重复使用,并且只要通过认证,执行流即可进行到140行,初始化aes密钥流。接着在144行处,服务端在没有经过任何认证的情况下,读入38字节的密文,并使用aes-cfb进行解密,在没有进行任何校验的情况下,将其中版本号,余量P,加密方式等信息,直接填入结构体中。
这里问题已经很明显了,攻击者只需要得知16字节的认证信息,就可以在30秒内反复修改这38字节的信息进行反复的重放攻击/密文填充攻击。
aes本身可以抵抗已知明文攻击,因此安全性方面基本没有问题。出现问题的是余量P。我猜想设计者应该是为了避免包的长度特征而引入这个字段,但是读入余量的方式出现了问题:在没有校验余量P、加密方式Sec、版本号Ver、指令 Cmd、地址类型T、地址A的情况下,将P直接代入ReadFullFrom中读取P字节(182行)。注意,这里P的范围是2^4=16字节以内。读取P+4字节后,v2ray才会对前面读入的内容进行校验,判断命令部分是否合法。如果不合法,断开连接。
临时性纾困方案
V2ray 社区针对这一漏洞在一周内接连推出了两个小的版本更新, 4.23.3 和 4.23.4.
V2Ray 项目在最近的几天内收到了数个隐匿性能方面的漏洞报告。这些漏洞都在被提出的数个小时内被解决(除 mKCP 修复暂缓)并发布相关更新。您可以升级到最新版本 v4.23.4 来获取最大程度的保护。我们支持和鼓励寻找并提出 V2Ray 各个方面漏洞的人。我们希望 V2Ray 的用户不要指责或者攻击为我们提供安全审计的人士。
可以使用
如果你已经升级到 V2Ray v4.23.4,并且没有开启 TLS 的 AllowInsecure 选项,以下配置组合不会泄露识别信息:
VMess over Websocket with TLS
VMess over TLS
VMess over HTTP/2 (使用 TLS 的 HTTP/2,并非 h2c)
Shadowsocks(AEAD) over Websocket with TLS
谨慎使用
以下配置组合可能会在攻击者位于网络路径上时可能会使攻击者获得的协议数据的一些统计学属性,但是这些信息不足以用于确定服务器上部署了这些协议
VMess over TCP (还在继续改进中) 已修复, 可以正常使用
并不建议
以下配置组合不建议用于穿越被攻击者控制的网络:
任何协议 + SOCKS5
任何协议 + HTTP 代理
任何协议 + HTTP 伪装
任何协议 + mKCP + 任何伪装
-xiaokangwang 于 关于在近期收到的数个漏洞的项目组公告
协议的长期解决方案
重写 Vmess 协议可能是在较长时间内解决这一问题的唯一出路.
Vmess 协议已经诞生了很长一段时间. 那时候互联网上tls并不普及,tls1.3也还没出来。因此协议过时出现问题可以说是必然. 依照此趋势, 我倾向于认为下一代的 Vmess 默认协议可能会是类似 Vmess+TCP/WS/HTTP2+TLS 的设计. HTTP3 短期看来不太可能有具体应用, 毕竟 QUIC 作为 HTTP3的雏形, 翻车翻成什么样大家心里都有数.
这次可能可以说是 V2ray 面世五年来遇到的最大一次危机. 不过, 目前的两个紧急补丁已经缓解了燃眉之急, 并且就 V2ray 社区的效率(两天内连续两个补丁), 我基本上已经消解了我之前的随时可能断网的担忧了.
当前社区内对于新协议的讨论如火如荼, 每天都能看到新的点子冒出来. 过不了多久可能就会见到新的用于替换当前的 Vmess 的协议, 或者是目睹 V2ray 终于要进入 v5.0.0时代. 不论是目睹了其中的任何一件, 都是在见证历史, 见证开源社区的协作, 见证又一次与 GFW 的缠斗.