bindog study Machine Learning & Security

ShadowSocks免费账号获取&测试工具

2014-09-06
宾狗

0x00 前言

PS:本文获取的账号全部来自ShadowSocks公益组织,套用他们官网的话,再次感谢那些无私奉献ShadowSocks帐号的人!

对实现细节不感兴趣的朋友可以直接拖到最后,有下载链接~

关于ShadowSocks这里不再多说了,用途很多,比如科学上网=。=如果你没有用过的话,推荐你看看ShadowSocks—科学上网之瑞士军刀,里面说的非常详细。当然,说来说去账号是关键,要么是你自己搭一个服务器,自己设定端口、密码和加密方式等等,要么就使用一些别人共享的免费账号,比如可以去ShadowSocks公益组织这个网站上去找一些账号。

无奈的是,由于各种各样的原因,其中很大一部分账号是不能用的,而且网站上给出参考的可用率也不太靠谱,所以最稳妥的办法是自己一个一个试。但是!这些账号信息不是直接写在网页上的,有两种获取方式。一种是通过二维码获得,解码出来是Base64,还要进行一次解码,这种方式主要是方便手机用户使用ShadowSocks的APP。另一种方式是填上你的邮箱和一个验证码,系统会自动给你的邮箱发一封邮件,里面包含了配置信息。

一句话概括,获取一个账号很麻烦,还要不停的复制粘贴,最后发现这个账号是不能用的……我常常花上半个小时还找不着一个可用的账号=。=

于是乎,我写了这么一个小工具,一开始写了个Java版的,主要使用了HTTPClient,也遇到了许多问题(如HTTPClient怎样使用SOCKS代理、HTTPS忽略证书等等),如果大家感兴趣的话,可以在底下留言~

由于最近正在学习Python,所以后来又写了一个Python版的,果然Python是挺方便的,代码量可能还不到Java版的十分之一。不过由于我也是初学者,代码也写的比较渣,大神请无视

好了,废话不多说了,我们来看看怎么来写这么一个小工具

0x01 步骤

整体思路其实很简单~

  1. 获取网站上所有的二维码
  2. 解析二维码获得账号信息
  3. 配置账号信息并测试延迟
  4. 把可用的账号输出到文件

获取网站上所有的二维码

#下载文件
def downloadfile(url, filename):
    print("downloading " + url + "...")
    data = urllib2.urlopen(url)
    with open(filename, "wb") as img:
        img.write(data.read())
    print("done")
#下载shadowsocks.net网页中所有二维码
def downloadallqrcode():
    s = urllib2.urlopen("https://www.shadowsocks.net/get").read()
    pattern = re.compile(r"window.open\('media/qr/(.*?)'")  #正则表达式匹配
    it = re.finditer(pattern, s)
    qrlist = []
    for match in it:
        qrlist.append(match.group(1))
    qrprefix = r"https://www.shadowsocks.net/media/qr/"
    for qrname in qrlist:
        downloadfile(qrprefix + qrname, "qrcode/"+qrname)

这个没什么好说的,就是正则表达式匹配

解析二维码获得账号信息

#把所有二维码解析为JSON格式的字符串
def parseallqrcode():
    filelist = os.listdir("qrcode")
    sslist = []
    for filename in filelist:
        #使用zbar这个命令行工具解析二维码
        cmd = ["zbar/zbarimg.exe","-D","qrcode/"+filename]
        #使用subprocess~可以获取控制台输出
        output = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE).communicate()[0]
        print filename+"-->"+output.rstrip()
        index = output.find("ss://")
        if index != -1:
            ss64 = output[index+5:].rstrip()
            #base64解码
            missing_padding = 4 - len(ss64) % 4
            if missing_padding:
                ss64 += b'='* missing_padding
            ss = base64.decodestring(ss64)
            print ss
            #分割字符串 获取配置信息
            pattern = re.compile(r"(?P<method>.*?):(?P<password>.*?)@(?P<ip>((?:(2[0-4]\d)|(25[0-5])|([01]?\d\d?))\.){3}(?:(2[0-4]\d)|(255[0-5])|([01]?\d\d?))):(?P<port>.*)")
            match = re.match(pattern, ss.replace(" ",""))
            if match:
                smethod = match.group("method")
                spassword = match.group("password")
                sserver = match.group("ip")
                sserver_port = match.group("port")
                #转换成JSON格式字符串
                d = dict(server=sserver,server_port=int(sserver_port),password=spassword,method=smethod,local_port=1080,timeout=600)            
                jsonstring = json.dumps(d)
                print jsonstring
                sslist.append(jsonstring)
    return sslist

这里我将所有二维码下载到qrcode这个文件夹中,Python中有许多二维码生成的库,但是二维码解析的库很少而且安装起来都比较麻烦。所以有两种偷懒的办法,一种是使用在线的API服务,国外有一个叫QR code API,国内有草料API,不过我都没用过=。=另一种办法就是我这里用的了,使用现成的命令行工具~

