socks5 协议
资料
rfc1928
SOCKS Protocol Version 5
https://datatracker.ietf.org/doc/html/rfc1928
socks5目标: TCP 和 UDP 域中的客户端-服务器应用程序提供一个框架,以便方便、安全地使用网络防火墙的服务
字节序
0x01234567 在字节顺序中表现
Big-Endian
0x100: 0x01
0x101: 0x23
0x102: 0x45
0x103: 0x67
Little-Endian
0x100: 0x67
0x101: 0x45
0x102: 0x23
0x103: 0x01
rfc1929
Username/Password Authentication for SOCKS V5
https://datatracker.ietf.org/doc/html/rfc1929
过程
1.TCP连接
3次握手后,客户端
连接 服务端
socks5端口1080
2.协商环节
2.1.客户端发送给服务端
X'05’ , X开头的数据都是十六进制
报文格式:
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
字段解释:
VER
版本号,X'05'
NMETHODS
支持的认证方法数量METHODS
支持的认证方法ID列表
最小3个byte长度:
|
最大257byte长度:
|
2.2.服务端响应客户端
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
报文格式:
VER
版本号METHOD
从客户端
给定选择的认证方法里面选择其中一种.
METHOD值:
X'00'
无认证需要X'01'
GSSAPIX'02'
用户名,密码方式验证X'03'
toX'7F'
IANA 分配X'80'
toX'FE'
私人方法保留X'FF'
没有可接受的方法列表,此时认证失败,客户端
必须关闭连接.
总共2个byte长度:
|
3.子协商
若服务端
响应METHOD为X'02'
,则进行用户名密码校验
3.1.用户名密码认证
3.1.1.客户端发送
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
- VER socks5版本
- ULEN 用户名长度
- UNAME 用户名
- PLEN 密码长度
- PASSWD 密码
最小长度5个字节
|
最大长度513字节
|
3.1.2.服务端响应
+----+--------+
|VER | STATUS |
+----+--------+
| 1 | 1 |
+----+--------+
- STATUS
- X'00’ 表示成功
- 其他值则客户端必须关闭连接
长度为2byte
|
4.Requests请求
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER: 协议版本
- CMD: 命令
0x01
: CONNECT 建立 TCP 连接0x02
: BIND 上报反向连接地址0x03
: 关联 UDP 请求
- RSV: 保留字段,值为
0x00
- ATYP: 地址类型
0x01
: IPv40x03
: 域名 fully-qualified domain name.0x04
:IPv6
- DST.ADDR 期望目标地址
- DST.PORT 期望目标端口 采用big-endian表示
|
域名下最大长度为262字节,7(固定字段长度)+域名长度
ipv4最大长度为10字节
ipv4最大长度为22字节
5.Replies
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
- VER 协议版本
- REP 回复字段
X'00'
已成功X'01'
通常的socks服务失败X'02'
规则集内不允许X'03'
网络不可达X'04'
主机不可达X'05'
连接已拒绝X'06'
TTL 过期X'07'
命令不被支持X'08'
地址类型不被支持X'09'
至X'FF'
没有定义
- RSV
- ATYP
- BND.ADDR 服务绑定地址
- BND.PORT 服务绑定端口 采用big-endian表示
类型
CONNECT
在对CONNECT
请求的回复中,BND.PORT
包含了服务器分配给连接目标主机
的端口号,而BND.ADDR
包含了对应的IP地址。
提供的BND.ADDR
地址通常与客户端用来连接SOCKS服务器的IP地址不同,因为这样的服务器通常支持多个网络接口。
SOCKS服务器应该考虑DST.ADDR
和DST.PORT
以及客户端源地址和端口来评估CONNECT
请求。
BIND
BIND
请求用于那些需要client
接受server
连接的协议。
FTP
就是一个典型示例,它使用 主
client-to-server
连接传输命令和状态报告,
但可能使用server-to-client
连接按需传输数据(如LS、GET、PUT)。
在应用协议中,客户端应该只在使用 CONNECT
请求建立主连接
后,才使用 BIND
请求建立次连接
.
SOCKS服务器应该在评估BIND
请求时考虑 DST.ADDR
和DST.PORT
。
在BIND
操作过程中,SOCKS服务器会向客户端发送两个回复。
第一个回复是在服务器创建并绑定新套接字后发送。
BND.PORT
字段包含SOCKS服务器为监听传入连接分配的端口号。
BND.ADDR
字段包含相关联的IP地址。
客户端通常会使用这些信息通过主或控制连接通知应用服务器会合地址。
第二个回复仅在待定传入连接成功或失败后发送。
在第二个回复中,BND.PORT
和BND.ADDR
字段包含连接主机的地址和端口号.
UDP ASSOCIATE
UDP ASSOCIATE
请求用于在 UDP 中继进程
中建立一个关联,以便处理 UDP 数据报。
DST.ADDR
和 DST.PORT
字段包含客户端期望用于发送 UDP 数据报的地址和端口。
服务器可以根据这些信息限制对关联的访问。
如果客户端在发送 UDP ASSOCIATE
请求时没有这些信息,则必须使用端口号和地址全部为 0。
UDP 关联会在发起 UDP ASSOCIATE
请求的 TCP 连接终止时 终止。
在对 UDP ASSOCIATE
请求的响应中,
BND.PORT
和 BND.ADDR
字段指示客户端必须将 UDP 请求消息发送到哪个端口/地址进行中继。
基于 UDP 的客户端程序
基于 UDP 的客户端必须将数据包发送到 UDP 中继服务器,
端口号为 UDP ASSOCIATE
请求响应中 BND.PORT
字段指定的端口。
如果选定的认证方法支持封装来保证真实性、完整性和/或保密性,数据包必须使用相应的封装方法进行封装。
每个 UDP 数据包都携带一个 UDP 请求头,其中包含
+----+------+------+----------+----------+----------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+----+------+------+----------+----------+----------+
- RSV (Reserved):保留字段,必须设置为 0x0000。
- FRAG (Fragment):片段标志,用于指示数据包是否被分片:Current fragment number
- 最高位:
- 0:表示数据包没有被分片。
- 1:表示数据包是分片的一部分。
- 其他位:
- 用于表示分片的顺序 范围为1-127
- 最高位:
- ATYP (Address Type):地址类型,指定目标地址的类型:
- 0x01:IPv4 地址。
- 0x03:域名。
- 0x04:IPv6 地址。
- DST.ADDR (Destination Address):根据 ATYP 指定的类型,可以是 IP 地址或域名。
- DST.PORT (Destination Port):目标端口号。
- DATA (User Data):用户数据,封装后的实际数据内容。
数据包转发
- 当 UDP 中继服务器决定转发一个 UDP 数据包时,它会默默地进行,不会通知请求客户端。
- 同样,它也会丢弃无法或不会转发的数据包。
回复数据包处理
- 当 UDP 中继服务器从远程主机收到回复数据包时,它必须使用上述 UDP 请求头和任何与认证方法相关的封装对该数据包进行封装。
- UDP 中继服务器必须从 SOCKS 服务器获取预计将发送数据包到
BND.PORT
的客户端的 IP 地址。 - 它必须丢弃来自任何除了记录在特定关联中的源 IP 地址之外的任何数据包。
数据包分片
FRAG 字段指示数据包是否被分片:
- 最高位指示片段序列的结束。
X'00'
值表示该数据包是独立的。- 1 到 127 之间的值指示片段在片段序列中的位置。
每个接收器都会有一个用于重新组装片段的队列和一个与这些片段相关的重新组装计时器。
- 当重新组装计时器过期或新到达的
FRAG
字段的值小于该片段序列中处理的最高FRAG
值时,重新组装队列必须重新初始化并放弃相关的片段。 - 重新组装计时器必须至少为 5 秒。
- 建议应用程序尽可能避免数据包分片。
不支持分片的实现
实现分片是可选的;不支持分片的实现必须丢弃任何 FRAG
字段不是 X'00'
的数据包。
UDP 编程接口
一个支持 SOCKS 的 UDP 编程接口必须报告低于操作系统提供的实际空间的可用 UDP 数据包缓冲区大小:
- 如果
ATYP
为X'01'
,则减少 10 + 与方法相关的字节。 - 如果
ATYP
为X'03'
,则减少 262 + 与方法相关的字节。 - 如果
ATYP
为X'04'
,则减少 20 + 与方法相关的字节。