socks5:一些笔记

基于TCP的客户端程序

当一个基于TCP协议的客户端想要建立一个链接,但与链接目标之间有一个防火墙,则客户端必须打开一个TCP链接,链入SOCKS服务系统中合适的端口。该端口一般位于1080。如果连接成功,客户端将指定一个验证方法,然后发送一个轮询请求。服务器接到请求后,或建立,或拒绝。
除非额外指定,否则在数据包格式图中出现的十进制数(字节)表示相应字段的长度。给出的八位字节必须指定值,X’hh’ 用来表示该字段中的单个八位字节。当使用’Variable’ 时,表示相应的字段具有由相关联的(一个或两个八位字节)长度字段或由数据类型字段定义的可变长度。
客户端连接到服务器后,发送一条协商版本及方法的信息至服务器。

+-----+----------+----------+
| VER | NMETHODS |  METHODS |
+-----+----------+----------+
|  1  |     1    | 1 to 255 |
+-----+----------+----------+
  • VER:标识版本,X’05’为SOCKS5
  • NMETHODS:包含METHODS字段中出现的指定方法的八进制数。

服务器在客户端给出的METHODS中选择一个方法,并且将结果返回给客户端

+-----+---------+
| VER |  METHOD |
+-----+---------+
|  1  |    1    |
+-----+---------+

如果METHOD的值为X’FF’,则表示客户端给出的方法中没有一个被接收,此时客户端必须关闭链接。
METHOD 值定义:

  • X’00’ 无需验证
  • X’01’ GSSAPI
  • X’02’ 用户/密码
  • X’03’ ~ X’7F’ 由IANA分配
  • X’80’ ~ X’FE’ 私有方法储备
  • X’FF’ 方法不合法
    然后客户和服务器进入由选定认证方法所决定的子协商过程。各种不同的方法的子协商过程的描述请参考各自的备忘录。

请求

当子协商过程完成,客户端发送详细的请求数据。如果协商的方法中有以完整性检查和/或以安全性为目的的封装,则该请求必须按照以下方法所定义的格式进行封装。  

    +----+-----+-------+------+----------+----------+
    |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
    +----+-----+-------+------+----------+----------+
    | 1  |  1  | X'00' |  1   | Variable |    2     |
    +----+-----+-------+------+----------+----------+
  • VER: 协议版本 (X’05’:SOCKS5)
  • CMD
    • CONNECT X’01’
    • BIND X’02’
    • UDP ASSOCIATE X’03’
  • RSV RESERVED(保留)
  • ATYP 以下地址的类型
    • IP V4 地址:X’01’
    • DOMAINNAME:X’03’
    • IP V6 地址:X’04’
  • DST.ADDR 目的地址
  • DST.PORT 以网络字节顺序出现的端口号

服务器会对请求基于来源及目的地进行评估,然后根据请求类型给出一个或多个回复信息。

应答

当对服务器的请求被确定,且认证协商完成时,客户端会立刻发送SOCKS请求信息。如果协商的方法中有以完整性检查和/或以安全性为目的的封装,则该请求必须按照以下方法所定义的格式进行封装:

    +----+-----+-------+------+----------+----------+
    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    +----+-----+-------+------+----------+----------+
    | 1  |  1  | X'00' |  1   | Variable |    2     |
    +----+-----+-------+------+----------+----------+
  • VER 懒得讲了
  • REP 回应字段
    • X’00’ 成功
    • X’01’ 请求失败
    • X’02’ 请求规则不合法
    • X’03’ 网络无法连接
    • X’04’ 服务器无法连接
    • X’05’ 连接被拒绝
    • X’06’ 连接超时
    • X’07’ 命令不合法
    • X’08’ 地址类型不合法
    • X’09’ ~ X’FF’ 未注册的值
  • RSV 保留(必须设置为X’00’)
  • ATYP (同上)
  • BND.ADDR 服务器绑定地址
  • BND.PORT 以网络字节顺序表示的服务器绑定的端口

ATYP详解

CONNECT

在对CONNECT的回复中,BND.PORT包含服务器分配的用于连接到目标主机的端口号,而BND.ADDR包含关联的IP地址。 BND.ADDR通常不同于客户端用于访问SOCKS服务器的IP地址,因为此类服务器通常是多宿主的。 SOCKS服务器将使用DST.ADDR和DST.PORT,以及客户端源地址和端口来评估CONNECT请求。

BIND

BIND请求用在需要客户端同意来自服务器的连接的协议中。 如FTP,它建立客户端到服务器连接来发送命令和状态报告,但也可能使用服务器到客户端的连接来按需传输数据(例如LS,GET,PUT)。

