基于SS5服务端的Socks5客户端
SS5停止更新已经好几年了,用作socks5代理的服务端还是比较稳定的。但是如果要使用加密账号和密码的协议,有些坑需要去填。
1、服务端的账号密码验证方式配置为“s”时,客户端进行协议验证时,需要用“0x21”,此时服务端会提醒不存在该协议或者错误的请求。是因为服务端的代码有问题。
在服务端SS5Mod_socks5.c文件的unsigned char GetMethod(struct _SS5ClientInfo *ci )函数中,有一段判断协议的代码是这样的
do { if( (node->SrcAddr == n_sa) && (node->Mask == nm) && (sp >= node->SrcRangeMin) && (sp <= node->SrcRangeMax) ) { if( ((node->Method == NOAUTH) && ci->NoAuth) || (((node->Method == USRPWD) || (node->Method2 == FAKEPWD)) && ci->BasicAuth) ||((node->Method == GSSAPI) && ci->GssApiAuth) ) return node->Method; if( ((node->Method2 == NOAUTH) && ci->NoAuth) || (((node->Method2 == USRPWD) || (node->Method2 == FAKEPWD)) && ci->BasicAuth) || ((node->Method2 == GSSAPI) && ci->GssApiAuth) ) return node->Method2; }
if判断时,把账号密码加密模式给丢了,其实要在里边加上 ((node->Method == S_USER_PWD) && ci->SecureBasicAuth)。
2、开发者写在“draft-supa.txt”里的《Socks 5 Secure User-Name and Password authentication protocol》,其实是有问题的。
比如发送密码交换协议时,作者是这样写的:
Now can start the Key Exchange process based of Diffie-Hellman procedure:
Client send a packet with "P", "G" and "A" to the server:
+-----+-----+----+-----+
| STAT| P | G | A |
+-----+----+-----+-----+ STAT:
| 1 | 4 | 4 | 4 | 0x1: Request Key
+-----+-----+----+-----+
服务端验证时,其实是这样的:
+-----+-----+----+-----+-----+----+-----+
| STAT| Plen| P |Glen | G |Alen| A |
+-----+----+-----+-----+----+-----+-----+ STAT:
| 1 | 4 | 4 | 4 | 4 | 4 | 4 | 0x1: Request Key
+-----+-----+----+-----+-----+----+-----+
3、作者在说明文档中说使用的是3des_cbc模式,但是在代码中使用的是3des_cbcm模式,而且未说明密钥的使用方式。实际密钥使用方式为:
ks1:密钥1;(为16字节密钥的左边8字节)
ks2:密钥2;(为16字节密钥的右边8字节)
ks3:密钥3;(为16字节密钥的左边8字节)
随机加密串iv使用0填充 memset(iv2,'\0',sizeof iv2);
需要注意的地方主要就是上边这些了。如果客户端使用其他加密库时(如cryptpp),需要留意与openssl之间的兼容性,所以客户端尽可能的也是用openssl。总之感觉作者没经过测试,就把程序放出来了,贻害无穷啊。