Socks5代理工作原理&抓包分析
Socks5代理工作原理
[TOC]
1. Socks5协议
以下摘自维基百科
SOCKS是一种网络传输协议,主要用于客户端与外网服务器之间通讯的中间传递。SOCKS是”SOCKetS”的缩写[注 1]。 当防火墙后的客户端要访问外部的服务器时,就跟SOCKS代理服务器连接。这个代理服务器控制客户端访问外网的资格,允许的话,就将客户端的请求发往外部的服务器。 这个协议最初由David Koblas开发,而后由NEC的Ying-Da Lee将其扩展到SOCKS4。最新协议是SOCKS5,与前一版本相比,增加支持UDP、验证,以及IPv6。 根据OSI模型,SOCKS是会话层的协议,位于表示层与传输层之间。 SOCKS协议不提供加密。
SOCKS 协议第 4 版本为基于 TCP 协议的 C/S 应用,包括 TELNET, FTP 和 使用广泛的信息发现协议如 HTTP 、 WAIS 提供了不保证安全性的防火墙穿透服务。
SOCKS 5 扩展了第 4 版本,加入了 UDP 协议支持,在框架上加入了强认证功能,并且地址信息也加入了域名和 IPV6 的支持。
2. Socks5 协议交互过程
除非特别说明,包结构图里面的十进制数字代表该字段的长度(字节数)。给定的字段,必定要有确定的值,语法 X’hh’代表该单字节字段的值。’Variable’ 代表该字段为可变长度,其长度要么由对应的关联字段标识(通常为一到两个字节),要么由数据类型确定。
当 TCP 客户端想要建立必须透过防火墙(取决于具体的情况)的连接时,客户端必须与合适的 SOCKS 服务建立连接。SOCKS 服务默认监听 1080 端口,如果连接成功,客户端需要与服务端协商认证方式并完成认证,之后便可以发送中继请求。SOCKS 服务端会执行请求,要么建立起合适的连接,要么拒绝请求。
2.1 认证
第一步,客户端向代理服务器发送代理请求,其中包含了代理的版本和认证方式:
+----+----------+----------+ |VER | NMETHODS | METHODS | +----+----------+----------+ | 1 | 1 | 1 to 255 | +----+----------+----------+
- VER:版本号
- X’04’:Socks4协议
- X’05’:Socks5协议
- NMETHODS:方法数目,该字段包含了METHODS中锁包含了方法识别码的个数
- METHOD :方法列表
第二步,代理服务器从给定的方法列表中选择一个方法并返回选择报文
+----+--------+ |VER | METHOD | +----+--------+ | 1 | 1 | +----+--------+
如果 METHOD (方法)字段为 X’FF‘, 表示方法列表中的所有方法均不可用,客户端收到此信息必须关闭连接。
目前已定义方法如下:
- X’00‘ 无需认证
- X’01‘ GSSAPI
- X’02‘ 用户名/密码
- X’03‘ 到 X’7F’ IANA 指定
- X’80‘ 到 X’FE’ 为私有方法保留
- X’FF‘ 无可接受方法
随后,客户端与服务端开始协商该方法对应的后续认证,后续认证方法因方法而异,在此不进行展开。
2.2请求
第三步,一旦认证方法对应的协商完成,客户端就可以发送请求细节了。如果认证方法为了完整性或者可信性的校验,需要对后续请求报文进行封装,则后续请求报文都要按照对应规定进行封装。
SOCKS请求格式如下
+----+-----+-------+------+----------+----------+ |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+
字段含义:
- VER:协议版本: X‘05’
- CMD:命令
- CONNECT 连接, X‘01’
- BIND 监听X‘02’
- UDP ASSOCIATE UDP关联 X‘03’
- RSV:保留字段
- ATYP:地址类型
- X‘01’: 表明地址字段为一个 IPV4 地址,长度为 4 个字节
- X‘03’ :表明地址字段为一个(合法的)域名,且第一个字节为域名长度标识,(显然)其不以 NULL 作为结束标识
- X‘04’ :表明地址字段为一个 IPV6 地址,长度为 16 个字节
- DST.ADDR:目标地址
- DST.PORT目标端口 (网络字节序)
SOCKS 服务端会根据请求类型和源、目标地址,执行对应操作,并且返回对应的一个或多个报文信息。
第四步,回复报文,客户端与服务端建立连接并完成认证之后就会发送请求信息,服务端执行对应请求并返回如下格式的报文:
+----+-----+-------+------+----------+----------+ |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | +----+-----+-------+------+----------+----------+ | 1 | 1 | X'00' | 1 | Variable | 2 | +----+-----+-------+------+----------+----------+
- VER协议版本: X‘05’
- REP 回复字段(回复类型):
- X‘00’ 成功
- X‘01’ 常规 SOCKS 服务故障
- X‘02’ 规则不允许的连接
- X‘03’ 网络不可达
- X‘04’ 主机无法访问
- X‘05’ 拒绝连接
- X‘06’ 连接超时
- X‘07’ 不支持的命令
- X‘08’ 不支持的地址类型
- X‘09’ 到 X’FF’ 未定义
- RSV 保留字段
- ATYP 地址类型
- IPV4 X‘01’
- 域名 X‘03’
- IPV6 X‘04’
- BND.ADDR 服务端绑定地址
- BND.PORT 服务端绑定端口 (网络字节序)
其中,标记为保留字段( RSV )的值必须设定为 X‘00’ 。
如果协商的方法为了完整性、可信性的校验需要封装数据包,则返回的数据包也会进行对应的封装。
2.3 通信
当连接建立后,客户端就可以和正常一样访问服务端通信了,此时通信的数据除了目的地址是发往代理程序以外,所有内容都是和普通连接一模一样。对代理程序而言,后面所有收到的来自客户端的数据都会原样转发到服务读端。
2.4 总结
通信流程总结:
3. 抓包验证
最近学习了Netty,正好可以使用Netty写一个客户端和服务端用于进行验证程序。服务端使用的是Netty提供例子,客户端是自己开发的简单的Demo。不过不知道是什么原因,自己在使用Wireshark 进行抓包时,并没有自动识别为Socks协议,可能和我代理的内容有点关系,我请求的代理服务器 ORZ
首先看前面三个数据包,很典型的 TCP 握手连接,服务端为本地 1098端口,源端口为本地 59992 端口。
3.1 认证
建立连接完毕之后,第 4 个数据包 就是Socks数据包了
与文档一致,版本号 X‘05’ ,可选方法数目 X‘01’ (一种),方法列表此时显然只有一个字节,其值也对应为 X‘00’ 。根据文档显然其对应为 SOCKS 5 版本,客户端只有一种协商方法 —— 无需认证。紧随其后的第 5 个数据包为 TCP 的 ACK 包,跳过,第 6 个数据包如下:
这一步也与文档一致,为协商认证方式的回复数据包,版本号 X‘05’ ,选择的认证方式为 X‘00’ 。可见无需认证,后续直接进行指令交互就可以了。
3.2 请求
第 7 个数据包为应用发送到 SOCKS 服务端的 TCP ACK 包,第 8 个数据包正如协议描述,为指令请求,抓包样例为 CONNECT 指令,具体如下图:
只需要注意一下新碰到的字段: CMD 字段为 X‘01’ 表示 CONNECT 指令,保留字段确实为 X‘00’ ,地址类型为 X‘04’ 也就是IPV4,端口也是1098,其实在这里为了Demo方便,我在这里请求的我自己。由于我请求的我自己,所以中间又有几条自己请求自己的数据包
最后第十一条是返回数据,
其实这几个字段对照前面给的报文模板都能找到相应的解释,在这就不过多赘述
4.总结
以上就是对Socks5协议解析的全部流程了,总的来说不算太复杂
参考
socialShare('.social-share', { sites: [ 'qq' , 'wechat' , 'weibo' , 'twitter' , 'facebook' ], wechatQrcodeTitle: "分享到微信朋友圈", wechatQrcodeHelper: '期待在朋友圈见到这篇文章' });