192 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
| #!/usr/bin/env python3
 | |
| """
 | |
| Webshare 代理管理器
 | |
| 通过 Tailscale 连接甲骨文节点进行代理中转
 | |
| """
 | |
| 
 | |
| import subprocess
 | |
| import time
 | |
| import threading
 | |
| import json
 | |
| import requests
 | |
| from concurrent.futures import ThreadPoolExecutor
 | |
| 
 | |
| class ProxyManager:
 | |
|     def __init__(self, oracle_ip):
 | |
|         self.oracle_ip = oracle_ip
 | |
|         self.local_start_port = 20001
 | |
|         self.oracle_start_port = 10001
 | |
|         self.proxy_count = 20
 | |
|         self.processes = []
 | |
|         
 | |
|     def start_local_forwards(self):
 | |
|         """启动本地转发"""
 | |
|         print(f"启动本地代理转发到甲骨文服务器 {self.oracle_ip}")
 | |
|         
 | |
|         # 清理之前的进程
 | |
|         self.stop_forwards()
 | |
|         
 | |
|         for i in range(self.proxy_count):
 | |
|             local_port = self.local_start_port + i
 | |
|             oracle_port = self.oracle_start_port + i
 | |
|             
 | |
|             cmd = [
 | |
|                 'gost', 
 | |
|                 '-L', f'socks5://127.0.0.1:{local_port}',
 | |
|                 '-F', f'socks5://{self.oracle_ip}:{oracle_port}'
 | |
|             ]
 | |
|             
 | |
|             try:
 | |
|                 process = subprocess.Popen(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
 | |
|                 self.processes.append(process)
 | |
|                 print(f"本地端口 {local_port} -> 甲骨文 {self.oracle_ip}:{oracle_port}")
 | |
|                 time.sleep(0.1)
 | |
|             except Exception as e:
 | |
|                 print(f"启动转发失败 {local_port}: {e}")
 | |
|         
 | |
|         print(f"已启动 {len(self.processes)} 个代理转发")
 | |
|         
 | |
|     def stop_forwards(self):
 | |
|         """停止所有转发"""
 | |
|         for process in self.processes:
 | |
|             try:
 | |
|                 process.terminate()
 | |
|                 process.wait(timeout=5)
 | |
|             except:
 | |
|                 try:
 | |
|                     process.kill()
 | |
|                 except:
 | |
|                     pass
 | |
|         self.processes.clear()
 | |
|         
 | |
|         # 额外清理
 | |
|         try:
 | |
|             subprocess.run(['pkill', '-f', 'gost.*:2000'], check=False)
 | |
|         except:
 | |
|             pass
 | |
|     
 | |
|     def test_proxy(self, port):
 | |
|         """测试单个代理"""
 | |
|         try:
 | |
|             proxy = f'socks5://127.0.0.1:{port}'
 | |
|             response = requests.get(
 | |
|                 'http://httpbin.org/ip',
 | |
|                 proxies={'http': proxy, 'https': proxy},
 | |
|                 timeout=10
 | |
|             )
 | |
|             if response.status_code == 200:
 | |
|                 ip = response.json().get('origin', 'Unknown')
 | |
|                 return port, True, ip
 | |
|         except Exception as e:
 | |
|             return port, False, str(e)
 | |
|         return port, False, 'Timeout'
 | |
|     
 | |
|     def test_all_proxies(self):
 | |
|         """测试所有代理"""
 | |
|         print("测试代理连接...")
 | |
|         ports = [self.local_start_port + i for i in range(self.proxy_count)]
 | |
|         
 | |
|         with ThreadPoolExecutor(max_workers=10) as executor:
 | |
|             results = list(executor.map(self.test_proxy, ports))
 | |
|         
 | |
|         working = 0
 | |
|         failed = 0
 | |
|         
 | |
|         for port, success, info in results:
 | |
|             if success:
 | |
|                 print(f"✓ 端口 {port}: {info}")
 | |
|                 working += 1
 | |
|             else:
 | |
|                 print(f"✗ 端口 {port}: {info}")
 | |
|                 failed += 1
 | |
|         
 | |
|         print(f"\n测试结果: {working} 个工作, {failed} 个失败")
 | |
|         return working, failed
 | |
|     
 | |
|     def generate_clash_config(self):
 | |
|         """生成 Clash 配置"""
 | |
|         config = {
 | |
|             'port': 7890,
 | |
|             'socks-port': 7891,
 | |
|             'allow-lan': True,
 | |
|             'mode': 'Rule',
 | |
|             'log-level': 'info',
 | |
|             'external-controller': '127.0.0.1:9090',
 | |
|             'proxies': [],
 | |
|             'proxy-groups': [],
 | |
|             'rules': ['MATCH,WebShare']
 | |
|         }
 | |
|         
 | |
|         # 添加代理
 | |
|         for i in range(self.proxy_count):
 | |
|             port = self.local_start_port + i
 | |
|             config['proxies'].append({
 | |
|                 'name': f'WebShare-{i+1}',
 | |
|                 'type': 'socks5',
 | |
|                 'server': '127.0.0.1',
 | |
|                 'port': port
 | |
|             })
 | |
|         
 | |
|         # 选择组
 | |
|         proxy_names = [f'WebShare-{i+1}' for i in range(self.proxy_count)]
 | |
|         config['proxy-groups'].append({
 | |
|             'name': 'WebShare',
 | |
|             'type': 'select',
 | |
|             'proxies': proxy_names
 | |
|         })
 | |
|         
 | |
|         # 负载均衡组
 | |
|         config['proxy-groups'].append({
 | |
|             'name': 'LoadBalance',
 | |
|             'type': 'load-balance',
 | |
|             'url': 'http://www.gstatic.com/generate_204',
 | |
|             'interval': 300,
 | |
|             'proxies': proxy_names
 | |
|         })
 | |
|         
 | |
|         # 保存配置
 | |
|         with open('clash-webshare-auto.yaml', 'w') as f:
 | |
|             import yaml
 | |
|             yaml.dump(config, f, default_flow_style=False)
 | |
|         
 | |
|         print("Clash 配置已生成: clash-webshare-auto.yaml")
 | |
|     
 | |
|     def run(self):
 | |
|         """运行管理器"""
 | |
|         try:
 | |
|             self.start_local_forwards()
 | |
|             time.sleep(2)  # 等待连接建立
 | |
|             
 | |
|             working, failed = self.test_all_proxies()
 | |
|             
 | |
|             if working > 0:
 | |
|                 self.generate_clash_config()
 | |
|                 print(f"\n可用代理端口: 127.0.0.1:{self.local_start_port}-{self.local_start_port + working - 1}")
 | |
|                 print("\n按 Ctrl+C 停止...")
 | |
|                 
 | |
|                 while True:
 | |
|                     time.sleep(60)
 | |
|                     # 定期检查
 | |
|                     print(".", end="", flush=True)
 | |
|             else:
 | |
|                 print("没有可用的代理连接")
 | |
|                 
 | |
|         except KeyboardInterrupt:
 | |
|             print("\n正在停止...")
 | |
|         finally:
 | |
|             self.stop_forwards()
 | |
| 
 | |
| def main():
 | |
|     import sys
 | |
|     
 | |
|     if len(sys.argv) != 2:
 | |
|         print("使用方法: python3 proxy-manager.py <甲骨文Tailscale IP>")
 | |
|         print("示例: python3 proxy-manager.py 100.64.0.1")
 | |
|         sys.exit(1)
 | |
|     
 | |
|     oracle_ip = sys.argv[1]
 | |
|     manager = ProxyManager(oracle_ip)
 | |
|     manager.run()
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main() |