SOCKS:通过防火墙的TCP代理协议[SOCKS4]

Author: Ying-DaLee
PrincipalMember Technical Staff
NEC Systems Laboratory, CSTC
[email protected]

========================

Translator: Stephen Liang
[email protected]

========================

    SOCKS最初由David Koblas开发,随后由Ying-Da Lee修改并扩展到当前的运行版本——Version 4。

    这是一个中继转播协议,它通过在防火墙主机上转发TCP会话,允许应用的用户透明地穿越防火墙进行访问。由于这个协议独立于应用的协议,它能够(而且已经)被用于许多不同的服务,例如telnet, ftp, finger, whois,gopher, WWW等等。访问控制在TCP会话开始时产生请求;之后服务器在客户端和应用服务器间进行简单的转发,仅产生最小的数据处理开销。由于SOCKS从来不必知道应用程序协议的任何内容,它也可以很空易调整应用程序,使用加密来保护应用数据传输,使数据不会受到嗅探器截获。

    两种操作定义:CONNECT(连接)和BIND(绑定)。

    1) CONNECT

    客户端连接到SOCKS服务器,并发送CONNECT请求, 以此来建立一个到应用服务器的连接。客户端在请求中包含了目标主机的IP地址和端口、用户id。下面是请求包的格式。

+----+----+----+----+----+----+----+----+----+----+....+----+

| VN | CD | DSTPORT |     DSTIP        | USERID       |NULL|

+----+----+----+----+----+----+----+----+----+----+....+----+

# of bytes:
1    1      2              4           variable       1

    VN是SOCKS协议的版本号,值为4。CD是SOCKS命令代码,CONNECT请求时的值应为1。NULL长度为一字节,值为0。

    SOCKS服务器检查一个请求是否应该被授权,规则是基于源IP地址,目标IP地址,目标端口,用户id,以及它可以获得的经过商议的识别信息,参阅RFC 1413。假如请求被授权,SOCKS创建一个到指定的目标主机端口的连接。一个应答包返回给客户端,当发生连接建立、请求被拒约或操作失败。

               +----+----+----+----+----+----+----+----+

               | VN| CD | DSTPORT |      DSTIP        |

               +----+----+----+----+----+----+----+----+

 # of bytes:    1    1      2              4

    VN是应答代码的版本,值为0。CD是结果代码,它可以是以下的值:
        90:请求被授权
        91:请求被拒绝或失败
        92:请求被拒绝,SOCKS服务器无法连接到客户端的identd。
        93:请求被拒约,客户端程序和identd使用不同的用户id

注:identd 是一个服务器,它按照 RFC 1413 文档中指定的方式实现TCP/IP 提议的标准 IDENT 用户身份识别协议。identd 的操作原理是查找特定 TCP/IP 连接并返回拥有此连接的进程的用户名。作为选择,它也可以返回其它信息,而不是用户名。
    剩余的域被忽略。

    SOCKS服务器在通知客户端失败或请求拒绝后,立即断开连接。对于一个成功的请求,SOCKS服务器准备好做双向转发。这样可以使客户端在这个连接上做I/O操作,就像它直接连接到应用程序服务器。

    2) BIND

    客户端连接到SOCKS服务器并发送绑定请求,这表示它想要为应用服务器的入站连接做准备。它应当仅发生在与服务器的主连接通过CONNECT建立之后。下面是动作序列的典型部分:
-bind(): 获得一个socket
-getsockname(): 获取socket的IP地址和端口
-listen(): 准备接收应用服务器的请求
-使用主连接通知应用服务器可以连接的IP地址和端口。
-accept(): 接收应用服务器的连接

    SOCKS的BIND操作的目的是为了支持这样一个操作序列,它使用SOCKS服务器上的socket,而不是客户端。客户端在请求包中包括应用程序服务器的IP地址、用于主连接的目标端口、以及用户id。

+----+----+----+----+----+----+----+----+----+----+....+----+

| VN | CD | DSTPORT |     DSTIP        | USERID       |NULL|

+----+----+----+----+----+----+----+----+----+----+....+----+
# of bytes:

   1    1     2              4           variable       1

    VN也是SOCKS的协议版本号4。CD值必须为2,表示BIND请求。

    SOCKS服务器使用客户端信息决定请求是否被授权。返回给客户端应答格式与CONNECT请求相同,即,

               +----+----+----+----+----+----+----+----+

               | VN| CD | DSTPORT |      DSTIP       |

               +----+----+----+----+----+----+----+----+

 # of bytes:     1    1      2              4

     VN是应答代码的版本,值为0。CD是结果代码,它可以是以下的值:

        90:请求被授权
        91:请求被拒绝或失败
        92:请求被拒绝,SOCKS服务器无法连接到客户端的identd。
        93:请求被拒约,客户端程序和identd使用不同的用户id

    然而,对于一个被授权的请求(CD值为90),DSTPORT和DSTIP域是有意义的。这样的话,SOCKS获得一个socket并等待进来的连接,然后依次通过DSTPORT和DSTIP将socket的IP地址和端口发送到客户端。假如应答中的DSTIP值为0(值的常量为INADDR_ANY),然后客户端应当使用连接到客户端的SOCKS服务器的IP地址替换。(这种情况发生在假如SOCKS服务器为非多主机时)典型情况下,这两个数字对于应用客户端程序通过操作序列getsockname()调用的结果是可得到的。应用程序协议必须提供一种方式,这两个信息可以从客户端发送到应用服务器,以便应用服务器能发起到SOCKS服务器的连接,而不是像正常情况下直连到应用客户端。

    当应用服务器的预先连接建立后,SOCKS服务器发送第二个应答包给客户端。SOCKS服务器检查与客户端BIND请求中指定的DSTIP值对应的起始主机IP地址。假如匹配错误,第二次应答中的CD域被设轩为91,并且SOCKS服务器断开两边的连接。假如匹配正确,第二次应答中的CD域被设置为90并且SOCKS服务器准备好转发两个连接间的传输。从这时起,客户端在此与SOCKS服务器连接上做I/O操作,就像直接连接到应用服务器。

    对于CONNECT和BIND操作,服务器对与应用服务器连接的建立做了时间限制(在当前CSTC实现中为2分钟)。假如连接在时间限制过到期时未能建立,服务器关闭与客户端的连接并放弃。

你可能感兴趣的:(C/C++,其它,防火墙,tcp,应用服务器,服务器,socket,null)