值得注意的是Pythonsubprocess的用法,具体来说就是怎么获取控制台输出,这些在代码中都有,也不多说了

随后的过程就是Base64解码以及转换成JSON了,至于为什么要转换成JSON往下看就知道了

配置账号信息并测试延迟

账号什么的都有了,下面就差测试延迟了

#测试某个访问某个url的延迟 默认最大为5s
def getlatency(url):
    print ("test the latency of "+url+"...")
    start = time.time()
    try:
        r = urllib2.urlopen(url,timeout=5)
    except:
        print ("this socks proxy may be invalid")
        return 5
    end = time.time()
    print r.read()
    latency = end - start
    print ("the latency of "+url+" is "+str(latency))
    return latency
#获取平均延迟 一般>=5s就可以认为这个代理无效
def getaveragelatency():
    urls=["https://www.google.com","https://twitter.com"]
    latencysum = 0
    for url in urls:
        latencysum += getlatency(url)
    averagelatency = latencysum/len(urls)
    print("the average latency is "+str(averagelatency))
    return averagelatency
#获取可用代理 并加上它们的延迟信息
def getavailableproxy():
    sslist = parseallqrcode()
    availables = []
    for ss in sslist:
        print "Testing "+ss+"..."
        #设置config.json文件
        f = open("shadowsocks/config.json","w")
        f.write(ss)
        f.close()
        #启动shadowsocks代理程序
        cmd = ["shadowsocks/shadowsocks-local.exe","-c","shadowsocks/config.json"]
        p = subprocess.Popen(cmd)
        time.sleep(0.5)
        a = getaveragelatency()
        #平均延迟小于5s则认为该代理有效 并加上延迟信息
        if a < 5:
            availables.append("latency:"+str(a)+"--->"+ss)
        p.kill()
        time.sleep(0.5)
    return availables

这里我测试的是平均延迟,这样结果可靠一点,测试的是GoogleTwitter,都是被墙的=。=

ShadowsSocks的客户端程序多种多样,毕竟人家是开源的嘛~程序中用到的是比较简单的一种,就是一个控制台程序shadowsocks-local.exe,会自动寻找当前目录下的config.json文件(知道为啥要转换成JSON了吧),也可以通过-c参数指定配置文件

最后,输出到文件就不列代码了,具体可以参考完整代码

0x02 urllib2使用socks代理

刚才说了说整体流程,但是还有一个很重要的环节没有涉及到,那就是程序中如何使用socks代理,这可不是启动了shadowsocks-local.exe就行了,毕竟不是VPN=。=

Google了一下发现了如下解决方案,使用SocksiPy这个模块就可以了~

import socks
import socket
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 1080)
socket.socket = socks.socksocket
import urllib2
print urllib2.urlopen('http://www.test.com').read()

可是后来我发现,访问TwitterFackbook这样的网站时程序依然会报错(即使是使用经测试可用的账号),同时访问国内的网站是没有问题的,显然矛头又指向了可爱的GFW

后来在Stack Overflow上找到了答案,httplib.HTTPConnection会使用socket模块中的create_connection函数来建立socket连接。但是在建立socket连接之前,这个函数是通过普通的getaddrinfo来进行DNS查询的……

好吧,果然是我们可爱的GFW,它有一个非常IMBA的技能叫作DNS污染,也就是说如果你不使用特殊渠道进行DNS解析的话,它会把TwitterFackebook的IP地址解析到火星上去,程序不报错才怪呢=。=

怎么办呢,也很简单,我们自己实现一个create_connection函数,然后PATCH到socket模块里面就可以了

import socks
import socket
def create_connection(address, timeout=None, source_address=None):
    sock = socks.socksocket()
    sock.connect(address)
    return sock
socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, "127.0.0.1", 1080)
socket.socket = socks.socksocket
socket.create_connection = create_connection

其实也没有多复杂啦,只不过把原来的sock替换为我们导入的模块中的socks.socksocket(),让它来接管DNS查询、连接等后续操作,最后返回可用的socket就可以了

0x03 资源下载

最后就是发福利了~

说明

  1. 源码中运行SSAccount.py即可,此外我用PyInstaller将程序打包成了一个exe工具,方便没有安装Python的小伙伴
  2. zbarshadowsocks文件夹中存放的是文中提到的两个命令行工具
  3. 程序执行完成后会生成一个available.txt,里面有可用账号和延迟信息
  4. 你可以把可用账号信息复制到config.json中,运行shadowsocks-local.exe来上网,当然也可以使用Shadowsocks GUI这种带界面的客户端
  5. 具体怎么配置浏览器使用ShadowSocks上网请参考ShadowSocks—科学上网之瑞士军刀

##下载地址


Comments