sock5开发(2)_sock5协议用户名密码篇

之前已经发文介绍过sock5协议无密码模式了,sock5有密码模式整理与无密码模式逻辑相同,但为了单独看此篇文章的童鞋,还是完整介绍下。

相关协议规范有2篇(第一个链接介绍sock5协议,第二篇介绍鉴权相关内容):

https://www.ietf.org/rfc/rfc1928.txt

https://www.ietf.org/rfc/rfc1929.txt

协议开始的前提当然是建立socket连接,然后开始认证流程。

一、支持的协议

客户端发起:

// +----+----------+----------+ // |VER | NMETHODS | METHODS| // +----+----------+----------+ // | 1|1 | 1 to 255 | // +----+----------+----------+ //如:版本为sock5,支持2种认证:无认证和密码认证 //数据为 0x05 0x02 0x00 0x02VER: 表示sock协议版本,此处固定值为0x5NMETHODS: 表示Client支持的认证方法数量, 同时也是METHODS段的长度METHODS: 客户端具体支持的认证方法,长度由NMETHODS决定

METHODS 值定义如下:

0x00 无认证( 不需要认证)0x0 GSSAPI认证0x02 用户名密码认证0x03 ~ 0x7F IANA 分配0x80 ~ 0xFE 私有方法保留0xFF 没有可用的认证方法

服务器答复:

// +----+--------+ // |VER | METHOD | // +----+--------+ // | 1| 1| // +----+--------+ //例如不需要认证的数据为:0x05 0x00 //用户名密码认证:0x05 0x02VER: 同客户端METHOD: 服务端在客户端支持的METHODS中选择一个认证方式回复客户端, 如0x无需认证、0x02用户名密码等

二、认证(无密码模式跳过此步骤,本文只有用户名密码认证)

客户端发送:

// +----+------+----------+------+----------+ // |VER | ULEN |UNAME | PLEN |PASSWD| // +----+------+----------+------+----------+ // | 1|1 | 1 to 255 |1 | 1 to 255 | // +----+------+----------+------+----------+VER: 固定0x05ULEN: UNAME的长度UNAME:用户名,变长PLEN:PASSWD 长度PASSWD:密码, 变长

服务端答复:

//+----+--------+ //|VER | STATUS | //+----+--------+ //| 1| 1| //+----+--------+VER: 固定0x05STATUS: 0x00认证成功,其他失败。如果发送失败,服务端应主动关闭连接。

注意:我看到有网络上有文章介绍此处时,说STATUS大于0表示失败,但是我看了规范原文之后,注意到其实说的时不等于0就失败。

三、握手

客户端发送

// +----+-----+-------+------+----------+----------+ // |VER | CMD |RSV| ATYP | DST.ADDR | DST.PORT | // +----+-----+-------+------+----------+----------+ // | 1|1| X00 |1 | Variable |2 | // +----+-----+-------+------+----------+----------+VER:0x05CMD:指令,后面有解释RSV:保留字段,1个字节,值为0ATYPE: 地址类型,即DST.ADDR类型,后面有解释DST.ADDR: 目标服务器地址,根据ATYPE不同而不同,内容分别为:in_addr/长度+域名/in6_addr,看后面ATYPE解释DST.PORT: 目标服务器端口。理所当然是网络字节序

CMD值如下:

0x01 CONNECT 连接目标服务器。(后面手撕代码, 用此模式,也是最常见的TCP模式)0x02 BIND 绑定,客户端会接收来自代理服务器的链接,FTP被动模式0x03 UDP ASSOCIATE UDP中

ATYPE值如下:

0x01 IPv4地址,DST.ADDR内容为in_addr0x02 没有这个类型,别问我为什么,我也想知道^_^0x03 域名地址,DST.ADDR第1个字节(假设为n)为域名长度,后面有n字节长度域名地址。也即是DST.ADDR的实际长度为1+n0x04 IPv6地址, DST.ADDR内容为in6_addr

服务端答复

//+----+-----+-------+------+----------+----------+ //|VER | REP |RSV| ATYP | BND.ADDR | BND.PORT | //+----+-----+-------+------+----------+----------+ //| 1|1| X00 |1 | Variable |2| //+----+-----+-------+------+----------+----------+VER:0x05REP:答复操作, 后面解释RSV:保留1字节, 0x00ATYPE/BND.ADDR/BND.PORT : 分别对应客户端请求的ATYPE、DST.ADDR、DST.POR

REP值内容如下:

0x00 目标连接成功0x01 代理服务器故障0x02 代理服务器规则集不允许连接0x03 网络无法访问0x04 目标服务器无法访问(主机名无效)0x05 连接目标服务器被拒绝0x06 TTL已过期0x07 不支持的命令0x08 不支持的目标服务器地址类型0x09 - 0xFF 未分配

四、通信

如果握手返回REP为0x00,即可正常进入通信模式。用户发什么,代理服务器就将其转发给目标服务器;目标服务器回什么,代理服务器就将其回给用户。