[
  {
    "path": ".gitignore",
    "content": "/.idea\n*.pyc"
  },
  {
    "path": "README.md",
    "content": "# ADSL拨号服务器代理设置\n\n更优的选择：https://github.com/Python3WebSpider/AdslProxy\n\n## 服务端\n\n服务端即远程主机\n\n### 安装Python\n\nPython3版本\n\n\n### 安装库\n\n```\npip3 install redis tornado\n```\n\n### Clone项目\n\n```\ngit clone https://github.com/Germey/ADSLProxyPool.git\n```\n\n### 安装Redis\n\n安装Redis并启动服务\n\n### 修改配置\n\n```\ncd server\nvi config.py\n```\n\n根据注释修改配置文件\n\n### 运行\n\n根目录运行\n\n```\npython3 server.py\n```\n\n## 客户端\n\n客户端即拨号主机\n\n### 安装Python\n\nPython3版本\n\n\n### 安装库\n\n```\npip3 install requests\n```\n\n### Clone项目\n\n```\ngit clone https://github.com/Germey/ADSLProxyPool.git\n```\n\n\n### 修改配置\n\n```\ncd server\nvi config.py\n```\n\n根据注释修改配置文件\n\n### 运行\n\n根目录运行\n\n```\npython3 client.py\n```\n"
  },
  {
    "path": "client/__init__.py",
    "content": ""
  },
  {
    "path": "client/config.py",
    "content": "# 拨号间隔\nADSL_CYCLE = 100\n# ADSL命令\nADSL_BASH = 'adsl-stop;adsl-start'\n\n# 代理端口\nPROXY_PORT = 8888\n\n# 服务器地址\nSERVER_URL = 'http://120.27.34.24:8000'\n\n# 通信秘钥\nTOKEN = 'adsl'\n\n# 客户端唯一标识\nCLIENT_NAME = 'adsl1'\n\n# 拨号网卡\nADSL_IFNAME = 'ppp0'"
  },
  {
    "path": "client/sender.py",
    "content": "import re\nimport subprocess\n\nimport time\n\nfrom client.config import *\nimport requests\nfrom requests.exceptions import ConnectionError\n\n\nclass Sender():\n\n\n    def get_ip(self, ifname=ADSL_IFNAME):\n        (status, output) = subprocess.getstatusoutput('ifconfig')\n        if status == 0:\n            pattern = re.compile(ifname + '.*?inet.*?(\\d+\\.\\d+\\.\\d+\\.\\d+).*?netmask', re.S)\n            result = re.search(pattern, output)\n            if result:\n                ip = result.group(1)\n                return ip\n\n\n    def adsl(self):\n        while True:\n            print('ADSL Start, Please wait')\n            (status, output) = subprocess.getstatusoutput(ADSL_BASH)\n            if status == 0:\n                print('ADSL Successfully')\n                ip = self.get_ip()\n                if ip:\n                    print('New IP', ip)\n                    try:\n                        requests.post(SERVER_URL, data={'token': TOKEN, 'port': PROXY_PORT, 'name': CLIENT_NAME})\n                        print('Successfully Sent to Server', SERVER_URL)\n                    except ConnectionError:\n                        print('Failed to Connect Server', SERVER_URL)\n                    time.sleep(ADSL_CYCLE)\n                else:\n                    print('Get IP Failed')\n            else:\n                print('ADSL Failed, Please Check')\n            time.sleep(1)\n\n\ndef run():\n    sender = Sender()\n    sender.adsl()\n\n\nif __name__ == '__main__':\n    run()\n"
  },
  {
    "path": "client.py",
    "content": "from client.sender import run\n\nif __name__ == '__main__':\n    run()"
  },
  {
    "path": "server/__init__.py",
    "content": ""
  },
  {
    "path": "server/config.py",
    "content": "# Redis数据库IP\nREDIS_HOST = 'localhost'\n# Redis数据库密码, 如无则填None\nREDIS_PASSWORD = 'foobared'\n# Redis数据库端口\nREDIS_PORT = 6379\n# 代理池键名\nPROXY_KEY = 'adsl'\n# 通信秘钥\nTOKEN = 'adsl'\n# 验证URL\nTEST_URL = 'http://www.baidu.com'\n# 接收器运行端口\nRECEIVER_PORT = 8000\n# 检测间隔\nTEST_CYCLE = 20\n"
  },
  {
    "path": "server/db.py",
    "content": "import redis\nimport random\nfrom server.config import *\n\n\nclass RedisClient(object):\n    def __init__(self, host=REDIS_HOST, port=REDIS_PORT):\n        self.db = redis.Redis(host=host, port=port, password=REDIS_PASSWORD)\n        self.proxy_key = PROXY_KEY\n    \n    def key(self, name):\n        return '{key}:{name}'.format(key=self.proxy_key, name=name)\n    \n    def set(self, name, proxy):\n        return self.db.set(self.key(name), proxy)\n\n    def get(self, name):\n        return self.db.get(self.key(name)).decode('utf-8')\n\n    def count(self):\n        return len(self.db.keys(self.key('*')))\n    \n    def remove(self, name):\n        return self.db.delete(self.key(name))\n\n    def keys(self):\n        return [key.decode('utf-8').replace(self.proxy_key + ':', '') for key in self.db.keys(self.key('*'))]\n\n    def all(self):\n        keys = self.keys()\n        proxies = [{'name': key, 'proxy': self.get(key)} for key in keys]\n        return proxies\n\n    def random(self):\n        items = self.all()\n        return random.choice(items).get('proxy')\n\n    def list(self):\n        keys = self.keys()\n        proxies = [self.get(key) for key in keys]\n        return proxies\n\n    def first(self):\n        return self.get(self.keys()[0])\n\n\nif __name__ == '__main__':\n    client = RedisClient()\n    client.set('a', 'abc')\n    client.set('c', 'abc2')\n    client.set('c', 'abc3')\n    client.set('b', 'abc4')\n    client.remove('b')\n    result = client.get('a')\n    print(client.count())\n    print(client.all())\n    print(result)\n\n"
  },
  {
    "path": "server/receiver.py",
    "content": "import json\nfrom urllib.parse import urlencode, parse_qs, urlsplit\n\nimport tornado.ioloop\nimport tornado.web\nfrom tornado.curl_httpclient import CurlAsyncHTTPClient\nfrom tornado.web import RequestHandler, Application\nfrom server.config import *\nfrom server.db import RedisClient\nfrom tornado.httpclient import HTTPRequest\n\n\nclass MainHandler(RequestHandler):\n    redis = RedisClient()\n    http_client = CurlAsyncHTTPClient(force_instance=True)\n\n    def handle_proxy(self, response):\n        request = response.request\n        host = request.proxy_host\n        port = request.proxy_port\n        name = parse_qs(urlsplit(request.url).query).get('name')[0]\n        proxy = '{host}:{port}'.format(host=host, port=port)\n        if response.error:\n            print('Request failed Using', proxy, response.error)\n            print('Invalid Proxy', proxy, 'Remove it')\n            self.redis.remove(name)\n        else:\n            print('Valid Proxy', name)\n\n    def test_proxies(self):\n        print('Test Proxies')\n        items = self.redis.all()\n        for item in items:\n            self.test_proxy(item)\n\n    def test_proxy(self, item):\n        proxy = item.get('proxy')\n        name = item.get('name')\n        try:\n            (proxy_host, proxy_port) = tuple(proxy.split(':'))\n            print('Testing Proxy', name, proxy)\n            test_url = TEST_URL + '?' + urlencode({'name': name})\n            request = HTTPRequest(url=test_url, proxy_host=proxy_host, proxy_port=int(proxy_port))\n            self.http_client.fetch(request, self.handle_proxy)\n        except ValueError:\n            print('Invalid Proxy', proxy)\n            self.redis.remove(name)\n\n    def post(self):\n        token = self.get_body_argument('token', default=None, strip=False)\n        port = self.get_body_argument('port', default=None, strip=False)\n        name = self.get_body_argument('name', default=None, strip=False)\n        if token == TOKEN and port:\n            ip = self.request.remote_ip\n            proxy = ip + ':' + port\n            print('Receive proxy', proxy)\n            self.redis.set(name, proxy)\n            self.test_proxies()\n        elif token != TOKEN:\n            self.write('Wrong Token')\n        elif not port:\n            self.write('No Client Port')\n\n    def get(self, api):\n        if api == 'first':\n            result = self.redis.first()\n            if result:\n                self.write(result)\n\n        if api == 'random':\n            result = self.redis.random()\n            if result:\n                self.write(result)\n\n        if api == 'list':\n            result = self.redis.list()\n            print(result)\n            if result:\n                for proxy in result:\n                    self.write(proxy + '<br>')\n\n        if api == 'count':\n            self.write(str(self.redis.count()))\n\n\ndef run():\n    application = Application([\n        (r'/', MainHandler),\n        (r'/(.*)', MainHandler),\n    ])\n    print('Listening on', RECEIVER_PORT)\n    application.listen(RECEIVER_PORT)\n    tornado.ioloop.IOLoop.instance().start()\n\n\nif __name__ == '__main__':\n    run()\n"
  },
  {
    "path": "server.py",
    "content": "from server.receiver import run\n\nif __name__ == '__main__':\n    run()\n"
  }
]