转 为何 shadowsocks 弃用一次性验证 (OTA)
https://yuanmomo.net/2019/08/18/ss-give-up-ota/
2019-08-18最近再配置 SS 客户端的时候,看到一个 OTA(deprecated),就查了一下,这个到底是什么东西?偶尔也还听说 SS 已经能被识别到。。。。。趁此机会也就研究一下。
1. 什么是 OTA
OTA(One-Time-Auth),一次性验证,是之前 shadowsocks 为了增强安全性,抵抗 CCA(Chosen-ciphertext Attack,选择密文攻击)而加入的实验性功能。
2. SS 原协议的弱点
2.1. shadowsocks 协议
shadowsocks 协议的 TCP(加密后)包如下
+---------+----------+ | IV | Payload | +---------+----------+ | Fixed | Variable | +---------+----------+ | 固定长度| 变长 | +---------+----------+
IV: Initalization Vector,初始化向量,是使用随机数生成器,生成的一个固定长度的输入值。通过引入 IV 能够使相同的明文和相同的密钥产生不同的密文,让攻击者难以对同一把密钥的密文进行破解。
shadowsocks 服务端会用这个 IV 和 pre-shared key(预共享密钥,通常是用户设置的密码)来解密 TCP 数据包中的 payload。解密后的内容格式如下:
+--------------+---------------------+------------------+----------+ | Address Type | Destination Address | Destination Port | Data | +--------------+---------------------+------------------+----------+ | 1 | Variable | 2 | Variable | +--------------+---------------------+------------------+----------+
其中 Address Type (ATYP) 是地址类型,占一个字节,有三个可能的取值:01, 03, 04,分别对应 IPv4, hostname, IPv6 类型的地址。这些都是 RFC1928 中定义的标准,有兴趣可以去看看。
握手完成后 shadowsocks 中继就会工作在流模式下,后续的所有 TCP 数据包不会再带上 IV,而是使用握手时协商的那个 IV。
2.2. 原协议的缺陷
正如上表所示,原始 shadowsocks 协议 TCP 握手包中的 IV 字段是 Fixed(定长)的。不同的加密算法 IV 长度不同,使用了 RC4 、AES-256-* 类型的流加密方式系列等常用算法,这个长度是 16 字节。
而服务端为了判断数据是否有效,会检查数据包中表示地址信息的那个字节,看它是不是上面提到的三个可能取值。如果是,就尝试解析后面的地址和端口进行连接;如果不是,立即断开连接。
正是 shadowsocks 服务器的这个行为使得主动探测成为可能。
2.2.1. 主动探测原理
一般来讲,「表示地址类型的那个字节」是被加密后发送的,所以第三方无法精确的修改它。但是不巧的是,shadowsocks 所有的加密方式都是 stream cipher(流加密),而这种加密方式的特点就是「明文数据流与密钥数据流一一对应」。
通俗地讲,即对应修改了某个位置的密文(根据加密模式的不同,可能影响到后面其他密文块的解密,也可能影响不到,但在这里这个性质并不重要),如果预先知道了明文的模式,虽然无法解密还原出内容,但可以修改密文中的特定字节,起到修改解密后的明文的效果。 ...