├── .DS_Store ├── README.MD ├── app ├── Dockerfile ├── entrypoint.sh └── init.py ├── docker-compose.yml └── images └── Screen Shot 2022-03-23 at 9.44.51 AM.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HomeCloudHub/multi-tor/678d5b895be4347a7a4bfb0c3358a2b8852357f3/.DS_Store -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # 基于洋葱打造代理池或者增强你的上网匿名性 2 | 3 | ## 前言 4 | 很多小伙伴长期苦于没有稳定的代理池,临时跑点爬虫数据焦麻了,网络公开的免费代理又极其不稳定,又不想购买商业代理池,本方案适用于未禁用洋葱节点的站点,稳定性妥妥的,洋葱节点数量上你懂的,另外有些小伙伴热衷了匿名上网,本方案可供参考,大大增强你上完的匿名性及选择灵活性。你每请求一次,走一条线路出去,配置的线路越多,效果越好,当然,得考验你的服务器撑得了几个洋葱了。 5 | 6 | ## 条件 7 | - 海外 Linux 服务器一台 8 | - 服务器需安装 docker & docker-compose 即可 9 | 10 | ## 特色 11 | 12 | - 基于 docker ,节省系统资源 13 | - 可配置洋葱线路个数,上限 65534 14 | - 统一入口,自动选路,免去爬虫端的代理节点控制逻辑 15 | - 入口代理兼容 http/socks4/socks5 协议接入 16 | - 入口代理可配置访问凭证,可防止未授权访问 17 | - 入口代理自动探测洋葱节点可用性 18 | - 入口代理支持负载均衡,以轮训方式选择洋葱节点转发流量出去 19 | - 洋葱线路可配置轮换间隔时间 20 | 21 | ## 快速开始 22 | ```bash 23 | git clone https://github.com/evling2020/multi-tor.git 24 | docker-compose up -d 25 | ``` 26 | 27 | ## 环境变量含义 28 | |名称|含义| 29 | |---|---| 30 | |TOR_NUM|洋葱进程数量,即洋葱并行节点个数| 31 | |TOR_ROTATE_TIME|每个洋葱变换IP时间,单位为秒,默认 300| 32 | |IN_PROXY_USER|入口代理访问控制,用户名| 33 | |IN_PROXY_PASS|入口代理访问控制,密码| 34 | |IN_PROXY_INTERVAL|洋葱线路存活探测间隔时间,单位为秒,默认 300| 35 | 36 | ## 异想天开 37 | 试想一下,咱们将洋葱线路切换时间设置为 60s ,洋葱进程开启 50 个,也就意味着,每分钟咱们可以享受 50 个异国他乡的代理地址,每小时可以享受 3000 个,一天最大可达 72000 个,是不是日常研究够用了嘛。 38 | 39 | ## 注意点 40 | - 目前采用一个容器,由于 tcp 端口数目有限制,入口代理需占用一个,所以最大理论可支持同时运行 65534 个洋葱进程 41 | - 启动容器后需要等待 30s 方可使用,请耐心等待 42 | - 如需利用线路爬取暗网资源,需启用暗网专用 dns 解析端口,请自行琢磨 43 | - 有些想要搞个透明代理啥的,也请自行琢磨,配置文件里加个配置项,再 iptables 转发下即可实现 44 | - 不要开太多洋葱进程,小心撑爆你服务器,量力而行,小易未做极限测试,小易的服务器是真滴渣,哎... 45 | 46 | ## 测试效果 47 | 48 | 49 | ![Screen Shot 2022-03-23 at 9.44.51 AM.png](./images/Screen%20Shot%202022-03-23%20at%209.44.51%20AM.png) 50 | 51 | 52 | ## 法律免责声明 53 | 该项目仅用于学习研究,若用于身份隐匿未经授权入侵属于非法行为,后果自负。切记,自用!!! 54 | 55 | ## 更新日志 56 | - **2022.03.23:** 首次创建项目 57 | 58 | ## 易雾山庄 59 | 60 | 该项目是易雾山庄-家庭基建的一部分,[**易雾山庄**](https://www.evling.tech)记录了家庭网络基础建设的种种实践,可以帮助更多有需要的人减少折腾。希望通过这个平台构建一只家庭基建小社群,共同优化我们的生活体验,增强个人数据安全保护意识,同时我们还要考虑环保节能问题,实实在在帮大家伙组建属于自己的家庭网络。欢迎关注微信公号《易雾山庄》,订阅易雾君的独家折腾!!! 61 | -------------------------------------------------------------------------------- /app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | #RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories 4 | RUN apk add --no-cache ca-certificates tzdata python3 py3-pip curl wget bash tor gzip && \ 5 | rm -rf /tmp/* && rm -rf /var/cache/apk/* 6 | RUN pip3 install pyyaml==5.4.1 7 | RUN wget -O /tmp/in_program.gz https://github.com/Dreamacro/clash/releases/download/v1.10.0/clash-linux-amd64-v1.10.0.gz && gzip -d /tmp/in_program.gz && mv /tmp/in_program /usr/bin/in_program && chmod +x /usr/bin/in_program 8 | VOLUME /data 9 | COPY entrypoint.sh /entrypoint.sh 10 | COPY init.py /init.py 11 | RUN chmod +x /entrypoint.sh 12 | 13 | ENTRYPOINT ["/entrypoint.sh"] 14 | -------------------------------------------------------------------------------- /app/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python3 /init.py 3 | /bin/bash /data/run.sh & # >> /data/proxy.log & 4 | tail -f /dev/stdout # /data/proxy.log 5 | -------------------------------------------------------------------------------- /app/init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # @Project : tools 4 | # @File : init.py 5 | # @Software: PyCharm 6 | # @Author : 易雾君 7 | # @Email : evling2020@gmail.com 8 | # @公众号 : 易雾山庄 9 | # @Site : https://www.evling.tech 10 | # @Describe : 家庭基建,生活乐享. 11 | # @Time : 2022/3/22 8:24 PM 12 | 13 | import os 14 | import shutil 15 | import yaml 16 | 17 | 18 | port_num = int(os.getenv('TOR_NUM')) if os.getenv('TOR_NUM') else 10 19 | port_num = port_num if port_num < 65535 else 65534 20 | tor_rotate_time = int(os.getenv('TOR_ROTATE_TIME')) if os.getenv('TOR_ROTATE_TIME') else 300 21 | in_proxy_interval = int(os.getenv('IN_PROXY_INTERVAL')) if os.getenv('IN_PROXY_INTERVAL') else 300 22 | in_proxy_port = 8080 23 | in_proxy_user = os.getenv('IN_PROXY_USER') 24 | in_proxy_pass = os.getenv('IN_PROXY_PASS') 25 | in_program_bin = '/usr/bin/in_program' 26 | in_program_dir = '/data/in_program/' 27 | in_conf = os.path.join(in_program_dir, 'proxy.yaml') 28 | 29 | tor_bin = '/usr/bin/tor' 30 | tor_data_dir = '/data/tor/' 31 | run_script = '/data/run.sh' 32 | 33 | command_lines = [] 34 | 35 | if not os.path.exists('/data'): 36 | os.mkdir('/data') 37 | 38 | if not os.path.exists(in_program_dir): 39 | os.mkdir(in_program_dir) 40 | 41 | if os.path.exists(tor_data_dir): 42 | shutil.rmtree(tor_data_dir) 43 | os.mkdir(tor_data_dir) 44 | 45 | def build_conf(port_list=[], in_conf='/data/in_program/proxy.yaml', username=None, passwd=None): 46 | base_conf_content = f''' 47 | mixed-port: {in_proxy_port} 48 | allow-lan: true 49 | bind-address: "*" 50 | mode: rule 51 | log-level: info 52 | rules: 53 | - MATCH,Load_Balance 54 | ''' 55 | config_dic = yaml.load(base_conf_content, Loader=yaml.FullLoader) 56 | if 'proxies' not in config_dic: 57 | config_dic['proxies'] = [] 58 | if 'proxy-groups' not in config_dic: 59 | config_dic['proxy-groups'] = [] 60 | 61 | proxy_group = { 62 | 'name': 'Load_Balance', 63 | 'type': 'load-balance', 64 | 'strategy': 'round-robin', 65 | 'url': 'http://www.gstatic.com/generate_204', 66 | 'interval': in_proxy_interval, 67 | 'proxies': [] 68 | } 69 | for port in port_list: 70 | proxy_name = f'tor-{port}' 71 | proxy_type = 'socks5' 72 | proxy_server = '127.0.0.1' 73 | proxy_port = port 74 | proxy_group['proxies'].append(proxy_name) 75 | node = {'name': proxy_name, 76 | 'type': proxy_type, 77 | 'server': proxy_server, 78 | 'port': proxy_port 79 | } 80 | config_dic['proxies'].append(node) 81 | config_dic['proxy-groups'].append(proxy_group) 82 | if username is not None and passwd is not None: 83 | config_dic['authentication'] =[f'{username}:{passwd}'] 84 | with open(in_conf, 'w', encoding='utf-8') as f: 85 | yaml.dump(config_dic, f, allow_unicode=True, sort_keys=False) 86 | f.close() 87 | 88 | port_list = [x for x in range(1, port_num+1)] 89 | if in_proxy_port in port_list: 90 | port_list.pop(in_proxy_port) 91 | port_list.append(port_num+1) 92 | 93 | for port in port_list: 94 | tmp_tor_data_dir = os.path.join(tor_data_dir, f'tor-{port}') 95 | if os.path.exists(tmp_tor_data_dir): 96 | shutil.rmtree(tmp_tor_data_dir) 97 | os.mkdir(tmp_tor_data_dir) 98 | tmp_tor_conf = os.path.join(tmp_tor_data_dir, 'torrc') 99 | with open(tmp_tor_conf, 'w') as f: 100 | f.write(f'''SOCKSPort 127.0.0.1:{port} 101 | DataDirectory {tmp_tor_data_dir} 102 | #VirtualAddrNetworkIPv4 10.192.0.0/10 103 | AutomapHostsOnResolve 1 104 | #TransPort 0.0.0.0:9140 105 | #DNSPort 0.0.0.0:9053 106 | MaxCircuitDirtiness {tor_rotate_time} 107 | ''') 108 | f.close() 109 | command_lines.append(f'{tor_bin} -f {tmp_tor_conf} &') 110 | 111 | 112 | build_conf(port_list, in_conf=in_conf, username=in_proxy_user, passwd=in_proxy_pass) 113 | command_lines.append('sleep 30') 114 | command_lines.append(f'{in_program_bin} -f {in_conf}') 115 | 116 | with open(run_script, 'w') as f: 117 | f.write('\n'.join(command_lines)) 118 | f.close() 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.0' 2 | services: 3 | app: 4 | build: ./app 5 | restart: always 6 | tty: true 7 | #privileged: true 8 | environment: 9 | - TOR_NUM=8 10 | - TOR_ROTATE_TIME=60 11 | - IN_PROXY_USER=admin 12 | - IN_PROXY_PASS=admin 13 | - IN_PROXY_INTERVAL=61 14 | ports: 15 | - "8081:8080" 16 | working_dir: /data 17 | volumes: 18 | - ./data:/data 19 | #network_mode: host 20 | -------------------------------------------------------------------------------- /images/Screen Shot 2022-03-23 at 9.44.51 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HomeCloudHub/multi-tor/678d5b895be4347a7a4bfb0c3358a2b8852357f3/images/Screen Shot 2022-03-23 at 9.44.51 AM.png --------------------------------------------------------------------------------