谈谈 Shadowsocks

Shadowsocks(简称为 SS)作为连接国际网络的方式之一,被技术人士使用得比较多。和 VPN 类似,SS 也是基于“中转站”的模式,并且支持非全程加密。相对于 VPN 来说 SS 有较强的技术性,一般使用 VPN 的人可能并未听说过 SS 或者不清楚 SS 是什么,这里我就从偏技术的角度来说一说 Shadowsocks。

Shadowsocks 是一种 SOCKS5 代理,设备的网络数据是通过代理服务器再到达 Web 站点。和前面讲的 VPN 原理一样,如果远端 SS 服务器不受干预设备就能畅通无阻的访问国际网络。加密方式也和 VPN 差不多,Shadowsocks 是非全程加密,从设备到 SS 服务器这一段是加密的,从 SS 服务器到 Web 站点这一段则不处理。

Shadowsocks Overview,摘自 Shadowsocks wihte paper

Shadowsocks 与 SOCKS5 关系

SOCKS 是代理的一种*(其他的还有 HTTP 代理、SMTP 代理、FTP 代理等等,应用场景不一样)*,没有专门的应用针对性,通常用于高级的/自定义的网络数据传输。SOCKS 代理协议分 SOCKS4 和 SOCKS5 两版本,SOCKS4 支持 TCP 而 SOCKS5 支持 TCP、UDP 以及基于账号和密码的身份认证,SOCKS5 遵循 RFC1928 协议规范。

Shadowsocks 则基于 SOCKS5 做了一层自定义协议,它定义了数据传输规则、加密/解密方法、协议插件。Shadowsocks 分了 SS-Client 和 SS-Server 两部分来实现自定义规则的数据传输和加密解密,SS-Client 运行于设备端,SS-Server 则运行于服务器端,这两个部分共同完成协议的对接和数据加密/解密。如果客户端需要启用某插件,服务器端则要支持该插件相应的功能,否则插件不起作用。SS-Local 在设备上会表现为一个 SOCKS5 本地代理服务。

使用代理对网络连接路径的改变,以及导致的速度、延时的变化这些都和前面讲的 VPN 的原理差不多,SOCKS5、Shadowsocks 协议本身不会给网络通信带来太大的开销。代理和 VPN 不同的是有些协议(如 ICMP)不走代理,也没法走代理。而 VPN 对网络通讯的接管就比较全面。此外,数据加解密会引入一些计算,会稍微的提升耗电量。

Shadowsocks 协议的实现

协议只运行于 SS-Local 与 SS-Server 之间,站在应用层的视角看不到协议执行、加解密过程,应用层只需要管理远端服务器连接即可。Shadowsocks 有不同语言的开源实现可用于不同的使用环境,像 Rust 写的 shadowsocks-rust,Go 写的 go-shadowsocks2,C 写的 shadowsocks-libev 等等。其中,shadowsocks-libev 是一种原生实现(依赖 libev 库),在 Windows、Linux、Android 上都可以运行。

这些实现都会提供服务器端(SS-Server)和设备端(SS-Local)的程序,将 SS-Server 部署到服务器设置好相关的参数,设备端用同样的参数运行 SS-Local 即可实现最基本的连接。设备端的软件就可以通过由 SS-Local 提供的 SOCKS5 本地代理访问国际网络。

目前开放公用的 SS 服务均不需要登陆,任何一个设备都可以免费连接,而且可以随时切换服务器。即使服务器保留 log 也没法确定设备信息的代表性,不能确定设备的使用人。机器层面的数据和人类实体身份没有任何关联,匿名特性挺好(匿名不代表不支持监管)。

客户端/应用程序的实现

不是所有的软件都能很好的支持 SOCKS5 代理,很多软件不会主动检测 SOCKS5 代理并使用它。通常 SS 客户端需要架设一个本地 Web Proxy 来支持更为普遍的网络访问,此外还需要和操作系统的代理功能对接,让 Web Proxy、SS-Local 能够直接处理操作系统代理端口的网络流量。这样,像浏览器一类的软件就可以不用任何设置走 SS 提供的线路。

不过,这对于自带 Web 网络通信能力(不使用操作系统 Web API)也不主动检测系统代理设置的软件(如 git、curl)不起作用,这类软件默认还是走原有的线路。如果需要走代理线路,则直接设置 SOCKS5 代理会比较高效。

操作系统代理、Web Proxy、SS-Local 都有流量过滤的功能,所以在一些客户端能看到几层过滤设置。最先过滤是操作系统的代理,这里可以设置绕过不需要走代理的流量,这里的过滤也是最高效的因为不需要将数据转到下一级。然后是 Web Proxy 的过滤,有的 Web Proxy 的过滤设计得非常完善和灵活甚至可以支持表达式,在客户端集成了这样的 Web Proxy 后所展示的强大过滤设置即可体现。最后是 SS-Local 的过滤,SS-Local 支持一个过滤列表,太依赖于这一级的过滤往往是低效的因为增加了不必要的本地数据传输。

客户端 App 的实现在 Android 移动设备上有所不同,在 Android 可以注册一个 VPN 服务来接管网络通讯,可以不用设置系统代理。这会让 SS 客户端 App 看起来很像 VPN,不过这只是使用了 Android 的 VPN 服务接管网络数据,App 实际连接的是 SS 服务器。

这个图标未必都是 VPN 服务

服务运营

抛开客户端软件专业的设置不讲,光是连接服务器也会让大部分的 VPN 使用者望而却步,这也是前面讲的“被技术人士使用得比较多”的原因。SS 服务提供方目前很零散,甚至一个开发者既可以在云端搭建 SS 服务,几乎没有公司化的运营方。没点技术背景的人很难用得顺手。

这也凸显出 SS 服务方“难以监管”的一面,也许这是比较重要的问题。

参考资料:

Shadowsocks white paper https://shadowsocks.org/assets/whitepaper.pdf
SOCKS Protocol Version 5 https://tools.ietf.org/pdf/rfc1928.pdf


2019-08-18