本文由TZWSOHO通过收集网络资料整理而成(百度百科和英文维基百科),文中某些地方可能由于笔者本人技术水平有限而造成翻译上甚至是个人理解上的错漏,欢迎路过本文的各路英雄斧正。另若有需要转载时请高抬贵手标明出处,万分感谢!
SOCKS v5的原理与SOCKS v4/v4a的原理大致相同,但增加了对UDP协议的支持、安全验证机制及IPv6的支持。客户端通过SOCKS v5代理服务器与外部建立连接的流程如下:
1、 客户端尝试连接代理服务器;
2、 客户端选择一种认证的方法,并发送认证信息的方法代码至代理服务器;
3、 若代理服务器不接受此认证方法,则拒绝客户端的请求;
4、 若代理服务器接受了此认证方法,则客户端可根据方法的规定与代理服务器进行一些信息通讯,如发送用户名及密码等;
5、 认证成功后,客户端将发送一个类似于SOCKS v4的请求数据包给代理服务器;
6、 代理服务器发送一个类似于SOCKS v4规定的回复数据包给客户端;
7、 若以上操作均成功进行,则此时客户端可以与目标主机通过代理服务器进行相互通讯。
客户端认证请求数据包格式
字段名
VER
NMETHODS
认证方式1
……
认证方式n
字段值
5
认证方式数目n
0-254
0-254
0-254
字段大小
(字节)
1
1
1
1
1
代理服务器应答认证数据包格式
字段名
VER
代理接受的认证方式
字段值
5
0-254(或返回255代表不支持此认证方式)
字段大小(字节)
1
1
已定义的认证方式代号:
0x00:无验证
0x01:通过GSSAPI验证
0x02:通过常规的“用户名/密码”对验证
0x03-0x7F:通过IANA(互联网地址编码分配机构Internet Assigned Numbers Authority)进行验证
0x80-0xFE:可以由用户自行定义
0xFF:不接受的认证方式
其中目前的GSSAPI认证方法一般有以下几种:Kerberos,NTLM,Distributed Computing Environment (DCE),SESAME,SPKM,LIPKEY。
“用户名/密码”对认证数据包格式
字段名
VER
ULEN
USERNAME
PLEN
PASSWD
字段值
1
用户名长度
用户名
密码长度
密码
字段大小
(字节)
1
1
可变
1
可变
代理服务器应答“用户名/密码”对认证数据包格式
字段名
VER
STATUS
字段值
1
0 - 成功
非零 - 失败
字段大小(字节)
1
1
注意:若认证失败,则代理服务器应马上关闭与客户端的连接。
认证成功后,客户端可向代理服务器发送连接请求,格式大致与v4版一样,但v5版增加了UDP和IPv6的支持,并且支持域名解析。
客户端“CONNECT/BIND/UDP关联”请求数据包格式
字段名
VER
CMD
RSV
ATYP
DSTADDR
DSTPORT
字段值
5
1 - CONNECT
2 - BIND
3 - UDP关联
0(保留)
1 - IPv4
3 - 域名
4 - IPv6
IP/域名
通讯端口
字段大小(字节)
1
1
1
1
可变
2
注意:若DSTADDR为域名,则该字段的第一字节代表域名名称的长度,域名名称最后无NULL作为终止符。
代理服务器应答请求数据包格式
字段名
VER
REP
RSV
ATYP
BNDADDR
BNDPORT
字段值
5
应答代号
0(保留)
1 - IPv4
3 - 域名
4 - IPv6
绑定的
地址
绑定的
端口
字段大小(字节)
1
1
1
1
可变
2
其中REP字段的值及其表示意义如下(注:RFC英文原文及本人翻译):
0x00: succeeded 成功
0x01: general SOCKS server failure 常规SOCKS服务器失败
0x02: connection not allowed by ruleset 规则集不允许此连接
0x03: Network unreachable 网络不可达
0x04: Host unreachable 主机不可达
0x05: Connection refused 连接被拒绝
0x06: TTL expired TTL期限已失效
0x07: Command not supported 命令不支持
0x08: Address type not supported 地址类型不支持
0x09 - 0xFF unassigned 未定义
1、 CONNECT
在对一个CONNECT命令的应答中,BND.PORT包含了服务器分配的用来连到目标机的端口号,BND.ADDR则是相应的IP地址。由于SOCKS服务器通常有多个IP,应答中的BND.ADDR常和客户端连到SOCKS服务器的那个IP不同。
SOCKS服务器可以利用DST.ADDR和DST.PORT,以及客户端源地址和端口来对一个CONNECT请求进行分析。
2、 BIND
BIND请求通常被用在那些要求客户端接受来自服务器的连接的协议上。FTP是一个典型的例子。它建立一个从客户端到服务器端的连接来执行命令以及接收状态的报告,而使用另一个从服务器到客户端的连接来接收传输数据的要求(如LS,GET,PUT)。
建议只有在一个应用协议的客户端在使用CONNECT命令建立主连接后才可以使用BIND命令建立第二个连接。建议SOCKS服务器使用DST.ADDR和DST.PORT来评价BIND请求。
在一个BIND请求的操作过程中,SOCKS服务器要发送两个应答给客户端。当服务器建立并绑定一个新的套接口时发送第一个应答。BND.PORT字段包含SOCKS服务器用来监听进入的连接的端口号,BAND.ADDR字段包含了对应的IP地址。客户端通常使用这些信息来告诉(通过主连接或控制连接)应用服务器连接的汇接点。第二个应答仅发生在所期望到来的连接成功或失败之后。在第二个应答中,BND.PORT和BND.ADDR字段包含了连上来的主机的IP地址和端口号。
3、 UDP关联
UDP 关联请求通常是要求建立一个UDP转发进程来控制到来的UDP数据报。DST.ADDR和DST.PORT字段包含客户端所希望的用来发送UDP数据报的IP地址和端口号。服务器可以使用这个信息来限制进入的连接。如果客户端在发送这个请求时没有地址和端口信息,客户端必须用全0来填充。
当与UDP相应的TCP连接中断时,该UDP连接也必须中断。
应答UDP 关联请求时,BND.PORT和BND.ADDR字段指明了客户发送UDP消息至服务器的端口和地址。
4、 应答处理
当一个应答(REP值不等于00)指明出错时,SOCKS服务器必须在发送完应答消息后一小段时间内终止TCP连接。这段时间应该在发现错误后少于10秒。
如果一个应答(REP值等于00)指明成功,并且请求是一个BIND或CONNECT时,客户端就可以开始发送数据了。如果协商的认证方法中有以完整性、认证和/或安全性为目的的封装,这些请求必须按照该方法所定义的方式进行封装。类似的,当以客户机为目的地的数据到达SOCKS服务器时,SOCKS服务器必须用正在使用的方法对这些数据进行封装。