前言:
Angel有1w个socks5代理的账号,要验证哪些还能用,哪些不能用,然后就有了这个工具.
在网上查了下相关的工具,基本上都是用curl设置代理,接着去请求一个公网上的一个脚本.也就是说你要批量验证,就得还有一个服务器.成本有些大.
于是就有了现在这篇文章和下面的这个工具了.
项目地址 https://coding.net/u/medicean/p/socks5validate/git
思路:
先说下我们验证的思路吧,就是把用户名和密码发送给server,然后根据返回的报文来看有没有验证成功.这个过程不需要第三方参与.
从协议开始:
老规矩,从协议开始.看协议的东西,RFC文档是最好的东西了.直接去查RFC文档了.
根据RFC1928文档: http://www.rfc-editor.org/rfc/rfc1928.txt
1.Client to Server
Client连接到Server,并发送一个版本,客户端支持的认证方式的一个报文,让服务器选择,格式如下:1
2
3
4
5+----+----------+----------+
|VER | NMETHODS | METHODS |
+----+----------+----------+
| 1 | 1 | 1 to 255 |
+----+----------+----------+
VER : socks协议版本号,这里就是x05.
NMETHODS: Client支持的认证的方式个数,我们本次只对用户名密码这种方式进行认证,所以个数就是x01
METHODS:认证方法.
下面是RFC文档中给出的已经有的取值
1 | The values currently defined for METHOD are: |
于是我们这里就取x02就好.
so,可以想到第一步的payload就是:payload1='\\x05\\x01\\x02'
2.Server To Client
Server在接收到Client的请求之后,Server会从Client支持的验证方式中选择一个合适的验证方法,告诉Client.格式如下:
1 | +----+--------+ |
很简单的报文.就不分析了.
3.Client to Server
Client在收到Server返回的报文之后,提供相应的凭据给Server. RFC1929 是socks5用户名密码认证方式的说明.
客户端发送的报文格式如下:1
2
3
4
5+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
VER:版本号
ULEN:用户名的长度
UNAME:用户名
PLEN:密码长度
PASSWD:密码
图中的数字代表该字段的字节数.
所以我们就可以构造第二步的payload了.
1 | username='test' |
4.Server to Client
Client提供认证凭据给Server,Server返回认证结果.
报文格式也是简单粗暴:1
2
3
4
5+----+--------+
|VER | STATUS |
+----+--------+
| 1 | 1 |
+----+--------+
VER:版本号
STATUS:状态.
状态这里,如果认证成功就是x00 如果不成功,返回的就不是\\x00
值得注意的是,VER 包含了子版本号,所以会出现返回
\\x05\\x00
和\\x01\\x00
这种情况,我之前的代码就没考虑到这些
编码实现
分析到这里,已经可以编码了.代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36debug=False
def validate(host,port,username,password):
try:
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
socket.setdefaulttimeout(20)
s.connect((host,port))
payload1='\\x05\\x01\\x02'#socks 5 版本1 02采用用户名密码验证
s.send(payload1)
data1=s.recv(1024)
if data1!='\\x05\\x02': # Server response 05 02 use username/password validate
if debug:
print "Don't support user/pass auth"
s.close()
return False
#send validate data
#version len(username) username len(password) password
payload2=struct.pack('!BB'+str(len(username))+'sB'+str(len(password))+'s',1,len(username),username,len(password),password)
s.send(payload2)
data2=s.recv(1024)
if data2[1] =='\\x00': #success
if debug:
print 'username:%stPassword:%s---Success!'%(username,password)
Flag=True
else:
if debug:
print 'Auth Fail!'
Flag=False
s.close()
except:
if debug:
print 'validate host:%s with %s/%s occurred some exception.'
Flag=False
if s:
s.close()
return Flag
这样只是对一个主机进行认证,要做到批量,就写个for,加个外壳就好了,这里就不说这些了.要爆破什么的,都是在这个基础上搞了…
最后再贴上源码地址: https://coding.net/u/medicean/p/socks5validate/git