穿透Socks5 代理的UDP编程
2003-01-31· · ··天极论坛
1 2 下一页
网络编程中,对于数据传输实时性要求较高的场合,大家都会选择UDP来作为数据传输协议,在TCP/IP协议族中UDP协议较TCP协议需要的网络系统资源更少。然而在企业应用中,由于网络安全原因等会导致除了特定端口以外的IP数据无法通过专用的路由或网关。为了支持这类应用,制定了专门的支持Socks连接的socks4/socsk5协议。Socks协议允许实现此类功能的代理软件可以允许防火墙(本文以下内容中防火墙与代理的称谓可以等同视之)以内的客户通过防火墙实现对外部的访问,甚至可以允许等待外部的连接。对于防火墙内部的软件客户端,仅同防火墙协商,同防火墙的特定端口取得联系,然后交换数据,而防火墙外部的程序也直同防火墙进行数据交换,外部看不到防火墙的内部网情况,这样起到了防火墙的监护功能,也满足了大多数通过非常用(如http ftp等)端口交换数据的应用程序需求。防火墙内部的应用程序如何通过防火墙将UDP数据传输到防火墙外部,并且接受外部的UDP数据报文,这就是所谓穿透Socks代理的UDP编程。
RFC1928描述了Socks协议的细节,告诉我们客户程序如何同Socks代理协商,取得透过该协议对外传输的途径。英文的URL为:http://www.ietf.org/rfc/rfc1928.txt,中文的翻译参考不是很贴切(但译者还是值得尊敬的),但对于E文不大好的可以将就一下:http://www.china-pub.com/computers/emook/0541/info.htm。建议先了解以上链接内容后在阅读下文。
一般的代理软件都实现了两个版本的Socks协议—Socks4以及Socks5,其中Socks5协议支持UDP报文的传输以及多种验证方法,该协议还考虑IP发展需要,支持Ipv6。
TCP透过代理支持两种方法:Bind以及Connection。Connection是指作为客户端,主动连接代理外部的服务程序,在这种方式中代理将替代客户程序发起真正的对外部服务程序的连接,并来回传输在此连接中需要交流的数据;Bind方式则用在那些需要客户机接受到服务器连接的协议中,例如FTP协议之类的除了需要建立一个客户--服务器的连接报告状态外,还需要建立一个服务器—客户的连接来传输实际的数据(当然要注意这里的FTP协议通过Socks协议连接远程主机,并非通过FTP代理协议)。UDP报文传输则意味着代理充当UDP数据传输的中间人,将防火墙内的主机对外的数据传递出去,将需要引入到防火墙内的UDP数据报文转给防火墙特定的主机。关于TCP穿透的讨论和例子很多(给出一个实现的例子:http://www.codeproject.com/internet/casyncproxysocket.asp ),就不多讲了,在此着重讨论如何实现UDP数据的穿透Socks5代理。
为了测试方便我简单写了一个服务进程在代理外IP为192。168。0。250上监听UDP8100端口,接收到一个UDP的数据报后,返回服务器上的当前时间给发送UDP报文的客户端。代理采用Wingate,他在192。168。0。1上运行,Socks的标准端口1080来运行服务监听程序。我的机器为192。168。0。10,你可以看到,我不能够直接联系运行时间服务的机器,我会向代理提出我的要求,由代理进程负责UDP数据报文的转发。代理软件选择Wingate,并且为了简单起见,采用不需要验证客户的验证方法。好了,交代了背景后,下面我们就开始穿越代理的旅程吧。
无论是TCP还是UDP通过代理,首先要同代理取得联系。为了能够确保在第一阶段顺利确保数据传输,协议规定客户端采用TCP方式连接联系代理服务器。
一旦客户同代理的1080端口连接上,客户首先要发送一个版本标识/方法选择的TCP报文给代理服务器,具体格式为:
版本号(1字节) | 可供选择的认证方法(1字节) | 方法序列(1-255个字节长度)
如果是socks4协议,版本号就是0x04,但是这里是支持UDP的Socks5,所以是字节0x05。此说明对于后面的报文格式解释的版本部分也都适用。
Socks协议定义了0-255种通过代理的认证方法:
0x00 无验证需求
0x01 通用安全服务应用程序接口(GSSAPI)
0x02 用户名/密码(USERNAME/PASSWORD)
0x03 至 X'7F' IANA 分配(IANA ASSIGNED)
0x80 至 X'FE' 私人方法保留(RESERVED FOR PRIVATE METHODS)
0xFF 无可接受方法(NO ACCEPTABLE METHODS)
显然,无论是发起Socks请求的客户端还是负责转发Socks数据的代理都不可能完全实现所有的(起码目前还没有)方法,所以客户端需要把自己能够支持的方法列出来供代理服务器选择。如果支持无验证,那么此报文的字节序列就为:0x05 0x01 0x00,其中的0x01表示客户端只支持一种验证,0x00表示能够支持的方法是编号为0x00的(无验证)的方法。如果客户端还支持用户名/密码的验证方式,那么报文就应当是:0x05 0x02 0x00 0x02。
代理接收到客户的请求,会根据自身系统的实现返回告诉客户验证采用哪一种方法,返回的保文格式为: