前言
在进行渗透测试、漏洞挖掘的时候,使用自动化工具是必须的一步,但是令人😠的是,经常由于扫描等原因导致IP被ban,这是我们最不想看到的。所以本着学习编程的目的,根据网上搜索的资料,东拼西凑的开发了这个系统。
0x01 涉及技术
Python3
使用Python3的原因是由于异步IO使用的是
asyncio
和aiohttp
,所以就学习尝试了下Python3,其实没多大区别感觉。(刚开始学编程,原谅我啥都不知道😜)Flask
使用Flask作为Web开发微框架,交与其他Python框架,具有简便、易扩展等优点。具体可看:Flask中文文档
Redis
Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。
五种类型数据类型为:字符串、列表、集合、有序集合、散列表。本次数据存储方面就利用的redis的有序集合。
爬虫
爬虫部分是从11个免费代理网站上抓取免费、高可用性的代理IP,并进行数据处理获取统一格式。同时本着学习的理念使用了:
lxml
,pyquery
,正则
,json
等不同的技术来实现。异步IO
默认给代理池设置的阈值为50000,由于数量比较大,为了提高代理高可用性的检测效率,我们在这里使用异步请求库aiohttp来进行检测。具体参考:廖雪峰的官方网站-异步IO
前端
web前端部分我是真不懂(但是我会抄啊😝),直接wget的一个自己觉得比较简洁的网站的前端,哈哈😄~
0x02 架构部分
主要分为如下几个模块:
爬虫模块:
主要从11个免费代理网站上抓取免费的代理IP,并进行格式统一处理。同时为了保证代理池的枯竭,采用周期性抓取。
1234567891011www.66ip.cnwww.xdaili.cnwww.kuaidailiwww.ip3366.netwww.89ip.cnwww.xicidaili.comwww.iphai.compremproxy.comwww.xroxy.comwww.data5u.comwww.kxdaili.com存储模块
主要学习了GitHub上一个采用的redis的有序集合来进行的,一是保证代理数据的不重复,二是使用
zscore
来标记代理的可用性。检测模块
定时检测数据库中的代理的可用性情况,并采用打分机制,初始化一个分值,若可用则标记为最高,不可用则在初始化分值基础上减1,直到为0,则从redis中删除。后续random获取的时候采用分值最高的优先展示的从高到低模式。同时保证代理的实时可用性,设置定时检测。
API模块
采用
Flask
作为web服务器,前端copy的别人的改的。从redis数据库中优先选择出分数最高的,若同时存在多个,则随机选择一个。
0x03 具体实现
爬虫模块
|
|
本着学习的目的,同时采用了pyquery
,正则
,json
,xpath
等不同的获取方法,使用yield
来将这些方法定义成生成器,这样我们每次请求就会通过yield
来返回一个代理IP。
同时使用crawl_
开头的函数命名方法,来达到动态添加代理网站地址接口的目的(这部分借鉴的大神的),具体参考:python元类解析
|
|
定义类ProxyMetaclass并声明一个__new__
方法,同时Crawler类将它声明为元类,这个方法有固定的几个参数cls, name, bases, attrs
,第四个参数attrs
中包含了类的一些属性。我们可以遍历attrs
这个参数即可获取类的所有方法信息,就像遍历字典一样,键名对应方法的名称。然后判断方法的开头是否crawl_
,如果是,则将其加入到__CrawlFunc__
属性中。这样我们就成功将所有以crawl_
开头的方法定义成了一个属性,动态获取到所有以crawl_
开头的方法列表。
然后定义了一个get_proxies()
方法,将所有以crawl_
开头的方法调用一遍,获取每个方法返回的代理并组合成列表形式返回。
存储模块
采用redis的有序集合,集合的特点是集合的每一个元素都是不重复的,这样就保证了代理的不重复。有序集合,顾名思义,这里存储的数据是有序的,我们就可以利用这点对代理IP进行打分、排序,实现权重的效果。具体可参考:Redis 有序集合(sorted set)
连接redis
|
|
添加数据,添加代理,设置分数为最高
|
|
获取代理IP,随机获取有效代理,首先尝试获取最高分数代理,如果不存在,按照排名获取,否则异常
|
|
删除代理IP,代理值减一分,小于最小值则删除
|
|
检测模块
代理检测第一次可用,则分数设置为100,代理不可用,分数减1,这样就可以实时改变每个代理的可用情况。API接口返回的时候只需要获取分数高的代理即可。使用的python3的异步IO库aiohttp
,参考的大神的表演,学习了。
|
|
定义了一个类Tester
,接下来定义了一个test_single_proxy()
方法,并在前面加了async
关键词,这代表这个方法是异步的。方法内部首先创建了aiohttp的ClientSession
对象,此对象类似于requests的Session
对象,可以直接调用该对象的get()方法来访问页面。在这里,代理的设置是通过proxy
参数传递给get()
方法,程序在获取Response后需要判断响应的状态,如果状态码在VALID_STATUS_CODES
列表里,则代表代理可用,可以调用RedisClient
的max()
方法将代理分数设为100,否则调用decrease()
方法将代理分数减1,如果出现异常也同样将代理分数减1。
0x04 接口模块
使用Flask实现接口模块,前端wget的VulApps的前端模版。
|
|
前端模版index.html
项目地址:http://proxy.w2n1ck.com:9090/
API接口:http://proxy.w2n1ck.com:9090/random
0x05 使用
测试结果如下:
获取代理IP:
|
|
使用代理IP:
|
|