这个issue应该不能算bug report,但是也没有找到合适的模板,所以没有使用模板,抱歉。
先说结论:仅凭tls client hello的cipher suite字段,就可以非常准确地将v2ray流量和正常浏览器流量区分开来。
PoC(来自@DuckSoft),此iptables规则可封禁所有v2ray的allowInsecureCiphers设置为false(默认设置)的出站TLS流量,而其他TLS流量不受影响:
iptables -I OUTPUT -m string --algo kmp --hex-string "|001ecca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302|" -j DROP
[微慑网 vulsee.com]
在新的版本释出之前,个人建议的缓解措施是客户端将allowInsecureCiphers设置为true。服务端建议可以拒绝所有具有此特征的TCP连接,以强迫所有客户端更新版本(但此举可能导致服务器遭到主动探测)。
下面是发现的过程和分析。
实验的启发来自下面这篇文章,其中提到了使用机器学习训练的模型可对v2ray的tls+ws流量进行识别,准确率高达0.9999
https://fr33land.net/2020/03/12/can-enable-tls-in-v2ray-help/
他训练的模型已经开源,仓库如下
https://github.com/rickyzhang82/V2Ray-Deep-Packet-Inspection
经过本地测试,可以复现。并且不限于tls+ws,对tls+vmess等组合也同样有效。其他tls流量如浏览器流量等,全程没有出现误报情况。
因此初步怀疑是v2ray使用的utls进行client hello伪造出现的问题。
此处使用的cipher suite,可能出于安全目的,使用了一组特殊的组合,而与绝大多数浏览器不同 。为了对比,下面是utls模拟的chrome的client hello。
抓包可以发现,对比真实的chrome与utls的client hello,两者基本一致,但与v2ray的存在较大差别,其中包括suite和extension的差别。此后,我们将utls的chrome的cipher suite patch到v2ray中后,此模型无法识别v2ray的tls流量。骗子垃圾网站 hackdig.com
所以我们可以初步认为,模型很可能是学习了tls client hello的特征,导致流量被识别。
但实际上,识别tls client hello并不需要使用机器学习的方法,简单的DPI即可实现,因此在gfw部署的成本很低。并且,由于这组cipher suites太过特殊,我们可以仅凭cipher suites进行准确识别。
顺带一提,cipher suites列表在代码中的顺序,和实际的发送的client hello中的顺序似乎是相反的,不知这是有意为之还是bug。
个人建议,客户端依旧使用utls,但应该伪造chrome/firefox的浏览器client hello,AllowInsecureCiphers仅对服务器生效,由服务器限制不安全的cipher suites。
因为 Cipher Suite 特征过于明显,随手撸一个从 0x90 偏移量开始的 memcmp 都能精准高效识别:
“特征码”:cca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302
甚至可以利用 iptables 进行明文匹配……其他的 PoC 方式请大家自己开动脑筋……
代码参考:骗子垃圾网站 hackdig.com
iptables -I OUTPUT -m string --algo kmp --hex-string "|001ecca8cca9c02fc02bc030c02cc027c013c023c009c014c00a130113031302|" -j DROP