早上,逛园子时看到breeze写了一篇Socks5代理协议的文章《C# 实现Socket5代理协议通讯 》,并在评论里看到howaaa说“顺便也讲讲用C#实现一个Socks5代理服务器吧,这方面资料很少,相信很有价值”,于是一时兴起,花了一个下午的时间捣鼓出Socks5代理的服务端程序。程序很简单(只要弄懂了Socks5协议就基本明白了)、代码很零乱。有兴趣的可以看看,没兴趣的就飘过吧,嘿嘿....
在breeze的文章中少了一个密码身份验证的讲解,在这里我补一下。
============================================================================================
当客户端与Socks5代理服务器连接上并进行握手时,客户端将会发送以下格式的握手报文:
版本号(1字节) | 认证方法数(1字节) | 认证方法序列(1-255个字节长度)
比如报文(假如为V5版本):
0x05 0x01 0x00 则表示客户端只支持一种(0x1)认证方法0x00 (无验证需求)
0x05 0x01 0x02 则表示客户端只支持一种(0x01)认证方法0x02(用户名/密码 验证)
0x05 0x02 0x00 0x02 则表示客户端支持两种(0x02)认证方法“0x00与0x02”
其中Socks5协议定义了以下几种认证方法:
0x00 无验证需求
0x01 通用安全服务应用程序接口(GSSAPI)
0x02 用户名/密码(USERNAME/PASSWORD)
0x03 至 X'7F' IANA 分配(IANA ASSIGNED)
0x80 至 X'FE' 私人方法保留(RESERVED FOR PRIVATE METHODS)
0xFF 无可接受方法(NO ACCEPTABLE METHODS)
在这里,我们要详解了解的则是“0x02 用户名/密码”验证的过程。
当客户端发送带有0x02认证方法的报文(如:“0x05 0x01 0x02”)到服务端时,根据报文,服务端得知客户端支持用户名/密码认证(0x02),因此如果服务端需要验证,则发送“0x05 0x02”应答,这样客户端将会进入“用户名/密码”验证过程。
“0x02 用户名/密码”验证协议的报文格式是:
0x01 | 用户名长度(1字节)| 用户名(长度根据用户名长度域指定) | 口令长度(1字节) | 口令(长度由口令长度域指定)
所以报文的长度是根据用户名与密码的长度而定,比如以下报文:
0x01 0x02 0x41 0x42 0x02 0x43 0x43
则表示发送用户名为“AB”密码为“CC”的验证报文。
服务端接收到用户名/密码验证报文后进行相应处理并返回以下格式的应答报文:
0x01 | 验证结果标志
如果验证通过则“验证结果标志”的值为“0x00”,否则其它值都表示验证失败!不允许再进行下一步的操作。
当握手与身份验证过程都通过后,将进入“连接请求”过程,在这步中服务端应该需要对客户端发送过来的远程服务端地址进行连接状态检查的,但在我这个程序中,我偷了懒没做,简单的就去后面的“连接”会话过程了,嘿嘿。
源代码下载:
https://files.cnblogs.com/kingthy/Socks5Server.rar
此程序用QQ与迅雷测试过,基本都能正常运行。。。