Socks5 协议
目录
SOCKS
是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间代理传递 。SOCKS是 "SOCKetS" 的缩写。目前其最新的版本是5,相比于前一个版本,其新增了 IPv6
, UDP
及 验证
。
根据OSI模型,SOCKS是会话层的协议,位于表示层与传输层之间。
协议详情
一个 socks5 连接的过程主要有两部分,协商与请求,如果协商后需要验证,则还包含验证的部分。
(1) 认证方法协商
客户端向服务端发出连接认证方法协商请求
VER
是 SOCKS 的版本,此处是0x05
NMETHODS
是 METHODS 部分数据的长度,即客户端支持的认证方式的 countMETHODS
是客户端支持的认证方式列表,每个方法占一个字节0x00
不需要认证0x01
GSSAPI0x02
用户名密码认证0x03 - 0x7F
由 IANA分配(保留)0x80 - 0xFE
私人方法(保留)0xFF
无可接受的方法
服务器回应协商,从客户端提供的方法中选择一个并通知客户端:
VER
是SOCKS的版本号,此处应为0x05
METHOD
是服务端选中的方法。如果不支持客户端提供的所有方法,则返回0xFF
(2) 认证
如果双方同意使用用户名密码方式认证,则认证过程如下
客户端发送用户名密码:
AVER
认证版本号,目前为0x01
服务端回应认证:AVER
同上STATE
认证状态0x00
成功0x01
失败
(3) 请求
VER
为版本号,此处为0x05
CMD
是 SOCK 的命令码0x01
表示CONNECT 请求
0x02
表示BIND 请求
0x03
表示UDP 转发
RSV
保留,为0x00
ATYP
为目标地址( DST.ADDR)的类型0x01
为IPV4
, 目标地址部分长 4 个字节0x03
为域名
, 目标地址部分的第一个字节为域名长度,其余部分为域名内容(没有 \0 结尾)0x04
为IPV6
, 目标地址分部长 16 个字节
DST.ADDR
目标地址DST.PORT
目标端口(网络字节序)
服务端回应客户端的请求:
VER
是SOCKS版本,这里应该是0x05
;REP
应答字段0x00
表示成功0x01
普通SOCKS服务器连接失败0x02
现有规则不允许连接0x03
网络不可达0x04
主机不可达0x05
连接被拒0x06
TTL超时0x07
不支持的命令0x08
不支持的地址类型0x09 - 0xFF
未定义
RSV
0x00
,保留ATYP
BND.ADDR类型0x01
IPv4地址,DST.ADDR部分4字节长度0x03
域名,DST.ADDR部分第一个字节为域名长度,DST.ADDR剩余的内容为域名,没有\0结尾。0x04
IPv6地址,16个字节长度。
BND.ADDR
服务器绑定的地址BND.PORT
网络字节序表示的服务器绑定的端口
实践
通过 python 建立一个 socks5 服务来分析其协议
代码如下,在本地起一个服务监听 1088端口, 接收 socks5 请求并响应请求
使用浏览器设置 socks5 代理(这里使用firfox):
然后在访问一个 Http 网站,这里选择 http://www.runoob.com/ 来实验,可以看到服务端的输出:
可以看出整个过程如下:
- STEP0 : Client 发起Socks5 请求,
0x05 0x01 0x00
- Server 响应请求,选择验证方法,
0x05 0x00
- STEP1 : Client 发起连接请求:
0x05 0x01 0x00 0x01 0xDB 0xEE 0x14 0x53 0x00 0x50
- Server 给出连接成功的响应
0x05 0x00 0x00 0x01 0xDB 0xEE 0x14 0x58 0x00 0x50
- STEP2: Client 向 Server 发送了HTTP请求
- Server 给出HTTP 响应(实际是Server向实际IP转发请求并给响应转发给Client, 这里做了假的代理)
最终浏览器得到的结果如下图: