-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
gost 的 Shadowsocks 服务端实现缺陷可能导致主动探测 #683
Comments
@DuckSoft 上面这两个库有没有你所说的缺陷? |
@ginuerzh 来看看。 |
在最新的 release 中(2.11.1),这个问题仍然存在。 |
注意:并非协议设计缺陷,仅影响 gost Shadowsocks,其他主要的 Shadowsocks 实现都可以抵御此探测,此缺陷可以通过软件更新比较简单地修复,请勿恐慌。
方法
在到 gost Shadowsocks 服务端的 TCP 连接上逐字节发送随机数。如服务端采用 AES-256-GCM 或 CHACHA20-IETF-POLY1305,则连接会在服务端接收到第 50 字节时断开,对于其他 加密,连接会在其他的固定位置断开。在使用此方法测试其他服务(HTTP,TLS,SOCKS5,SSH,RDP,Minecraft,RTMP)时均未见在数十字节左右的固定值中断的现象。
分析
AEAD 加密
Shadowsocks AEAD 加密协议结构如下
其中
chunk
有以下结构Shadowsocks (以及同类协议)对数据完整性的验证完全依靠 AEAD 解密过程保证——只有在第一次 AEAD 解密后,我们才能知道数据流是否伪造。如果一个服务端在发现解密失败后直接关闭连接,例如 shadowsocks-rust ,则可以使用 v2ray/v2ray-core#2523 中提到的逐字节发送数据包并观测连接何时关闭的手段测量验证过程至少需要多少字节。
对于 Shadowsocks AEAD,完成验证需要接收
salt
,第一个chunk
的encrypted_length
和encrypted_length_tag
。其中salt
和encrypted_length_tag
是与加密相关的常数,encrypted_length
长度为 2。则对现有 AEAD 加密,有下表,可见对于现有加密,有 34/42/50/82 这四种可能的验证所需长度,抛开不常用加密,实际上只有 50(和 34)。显然随机数不可能通过 AEAD 解密过程验证,服务端会在接收到完成验证所需长度的数据后关闭连接。因此若多次向某个开放的 TCP 端口逐字节输入随机数,连接始终在输入50字节后断开,则可怀疑此端口是 Shadowsocks 端口。
流加密
Shadowsocks 流加密协议结构如下
其中
encrypted_data
有以下结构使用错误的密码时,
atyp
极有可能是不合理的数值,导致服务端无法解析地址。对于流加密,在解密atyp
后,即可以较低的假阳性率(3/256)知道数据流是否伪造。按照相同的原理,连接会在 8/12/16 字节后断开。无加密/置换密码/rc4加密
这三种加密不使用
iv
,可以视作流加密中iv
长度为0的特例。按照相同的原理,连接在接收到第一字节时(有 (256-3)/256 的概率)断开。防御
按照 https://censorbib.nymity.ch/#Frolov2020a 的结论,最稳妥的防御是从不主动关闭异常的连接。我们不可能改变完成验证所需长度,但从不主动关闭连接应足以阻止此类依赖服务端响应的主动探测。
Credits
https://github.com/Qv2ray
https://github.com/studentmain
Related
txthinking/brook#708
shadowsocks/shadowsocks-rust#292
nadoo/glider#180
The text was updated successfully, but these errors were encountered: