-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
shadowsocks-rust 服务端实现缺陷可能导致主动探测 #292
Comments
Sounds fair. I think I proposed something similar for shadowsocks-libev or shadowsocks-org sometime back. |
But if we don't close invalid connections actively, file descriptors will be exhaused. |
It seems that shadowsocks-libev closes socket only when It is quite tricky to avoid TcpStream to be closed by RAII... |
@zonyitoo 也许可以 spawn 一个新的任务来接管这个 TcpStream |
This is one of the ways I was thinking. But that will become very nasty: you have to "catch" this stream everywhere that would throwing |
Made a simple solution for this issue, which will throw away data if server failed to decrypt the first handshake packet. Althrough it is not a perfect solution, but it should help. I am going to make a release v1.8.17 for this. |
Is this what you mean? |
Sort of. |
* Refactored and separate library into crates - shadowsocks: the core feature of shadowsocks - shadowsocks-service: library for building shadowsocks services - dns, http, redir, socks, tunnel - load balancer - shadowsocks-rust: release binaries fix #347 * unified DnsResolver implementation * unified local service common parameters into ServiceContext - ServiceContext is common parameters shared between all local implementations - Completely removed https local support * add #292 reply attack protection * migrated redir local server * support customizing outbound socket bind address * manager outbound socket should accepts connect_opts * republic local implementations * socks5 udp server should always listen to client address * socks4 controlled by local-socks4 feature * socks4 also obey mode configuration * socks server tcp cannot be disable. add support of udp-bind-addr parameter * add udp-bind-addr for customizing udp-relay bind-addr * local-dns infra, support customizing resolver * fully implements DNS relay server * support binding to specific interface on Linux-like platform * tcp cannot be disabled in socks * enable local-flow-stat * fixed windows build * fixed android specific warnings and compile errors * allow udp_only mode in socks5 * dns relay listens to both TCP and UDP, mode controls outbound upstreams * dns relay retries twice if request failed * doc * fix DnsClient typo * fix stream EncryptWriter bug * allow disable logging output updated dependencies * add readme * refine doc * remove depending on trust-dns-client * socks4/4a client * allow socks5 udp_only mode, fixes compile warning * create standalone socks5 UDP relay server - socks5 UDP association full cone (NAT2) * server udp relay supports full cone (NAT2) * acl moved to crate root * redir udp relay support full cone (NAT2) * standard socks5 udp test must use tcp_and_udp mode * set server context fields with pub APIs * udp_max_associations and udp_timeout default value set in Config * local dns resolver retry with fixed attempts * max_udp_association keeps unlimited by default * fixed logging binary name * pops first exited future result for local and server * update reverse target index cache * fix ProxyClientStreamWriteHalf that allows sending empty buffers ref #232 * remove unused import when socks4 is disabled * make balancer become a globally shared object * print plugin exit status * control local, server, manager services in features
shadowsocks-rust 服务端实现缺陷可能导致主动探测
注意:并非协议设计缺陷,仅影响 shadowsocks-rust,其他主要的 shadowsocks 实现都可以抵御此探测,此缺陷可以通过软件更新比较简单地修复,请勿恐慌
方法
在到 shadowsocks-rust 服务端的 TCP 连接上逐字节发送随机数。如服务端采用 AES-256-GCM 或 Chacha20-Poly1305,则连接会在服务端接收到第 50 字节时断开,对于其他 AEAD 加密,连接会在其他的固定位置断开。在使用此方法测试其他服务(HTTP,TLS,SOCKS 5,SSH,RDP,Minecraft,RTMP)时均未见在数十字节左右的固定值中断的现象。
分析
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 端口。
防御
按照 https://censorbib.nymity.ch/#Frolov2020a 的结论,最稳妥的防御是从不主动关闭异常的连接。我们不可能改变完成验证所需长度,但从不主动关闭连接应足以阻止此类依赖服务端响应的主动探测。
The text was updated successfully, but these errors were encountered: