[关闭]
@programath 2015-11-23T11:15:57.000000Z 字数 6191 阅读 3162

SOCKS协议第五版(SOCKS Protocol Version 5)

network protocol


本备忘录状态

这个文件为因特网社区详细说明了一个因特网标准追踪协议,同时为了改善征询讨论和建议。如果想了解标准化情况以及本协议的状态请参考“因特网官方协议标准”的当前版本(STD 1)。该备忘录的分发不受任何限制。

致谢

本备忘录描述了一个协议,该协议是前一个版本4[1]的升级版。这个新的协议源于活跃的讨论以及多个原型实现。关键贡献人如下:加拿大贝尔实验室的Marcus Leech,作为独立顾问的David Koblas,NEC系统实验室的Ying-Da Lee,惠普公司的LaMont Jones, Unify集团的Ron Kuris,以及IBM的Matt Ganis。

1. 简介

将组织内部网络架构隔离于外部网络的网络防火墙以及其它系统的应用越来越流行。这些防火墙系统最典型的用处就是在各个网络之间作为应用层的网关,用于控制TELNET、FTP和SMTP的访问。随着为促进全球信息发现而设计的更加复杂的应用层协议的出现,一个针对协助这些协议透明且安全地穿透防火墙的通用框架的需求也随之出现。

同时,这也需要一个贴近实用的细粒度的强验证。这些需求源于如下现实:“客户端-服务器”关系出现在不同组织的网络之间,并且这种关系必须是受控的而且通常也是强认证的。

这里描述的协议就是为在TCP域和UDP域工作的“客户端-服务器”应用提供一个框架而设计的,从而使这些应用可以便捷安全地使用网络防火墙的服务。从概念上讲,本协议是一个介于应用层和传输层之间“中介层”,而且其本身并不提供诸如ICMP消息转发等网络层网关服务。

2. 现存实践

当前已经有了一个SOCKS4协议,它为基于TCP协议的“客户端-服务器”应用——TELNET、FTP以及流行的信息发现协议如HTTP、WAIS、GOPHER——提供无担保的防火墙穿透功能。

这个新协议为UDP扩展了SOCKS4模型,为提供一般化的强认证方案扩展了框架,为包含域名和IPV6地址扩展了寻址方案。

为了使用SOCKS库中合适的封装例程,SOCKS协议的实现典型地包括重新编译或者重新链接已有的基于TCP的客户端应用。

注意

除非另作说明,出现在包格式图中的十进制数表示对应域的长度,以八位字节为单位。一个给定的八位字节必须承担一个具体的值,语法X'hh'用于表示域中的单个八位字节的值。当单词'Variable'被使用的时候,这表示对应的域有一个可变长度——通过一个关联的一到两个八位字节的长度域或者通过一个数据类型域来定义。

3. 基于TCP的客户端的处理过程

当一个基于TCP的客户端想要创建一个到某个仅通过防火墙(这个限制取决于具体实现)可达的物件的连接时,它必须打开一条到SOCKS服务器的恰当端口的TCP连接。按照惯例,SOCKS服务运行在TCP 1080端口上。如果TCP连接建立成功,客户端就进入了针对要使用的认证方法的协商阶段,通过选择的方法进行认证,然后发送一个中继请求。SOCKS服务器评估这个请求,然后要么建立一个恰当的连接要么拒绝掉。

除非另作说明,出现在包格式图中的十进制数表示对应域的长度,以八位字节为单位。一个给定的八位字节必须承担一个具体的值,语法X'hh'用于表示域中的单个八位字节的值。当单词'Variable'被使用的时候,这表示对应的域有一个可变长度——通过一个关联的一到两个八位字节的长度域或者通过一个数据类型域来定义。

客户端连接到服务器,然后发送一个版本标识符和方法选择消息:

    +----+----------+----------+
    |VER | NMETHODS | METHODS  |
    +----+----------+----------+
    | 1  |    1     | 1 TO 255 |
    +----+----------+----------+

在这个版本的协议中,VER域应该设置为X'05'。NMETHODS域包含了出现在METHODS域中的表示方法标识符的八位字节的个数。

服务器端在METHODS域给定的方法中选择一个,然后返回一个方法选择消息:

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

如果被选择的方法是X'FF',表示客户端发过来的所有方法都不被服务器接受,这时客户端必须关闭连接。

当前定义的表示方法的值有:

然后,客户端和服务器进入了针对具体方法的子协商。

针对所依赖的方法的子协商描述出现在另外的备忘录中。

如果开发者要在该协议中支持新的方法,必须向IANA申请一个新的方法值。要想了解当前已经分配的方法值及其对应的协议,可以参考ASSIGNED NUMBERS文档。

遵守本协议的实现必须支持GSSAPI,并且应该支持USERNAME/PASSWORD认证方法。

4. 请求

针对所依赖方法的子协商一旦完成,客户端就发送请求细节。如果协商过的方法包含了针对完整性检查或保密性目的的封装,这些请求必须被包装到所依赖的方法的封装中。

SOCKS请求按下述格式进行组织:

    +----+-----+-------+------+----------+----------+
    |VER | CMD |  RSV  | ATYP | DST.ADDR | DSP.PORT |
    +----+-----+-------+------+----------+----------+
    | 1  |  1  | X'00' |  1   | Variable |    2     |
    +----+-----+-------+------+----------+----------+

其中,

SOCKS服务器将会基于源地址和目的地址评估这次请求,然后针对请求类型返回一个或多个响应消息。

5. 寻址

ATYP域指定了被包含在一个地址域(DST.ADDR,BND.ADDR)中的地址类型:

表示地址域包含一个长度为4个字节长度的IPV4地址

表示地址域包含一个完整合法的域名。第一个字节表示紧随其后的域名的字节长度。注意最后没有NUL字节。

表示地址域包含一个长度为16字节的IPV6地址。

6. 响应

一旦客户端建立一条到SOCKS服务器的连接并且完成了认证协商,它就会立刻发送SOCKS请求信息。服务器评估请求并且返回一个如下组织的响应:

    +----+-----+-------+------+----------+----------+
    |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    +----+-----+-------+------+----------+----------+
    | 1  |  1  | X'00' |  1   | Variable |    2     |
    +----+-----+-------+------+----------+----------+

其中:

标记为被保留的(RSV)域必须被设置为X'00'。

如果被选择的方法包含了针对认证、完整性或私密性目的的封装,响应必须被包装到所选择方法的封装中。

连接CONNECT

在一个针对CONNECT的响应中,BND.PORT包含了服务器被分配的用于连接到目标主机的端口号,而BND.ADDR包含与此关联的IP地址。BND.ADDR通常与客户端使用的连接到SOCKS服务器的IP地址不同,因为这些服务器通常是多址的。我们期待SOCKS服务器将会使用DST.ADDR和DST.PORT以及客户端侧的源地址和源端口来评估CONNECT请求。

绑定BIND

BIND请求被用于要求客户端接受来自服务器连接的协议中。FTP是一个众所周知的例子,它针对命令和状态报告使用主要的“客户端到服务器”的连接,但是用来响应命令(如LS、GET、PUT命令)的数据传输可以使用一条“服务器到客户端”的连接。

我们期待一个应用协议的客户端侧仅会在使用CONNECT请求建立了一条主要连接之后又想建立一条次要连接的时候才使用BIND请求。我们同时期待SOCKS服务器在评估BIND请求的时候使用DST.ADDR和DST.PORT。

SOCKS服务器在BIND操作中会给客户端发送两个响应。第一个响应在服务器创建并绑定了一个新的socket之后发送。BND.PORT域包含了SOCKS服务器用于监听新连接的端口号,而BND.ADDR域包含了与之关联的IP地址。客户端通常使用这些信息通过主连接(即控制连接)将汇合地址通知应用服务器。第二条响应仅当预期中到来的连接成功或失败之后发送。

在第二条响应中,BND.PORT和BND.ADDR域包含了处于连接中的主机的地址和端口号。

UDP ASSOCIATE

UDP ASSOCIATE请求用于在UDP中继处理中建立一条关联以处理UDP数据报。DST.ADDR和DST.PORT域包含了客户端期待的用于在关联上发送UDP数据报的地址和端口。服务器可以使用这个信息来限制针对该关联的访问。如果客户端在UDP ASSOCIATE时不知道这个信息,客户端必须使用一个全0的端口号和全0的地址。

一个UDP关联在UDP ASSOCITATE请求到达服务器所依赖的TCP连接终结之后才会终结。

在针对UDP ASSOCIATE请求的响应中,BND.PORT和BND.ADDR域指明了客户端必须把被中继的UDP请求消息发送到的端口号和地址。

中继处理Relay Processing

当一个响应(REP值不为X'00')指示失败的时候,SOCKS服务器必须在发送这个响应后立刻断开这条TCP连接。这必须发生在检测到引起失败的原因之后的10秒内。

如果响应码(REP值为X'00')指示成功,而且这次请求是BIND或者CONNECT,那么客户端可以立刻开始数据传输。如果选择的认证方法支持针对完整性、认证或私密性目的封装,要传输的数据应该包装在所依赖的认证方法的封装中。同样地,当针对客户端的响应数据到达SOCKS服务器的时候,服务器也必须根据使用的认证方法来封装数据。

7. 基于UDP的客户端的处理过程

一个基于UDP的客户端必须将它的数据报发送到UDP中继服务器的指定端口——该端口在针对UDP ASSOCIATE的响应中的BND.PORT域指明。如果选择的认证方法提供了针对认证、完整性或私密性目的的封装,数据报必须使用恰当的封装方式进行包装。每一个UDP数据报都随身携带了一个UDP请求头:

    +----+------+------+----------+----------+----------+
    |RSV | FRAG | ATYP | DST.ADDR | DST.PORT |   DATA   |
    +----+------+------+----------+----------+----------+
    | 2  |  1   |  1   | Variable |    2     | Variable |
    +----+------+------+----------+----------+----------+

UDP请求头中的各个域分别为:

当一个UDP中继服务器决定中继一个UDP数据报的时候,它会默默的做——不会给客户端返回任何通知。同样的,如果它不能中继数据报那它就会丢弃数据报。当一个UDP中继服务器从远端主机收到一个响应数据报文的时候,它必须根据使用上述的UDP请求头对该响应报文进行封装,然后再进行所依赖的认证方法的封装处理。

UDP中继服务器必须从SOCKS服务器获得期望的客户端——该客户端将会把数据报发送到在针对UDP ASSOCIATE响应中指定的BND.PORT端口——IP地址。它必须丢弃所有来自任意源IP地址的数据报,除非这些数据报来自早就记录在案的特定关联。

FRAG域指明了该数据报是否为一系列数据报其中之一。如果实现过的话,最高位就会指明该分片序列的结束,但是值X'00'表示该数据报是独立的。1到127之间的值表示一个分片序列中的某个分片的位置。每一个接收者都有一个与这些分片关联的重排序队列重排序定时器。重排序队列有时必须被重新初始化同时将与之关联的数据报全部丢弃,这种情况发生在重排序定时器超时或者一个FRAG值小于当前分片序列已收到的最大FRAG值的分片到达的时候。重排序定时器超时时间必须不少于5秒。我们推荐应用层尽可能的避免分片。

分片的实现是可选的;任何不支持分片的实现必须丢弃任何FRAG值不等于X'00'的数据报。

针对基于SOCKS UDP协议的程序接口必须针对小于操作系统提供的实际空间大小的UDP数据报报告一个可用的缓冲区空间:

8.安全考量

本文档描述的是一个针对应用层穿透IP网络防火墙的协议。穿透过程的安全性高度依赖于具体的认证机制以及由具体实现提供的并且在SOCKS客户端和SOCKS服务器协商阶段选择的认证方法。

选择认证方法的管理员必须对此详加考虑。

9. 引用

作者联系方式

Marcus Leech
Bell-Northern Research Ltd
P.O. Box 3511, Stn. C,
Ottawa, ON
CANADA K1Y 4H7

Phone: (613) 763-9145
EMail: mleech@bnr.ca


[1] Koblas, D., "SOCKS", Proceedings: 1992 Usenix Security Symposium.
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注