应用协议的客户端将使用BIND请求,在使用CONNECT建立主连接之后建立次连接。SOCKS服务器将使用DST.ADDR和DST.PORT来评估BIND请求。

在BIND操作期间,SOCKS服务器将发送给客户端两条回复。第一个是在服务器创建和绑定一个新的套接字后发送的。 BND.PORT字段包含SOCKS服务器分配的用于侦听传入连接的端口号。 BND.ADDR字段包含关联的IP地址。客户端通常将使用这些信息来通知(经由主连接或控制连接)应用服务器的会合地址。第二个回复仅在预期的传入连接成功或失败后发生。在第二个应答中,BND.PORT和BND.ADDR字段包含了连接主机的IP地址和端口号。

UDP ASSOCIATE

UDP ASSOCIATE请求用于在UDP中继过程中建立关联以处理UDP数据报。DST.ADDR和DST.PORT字段包含客户端期望用于发送UDP数据报的关联的地址和端口。 服务器可以使用此信息来限制对关联的访问。 如果客户端在UDP ASSOCIATE时不具有信息,则客户端必须使用全零的端口号和地址。

当UDP ASSOCIATE请求到达的TCP连接终止时,UDP关联终止。

在对UDP ASSOCIATE请求的答复中,BND.PORT和BND.ADDR字段指示客户端必须发送要请求中继的UDP请求消息的端口号/地址。

REP详解

REP != X’00’:指示失败,SOCKS服务器必须在发送回复之后立即终止TCP连接,且必须在检测到导致故障后的10秒内。

REP == X’00’:指示成功,并且请求是BIND或CONNECT,则客户端现在可以开始传递数据。 如果所选认证方法支持用于完整性,安全性 和/或 机密性的封装,则使用依赖于方法的封装来封装数据。 类似地,当数据到达用客户端的SOCKS服务器时,服务器必须封装适合于正在使用的认证方法的数据。

基于UDP的客户端程序

基于UDP的客户端必须在对UDP ASSOCIATE请求的回复中,通过BND.PORT指示的UDP端口将其数据报发送到UDP中继服务器。 如果选择的认证方法支持用于完整性,安全性 和/或 机密性的封装,则必须使用适当的封装来封装数据报。 每个UDP数据报都带有一个UDP请求头:

  +----+------+------+----------+----------+----------+
  |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
  +----+------+------+----------+----------+----------+
  | 2  |  1   |  1   | Variable |    2     | Variable |
  +----+------+------+----------+----------+----------+
  • RSV X‘0000’
  • FRAG 当前分段号
  • ATYP (同上)
  • DST.ADDR
  • DST.PORT
  • DATA 用户信息

当UDP中继服务器决定中继或丢弃UDP数据报时,它不会通知请求的客户端。当UDP中继服务器从远程主机接收到应答数据报时,它必须使用上述UDP请求报头或任何依赖于该认证的方法来封装。

客户端将向UDP ASSOCIATE给出的BND.PORT发送数据报,而UDP中继服务器必须从SOCKS服务器获得该客户端的期望IP。

The UDP relay server MUST acquire from the SOCKS server the expected
IP address of the client that will send datagrams to the BND.PORT
given in the reply to UDP ASSOCIATE. (???神特么英文长句…哪来的那么多定语啊…UDP中继服务器必须从SOCKS服务器获得将要向在UDP ASSOCIATE给出的BND.PORT发送数据报的客户端的期望IP地址???)

它必须删除任何源IP地址,除了被记录用于特定关联的IP地址,的所有数据报。

FRAG字段指示该数据报是否是多个片段中的一个。则高阶比特指示分段序列的序列,而值X’00’指示该序列是独立的。 1和127之间的值表示片段序列内的片段位置。每个接收器将具有与这些片段相关联的重组队列和重组定时器。重新装配队列必须重新初始化。当重组定时器超时或者新的数据报到达时携带FRAG字段,且其值小于为该片段序列处理的最高FRAG值,则丢弃相关片段。重组定时器必须不少于5秒。建议通过应用尽可能避免分段。

分段的实现是可选的;不支持分段的实现必须删除FRAGfield不是X’00’的所以数据报。

一个SOCKS的UDP编程接口必须报告UDP数据报的可用缓存空间是否小于操作系统提供的实际剩余空间:

  • ATYP == X’01’ - 10+method_dependent octets smaller
  • ATYP == X’03’ - 262+method_dependent octets smaller
  • ATYP == X’04’ - 20+method_dependent octets smaller