一 介绍
Socket5协议,也被称为SOCKS5,是SOCKS协议的第五个版本。SOCKS是一个网络协议,它允许客户端通过服务器来访问网络服务,这个服务器会作为一个代理服务器来转发客户端的请求和服务器的响应。
SOCKS5协议相比于前一个版本SOCKS4,增加了很多新的特性,包括:
更好的安全性:SOCKS5支持各种类型的身份验证方法,包括无身份验证、用户名/密码身份验证和GSS-API身份验证。这使得SOCKS5比SOCKS4更安全。
更好的性能:SOCKS5支持IPv6,这使得它能够处理更多的网络流量。此外,SOCKS5还支持UDP协议,这使得它能够处理更多类型的网络请求。
更好的兼容性:SOCKS5支持各种类型的网络协议,包括TCP和UDP。这使得SOCKS5能够与各种类型的网络服务进行交互。
总的来说,SOCKS5是一个强大的网络协议,它提供了一种安全、高效和兼容性强的方式来访问网络服务。
二 协议详解
首先是握手,先认证握手再连接握手
认证握手:
客户端首先发送一个声明支持的认证方式的列表到服务器。服务器从这个列表中选择一个它也支持的方式,并发送回去。如果所选的方式需要进一步的验证(例如用户名/密码验证),那么客户端将会发送必要的凭证(例如用户名和密码),服务器接收并验证这些凭证。认证握手的主要目的是为客户端和服务器的后续交互建立一种安全的认证机制。
连接握手:
认证成功后,客户端发送一个连接请求到服务器,声明要连接的远程主机和端口及所用的连接类型(通常是TCP或UDP)。服务器处理这个请求,尝试与指定的远程主机建立连接,并发送一个包含请求处理结果的响应回到客户端。如果请求成功,那么此后客户端和服务器就可以在当前的连接上进行进一步交互(如发送和接收数据)。连接握手的主要目的是为客户端建立到远程主机的代理连接。
2.1 认证握手
在Socks5协议握手的过程中,客户端首先需要发送一个报文,格式如下:
+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
每个字段的含义是:
VER
:版本号,Socks5协议的版本号为0x05
,这个字段占1个字节。NMETHODS
:身份验证方式的数量,这个字段也占1个字节。METHODS
:客户端支持的身份验证方式列表,每种方式占1个字节,可以有1到255种不同的方式。
举个例子,假设一个客户端支持两种身份验证方式,无需认证和用户名/密码认证,那么它发送的报文可能是0x05 0x02 0x00 0x02
。
在接收到客户端发送的身份验证方式列表后,Socks5服务器会回复一个信息来表明其选择的验证方式。服务器的回复报文格式如下:
+----+--------+
|VER | METHOD |
+----+--------+
| 1 | 1 |
+----+--------+
每个字段的含义是:
VER
:版本值,对于Socks5协议,该字段的值应为0x05
。METHOD
:服务器选择的身份验证方式,此值应在客户端提供的身份验证方式列表中。
如下是一些具体的METHOD
值代表的含义:
0x00
:无需认证0x01
:GSSAPI0x02
:用户名/密码0xFF
:无可接受的方法,如果服务器返回这个值,那表示它不能接受客户端提供的任何身份验证方式。
因此,如果服务器选择不需要任何身份验证,那么它将回复0x05 0x00
。如果它选择用户名/密码认证,则回复0x05 0x02
。
当客户端收到服务器的回应,如为0x05 0x00
直接到连接握手。
当客户端收到服务器的回应,如0x05 0x02
后,这表明服务器选择了0x02
作为身份验证方式。在Socks5协议中,0x02
代表Username/Password方式。
客户端需要根据这个服务端的要求,提供相应的用户名和密码进行身份验证。具体的验证报文格式如下:
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
客户端需要根据这个服务端的要求,提供相应的用户名和密码进行身份验证。具体的验证报文格式如下:
每个字段的含义是:
VER:版本值,对于UserName/Password身份验证方式,该字段的值应为0x01。
ULEN:用户名长度。
UNAME:用户名,长度为ULEN。
PLEN:密码长度。
PASSWD:密码,长度为PLEN。
其实例假设用户名为user
,密码为passwd
,则客户端会发送如下格式的身份验证信息:
0x01 0x04 0x75 0x73 0x65 0x72 0x06 0x70 0x61 0x73 0x73 0x77 0x64
当服务器收到客户端发送的身份验证信息后,会进行相关的验证步骤。
首先,服务器会解析出客户端发送的用户名和密码,然后进行相应的验证。这个验证过程依赖于具体的实现,例如可以查看一个数据库是否包含特定的用户名和密码,或者可以对密码进行哈希计算并与预先存储的值进行比较。
验证成功后,服务器将发送一个回复给客户端,确认身份已验证。回复的报文格式如下:
+----+--------+
|VER | STATUS |
+----+--------+
| 1 | 1 |
+----+--------+
每个字段的含义是:
VER:版本值,对于Username/Password身份验证方式,该字段的值应为0x01。
STATUS:状态码,0x00表示验证成功,非0x00值表示验证失败。
例如,如果验证成功,服务器将发送0x01 0x00
给客户端。如果验证失败,服务器会将连接关闭。
0x01 0x04 0x5 0x73 0x65 0x72 0x06 0x70 0x61 0x73 0x73 0x77 0x640x01 0x04 0x75 0x73 0x65 0x72 0x06 0x70 0x61 0x73 0x73 0x77 0
2.2 连接握手
当Socks5客户端的认证通过后,将进行连接握手。首先客户端需要发送一个连接请求,然后服务器将根据请求决定与目标服务器的连接方式。下面是这个阶段主要步骤和报文格式:
第一步:客户端发送请求到Socks5服务器。请求报文的格式如下:
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
每个字段的具体含义:
VER:版本号,对于Socks5协议,该字段的值应为0x05。
CMD:连接的类型,可以取以下值:
X'01':CONNECT,表示建立TCP/IP连接。
X'02':BIND,表示绑定TCP/IP端口。
X'03':UDP ASSOCIATE,表示UDP关联。
RSV:保留字段,应为X'00'。
ATYP:指定了DST.ADDR字段中的地址类型,取值及含义如下:
X'01':IPv4地址,占用4个字节。
X'03':域名,长度不固定(长度由紧接着的一个字节决定)。
X'04':IPv6地址,占用16个字节。
DST.ADDR:目标地址,在网络请求中,需要访问的对方IP或者主机名。根据ATYP字段可能是一个IPv4地址、一个域名或者一个IPv6地址。
DST.PORT:目标端口,在网络请求中,需要访问的对方的端口,两字节,网络字节序。
第二步:在得到客户端的连接请求之后,Socks5的服务器会回复一个信息来表明这个连接请求的处理结果。服务器的回复消息格式如下:
+----+-----+-------+------+----------+----------+
|VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
每个字段的具体含义:
VER:版本号,对于Socks5协议,该字段的值应为0x05。
REP:表示响应的状态码,服务器返回给客户端的状态值,此值独立于所选的身份验证、命令和地址类型方法。取值及含义如下:
X'00':succeeded,表示请求成功,连接已经建立。
X'01':general SOCKS server failure,表示请求失败,一般是由SOCKS服务器错误导致。
X'02':connection not allowed by ruleset,表示由于服务器设置的规则,请求的连接不被允许。
X'03':Network unreachable,表示网络不可达,一般由于网络问题导致。
X'04':Host unreachable,表示目标主机不可达,也是由于网络问题导致。
X'05':Connection refused,表示连接被拒绝,无法建立连接。
X'06':TTL expired,表示请求的生存时间(TTL)过期。
X'07':Command not supported,表示不支持的命令。
X'08':Address type not supported,表示不支持的地址类型。
RSV:保留字段,应为X'00'。
ATYP:指定了BND.ADDR字段中的地址类型。取值及含义如下:
X'01':IPv4地址,占用4个字节。
X'03':域名,长度不固定(长度由紧接着的一个字节决定)。
X'04':IPv6地址,占用16个字节。
BND.ADDR:表示绑定地址,即服务器为此次会话分配给客户端的地址。根据ATYP字段可能是一个IPv4地址、一个域名或者一个IPv6地址。
BND.PORT:表示绑定的端口,即服务器为此次会话分配给客户端的端口,两字节,网络字节序。
2.3 数据传输
Socks5协议支持三种数据传输方式:CONNECT、BIND和UDP ASSOCIATE。也就是上面提到的连接握手时的CMD
,当sockt5服务器响应成功就进入到了对应的数据传输模式。
2.3.1 CONNECT
CONNECT 命令用于建立TCP连接,其具体执行流程如下:
客户端向服务器发送一个 "CONNECT" 请求,该请求包含目标地址和端口。
服务器会收到这个 "CONNECT" 请求后,开始尝试与目标地址建立TCP连接。
建立连接后,服务器会向客户端发送一个响应,指示连接是否成功建立。
客户端收到连接成功后,开始传输数据(复用之前的TCP连接)。
客户端 服务器 目标地址
| | |
|——— Socks5握手 ———> | |
|<—— 握手成功响应 —— |
| | |
|——— 权限认证请求 ——> |
|<—— 认证通过响应 —— |
| | |
|——— CONNECT请求 ———>|
| | |
| |— 连接目标地址请求 —> |
| |<— 连接成功响应 —— |
|<——— 成功响应 ———— |
| | |
|——— 开始数据传输 ——> |
| |— 数据传输至目标 ——> |
| |<— 目标回传数据 —— |
|<—— 数据传输回客户端 |
| | |
2.3.2 BIND
Socks5协议中的BIND命令用于在SOCKS服务器上建立一个监听的端口,为即将到来的连接做准备。它常见的用途是在FTP数据传输中支持被动模式(PASV)。具体流程如下:
客户端向服务器发送BIND请求。这个请求将会告诉服务器在哪个地址和端口进行监听
服务器收到请求后,会在指定的地址和端口上建立监听。如果监听成功,服务器将返回一个响应给客户端。
当有来自被动模式的FTP服务器的连接至SOCKS服务器时,SOCKS服务器会另外发送一个响应至客户端。
如果服务器返回的REP是0x00,表示连接成功。然后,客户端就可以开始在这个连接上进行数据传输了。
客户端 服务器 远端客户机
| | |
|——— Socks5握手 ———> | |
|<—— 握手成功响应 —— | |
| | |
|——— 权限认证请求 ——> | |
|<—— 认证通过响应 —— | |
| | |
|——— BIND请求 ————> | |
| |——— 设置监听 ————> |
|<——— 成功响应 ———— | (返回BND.ADDR和BND.PORT)|
| | |
| |<—— 远端连接请求 —— |
| |—— 连接成功响应 ——> |
|<——— 连接通知 ———— | (返回BND.ADDR和BND.PORT) |
|——— 开始数据传输 ——> | |
| |<—— 数据回传 ———— |
|<—— 数据传输回客户端 | |
2.3.3 UDP ASSOCIATE
UDP ASSOCIATE操作是Socks5协议中处理UDP请求的部分。下面我们将详细讨论这个流程:
客户端启动一个TCP连接到Socks5服务的IP和端口,并发送一个UDP ASSOCIATE请求(DST.ADDR和DST.PORT)给Socks5服务器。
Socks5服务器接收到请求后,会设置监听一个UDP端口,然后返回一个响应(BND.ADDR和BND.PORT)给客户端。
客户端收到响应后,向BND.ADDR和BND.PORT发送UDP请求
Socks5服务器在收到从客户端发来的UDP数据包后,会将其转发到目标地址和端口
目标主机处理完UDP请求后,将UDP响应发送回Socks5服务器,然后服务器将UDP响应处理并发送到客户端
在Socks5协议中,Sockt5服务端在响应UDP请求时,会在数据包前增加一个头部,该头部的结构如下:
+----+------+------+----------+----------+--------+
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+----+------+------+----------+----------+--------+
| 2 | 1 | 1 | Variable | 2 |Variable|
+----+------+------+----------+----------+--------+
其中RSV是保留字段,固定为0x00;FRAG是片段编号,用于UDP数据包分片,在这个场景中通常为0x00;ATYP表示地址类型,DST.ADDR和DST.PORT表示目标地址和端口;DATA是UDP数据包的负载。
服务端在接收到来自目标主机的UDP响应后,需要创建一个新的数据包,将UDP响应作为DATA部分,然后在前面添加上述的头部信息,最后将新的数据包发送回客户端。
客户端收到数据包后,会根据头部中的DST.ADDR和DST.PORT来确定这个数据包是从哪个目标地址和端口发送过来的,然后处理DATA部分的UDP响应。
三 总结
Socks5协议是一个较为简单的协议,它的RFC文档相当简短,但这并不意味着它的能力有任何限制。实际上,Socks5协议因其简洁高效而被广泛采用,适用于各种复杂的网络环境。其主要功能是作为一个代理服务器,允许客户端通过它来传输TCP和UDP包,与网络上的其他服务器进行通信。
Socks5协议不仅具有广泛的应用通道,还包括多种身份验证方法,适应不同的需求。其常用的身份验证方法包括无需任何验证、用户名/密码验证,以及GSSAPI验证。此外,Socks5协议还支持IPv4和IPv6两种网络地址格式。
虽然Socks5协议文档简洁,但对于理解网络传输原理、应用程序与网络栈的交互关系,以及编程实践都有极大的帮助。对于希望实现Socks5服务的朋友,这将是一个非常值得挑战的任务。
评论区