socks5在socks4上多了对udp代理的支持,可以说是“全能代理”了。udp代理较对比tcp代理,流程上要复杂一些,下面从最开始流程讲起
握手阶段
客户端建立和代理服的tcp连接A,并发送第一帧数据:
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
代理服务器收到后,会鉴别VER,回应
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
流程和前一篇socks5协议简介完全相同
准备阶段
客户端发送第二帧数据:
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
CMD:命令,tcp代理0x01,udp代理0x03
RSV:保留字段
ATYP:地址类型 0x01:ipv4,0x03:域名,0x04:ipv6
DST.ADDR:本地使用udp的地址
DST.PORT:本地使用udp的端口
比如数据 :0x05|0x03|0x00|0x01|0x00000000|0x0000
代表需要代理的是udp连接,此时DST.ADDR和DST.PORT代表客户端UDP准备发送的地址和端口,用于服务器权限控制(只给DST.ADDR:DST.PORT发出来的udp包代理),当然可以为空即全是0
代理服收到后,回复
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
REP:状态位,0x00代表连接DST.ADDR成功了
RSV:保留字段
ATYP:地址类型 0x01:ipv4,0x03:域名,0x04:ipv6
BND.ADDR:udp代理地址
BND.PORT:udp代理端口
比如,返回0x05|0x00|0x00|0x01|0xc0a8c76a|0xcdf0,通知客户端UDP代理地址是192.168.199.106:52720,有什么udp包直接向这个地址发
代理阶段
客户端知道udp代理地址后,将所在发送的数据DATA需要包裹成下面的帧发送给192.168.199.106:52720
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
RSV:保留位
FRAG:分片位
ATYP:地址类型 0x01:ipv4,0x03:域名,0x04:ipv6
DST.PORT:目标地址
DST.PORT:目标端口
DATA:要发送的数据
其中FRAG分片位,用于控制大帧分成多帧用,一般情况下为0x00(不分帧)
UDP代理收到后,将DATA分离出来,发送给DST.ADDR:DST.PORT,同时,收到目标报的UDP的数据,也包裹成上面帧结构发给客户端
总结
可以发现,udp代理的建立是在与代理服先建立tcp连接,tcp连接上先“握手”和“准备代理”,客户端知道udp代理地址后,就不用这个tcp连接了,直接udp代理了,理论上这个tcp连接无用了,但socks5协议指出,这个tcp连接要保持长连接,如果断开,则相应的udp代理也要结束,真正实现上,我看过的许多socks5代理源码没实现的这么细,我的golang实现socks5上,也只是保持这个tcp长连接,有时间再完善这个细节点
想详细了解的可以参照我的golang实现https://github.com/0990/socks5
引用
RFC1928-SOCKS Protocol Version 5
有疑问加站长微信联系(非本文作者)