相信大家都使用过或者听说过shadowsocks, 它可以帮助我们访问一些“访问不到”的网站。在wiki上对于它的说明是“shadowsocks是一种基于Socks5代理方式的网络数据加密传输包”(百度上并没有这个词条了)。其实shadowsocks就是socks5协议的客户端和服务端的实现。接下来我们了解一下socks5的具体细节,并使用node
来实现一个简单的服务端版本。
其中socks有socks4和socks5版本,socks5比socks4多了UDP、验证,以及IPv6的支持,所有socks5是socks4的升级版也支持了socks4所有的内容(我们下面说到的所有socks协议都是基于socks5版本)。同时socks协议位于表示层和传输层之间,而http和https位于应用层,所以使用socks协议来代理https可以不需要考虑https本身的安全限制。
关于socks5的协议,我们可以查看RFC的socks5说明。
需要注意的是socks5传输的都是16进制的数据。
创建服务器
首先我们需要创建一个服务器来接收后面客服端传过来的数据。
下面是node的实现:
1 | const net = require('net'); |
第一次握手连接
可以看到第一步是创建连接。首先是由客户端发起请求,这里我们还没有写socks5的客户端,我们暂时使用curl
来代替socks5客户端。
我们第一次收到这样格式的数据。
+—-+———-+———-+
|VER | NMETHODS | METHODS |
+—-+———-+———-+
| 1 | 1 | 1 to 255 |
+—-+———-+———-+
第一个VER
表示客服端采用的socks版本,例如socks5版本就会是0x05
。
第二个参数NMETHODS
表示客户端支持的验证类型的数量。
第三个参数METHODS
,每一位表示一个验证类型。
当前定义的方法有:
· X’00’ 不需要认证
· X’01’ GSSAPI
· X’02’ 用户名/密码
· X’03’ – X’7F’ 由IANA分配
· X’80’ – X’FE’ 为私人方法所保留的
· X’FF’ 没有可以接受的方法
而我们接收到客服端信息后,判断是否和自己支持的版本是否一样,同时选择一个验证方式,如果没有则传输0xFF
。
下面是node的代码实现
1 | // 密码验证处理,后面会实现 |