本文由TZWSOHO通过收集网络资料整理而成(百度百科和英文维基百科),文中某些地方可能由于笔者本人技术水平有限而造成翻译上甚至是个人理解上的错漏,欢迎路过本文的各路英雄斧正。另若有需要转载时请高抬贵手标明出处,万分感谢!
SOCKS v4代理服务器由于用户验证机制没有v5版完善现已不多见,但其实现原理与v5版有很多类似之处,且较v5版为简单,估作为知识点的引导在此先作介绍。而v4a版只对v4版增加了域名解析的功能,其他功能不变,故在此一并讲述。
SOCKS v4/v4a定义了两种操作:CONNECT和BIND。
1.CONNECT
当一台内网计算机(客户端)意图连接外网的一台计算机时,客户端首先会发送一个CONNECT请求数据包到代理服务器,通过此请求代理服务器将与外网计算机建立连接,若代理服务器与指定的外网计算机的连接建立成功,则之后客户端与该外网计算机的通讯便完全通过代理服务器作为数据交换的媒介。v4版的CONNECT请求数据包的格式如下:
字段名
VN
CD
DSTPORT
DSTIP
User ID
NULL
字段
默认值
4
1
外网计算机通讯端口
外网计算机IP
用户ID
0
字段长度(字节)
1
1
2
4
可变
1
VN是SOCKS的版本,此字段值为4.
CD为操作类型标识,CONNECT操作定义为1,BIND操作定义为2.
DSTPORT为目标计算机的通讯TCP端口(网络字节顺序)。
DSTIP为目标计算机的IP地址(网络字节顺序)。
USERID为客户端登录用户名,长度可变。
数据包最后以NULL字段(1字节,值为0)结束。
代理服务器接收到此数据包后,将尝试根据数据包的DSTIP和DSTPORT与目标计算机进行连接,然后根据连接的结果回复一个数据包给客户端。此回复数据包的格式如下:
字段名
VN
CD
DSTPORT
DSTIP
字段默认值
0
连接状态
目标主机端口
目标主机IP
字段长度(字节)
1
1
2
4
VN是返回代码的版本,此字段值为0。
CD是连接状态的编码,具体意义如下:
l 90,请求得到允许;
l 91,请求被拒绝或失败;
l 92,由于SOCKS服务器无法连接到客户端的identd(一个验证身份的进程)或无法连接到目标主机,请求被拒绝;
l 93,由于客户端程序与identd报告的用户身份不同,连接被拒绝。
DSTPORT与DSTIP与请求包中的内容相同,但被忽略。
若请求被拒绝或失败,则代理服务器将立即关闭与客户端的通讯连接。若请求成功,则代理服务器就充当客户端与目的主机之间进行双向传递,对客户端而言,就如同直接在与目的主机相连。
2.BIND
当客户端意图接收外部传入的连接时,将会发送一个BIND请求数据包至代理服务器,通过代理服务器建立指定的监听端口来监听外部连接。BIND请求数据包的格式与CONNECT请求数据包格式一样,不同的是CD字段的值为2。
下面举例说明一台identd为Fred的客户端主机尝试通过代理服务器连接到66.102.7.99:80,且连接成功建立的过程中双方发送的数据包:
客户端:0x04 | 0x01 | 0x00 0x50 | 0x42 0x66 0x07 0x63 | 0x46 0x72 0x65 0x64 | 0x00
代理服务器:0x00 | 0x5a | 0x00 0x50 | 0x42 0x66 0x07 0x63
其中0x46 0x72 0x65 0x64为字符串Fred的ASCII码。
SOCKS v4a是对v4的简单扩展,专门对于客户端无法解析某个域名而设,其请求数据包的格式如下:
字段名
VN
CD
DSTPORT
DSTIP
User ID
NULL
HOST
NULL
字段值
4
1或2
目标主机端口
0.0.0.x
用户ID
0
目标主机
0
字段长度(字节)
1
1
2
4
可变
1
可变
1
若代理服务器读取到DSTIP的前三字节为0且第四字节非零(即IP为0.0.0.x,此IP在实际应用中是不存在的),则代理服务器需要读取HOST字段并且解析域名,最后与解析得到的IP尝试建立连接。请求数据包中的其他字段意义与v4版本一样。
代理服务器回复客户端的数据包格式与v4版本一样。