From 169196a372a62c21282a106eb6411c766652f7e3 Mon Sep 17 00:00:00 2001 From: WebShare Proxy Bot Date: Thu, 9 Oct 2025 01:21:44 +0000 Subject: [PATCH] 11 --- .kiro/steering/product.md | 28 +++++ .kiro/steering/structure.md | 52 ++++++++++ .kiro/steering/tech.md | 56 ++++++++++ SETUP-GUIDE.md | 165 ++++++++++++++++++++++++++++++ fetch_proxies.py | 0 local-client-setup.sh | 148 +++++++++++++++++++++++++++ local-webshare-forward.py | 88 ++++++++++++++++ oracle-proxy-config.json | 28 +++++ oracle-server-setup.sh | 124 ++++++++++++++++++++++ pr.sh | 0 proxy-manager.py | 192 +++++++++++++++++++++++++++++++++++ quick-start.sh | 105 +++++++++++++++++++ simple-forward.sh | 34 +++++++ simple-test.sh | 70 +++++++++++++ start-oracle-proxy.sh | 15 +++ test-webshare-proxies.py | 179 ++++++++++++++++++++++++++++++++ webshare_proxies.txt.example | 22 ++++ 17 files changed, 1306 insertions(+) create mode 100644 .kiro/steering/product.md create mode 100644 .kiro/steering/structure.md create mode 100644 .kiro/steering/tech.md create mode 100644 SETUP-GUIDE.md mode change 100644 => 100755 fetch_proxies.py create mode 100755 local-client-setup.sh create mode 100755 local-webshare-forward.py create mode 100644 oracle-proxy-config.json create mode 100755 oracle-server-setup.sh mode change 100644 => 100755 pr.sh create mode 100755 proxy-manager.py create mode 100644 quick-start.sh create mode 100755 simple-forward.sh create mode 100755 simple-test.sh create mode 100755 start-oracle-proxy.sh create mode 100755 test-webshare-proxies.py create mode 100644 webshare_proxies.txt.example diff --git a/.kiro/steering/product.md b/.kiro/steering/product.md new file mode 100644 index 0000000..116d093 --- /dev/null +++ b/.kiro/steering/product.md @@ -0,0 +1,28 @@ +--- +inclusion: always +--- + +# Product Overview + +This is a proxy management tool that fetches proxy lists from Webshare API and generates configuration files for multiple proxy clients. + +## Core Functionality + +- Fetches SOCKS/HTTP proxies from Webshare.io API using download tokens +- Supports multiple output formats: raw, HTTP, SOCKS5 +- Generates configuration files for popular proxy clients: + - Clash (YAML format) + - SingBox (JSON format) + - V2Ray (JSON config + Base64 subscription) + +## Key Features + +- Automatic API key management from `.env` file or environment variables +- Multiple authentication methods (username/password, IP auth) +- Country and location filtering support +- Automatic proxy health checking and failover configurations +- Chinese language support with UTF-8 encoding + +## Target Users + +Developers and users who need to manage proxy configurations across different clients and platforms, particularly those requiring access to geo-restricted content or enhanced privacy. \ No newline at end of file diff --git a/.kiro/steering/structure.md b/.kiro/steering/structure.md new file mode 100644 index 0000000..efa2386 --- /dev/null +++ b/.kiro/steering/structure.md @@ -0,0 +1,52 @@ +--- +inclusion: always +--- + +# Project Structure + +## Root Directory Layout + +``` +├── fetch_proxies.py # Main Python script - core functionality +├── pr.sh # Shell script for manual API testing +├── .env # Environment variables (API keys) +├── user_info.txt # User account information +├── README.md # Project documentation +└── .gitignore # Git ignore rules +``` + +## Generated Output Files + +``` +├── proxies_raw.txt # Raw proxy format (host:port:user:pass) +├── proxies_http.txt # HTTP proxy URLs +├── proxies_socks5.txt # SOCKS5 proxy URLs +├── clash_config.yaml # Clash client configuration +├── singbox_config.json # SingBox client configuration +├── v2ray_config.json # V2Ray client configuration +└── v2ray_subscription.txt # Base64 encoded V2Ray subscription +``` + +## Code Organization + +### Main Script (`fetch_proxies.py`) +- **API Functions**: `load_api_key()`, `get_download_token()`, `download_proxies()` +- **Parsing Functions**: `parse_proxies()`, `format_proxy_list()` +- **Output Functions**: `save_proxies()`, `save_*_config()` for each client type +- **Config Generators**: `generate_clash_config()`, `generate_singbox_config()`, `generate_v2ray_config()` + +### Configuration Patterns +- All functions use UTF-8 encoding +- Error handling with descriptive Chinese messages +- Modular design - each client type has dedicated generator functions +- Consistent proxy data structure: `{'host', 'port', 'username', 'password'}` + +## File Naming Conventions +- Snake_case for Python files and generated outputs +- Descriptive prefixes: `proxies_*` for proxy lists, `*_config.*` for client configs +- Standard extensions: `.py`, `.yaml`, `.json`, `.txt`, `.sh` + +## Environment Management +- `.env` file for sensitive API keys +- Environment variables as fallback: `TOKEN` or `WEBSHARE_API_KEY` +- All sensitive data excluded from version control via `.gitignore` \ No newline at end of file diff --git a/.kiro/steering/tech.md b/.kiro/steering/tech.md new file mode 100644 index 0000000..5bf6c20 --- /dev/null +++ b/.kiro/steering/tech.md @@ -0,0 +1,56 @@ +--- +inclusion: always +--- + +# Technology Stack + +## Language & Runtime +- **Python 3**: Main scripting language with UTF-8 encoding support +- **Bash**: Shell scripting for automation + +## Dependencies +- `requests`: HTTP client for API calls +- `yaml`: YAML configuration file generation +- `json`: JSON configuration handling +- `base64`: Encoding for V2Ray subscriptions +- `os`: Environment variable and file system operations + +## Configuration Formats +- **YAML**: Clash proxy client configurations +- **JSON**: SingBox and V2Ray configurations +- **Plain text**: Raw proxy lists in various formats +- **Base64**: V2Ray subscription links + +## Common Commands + +### Setup +```bash +# Install dependencies (if using pip) +pip install requests pyyaml + +# Set up environment +echo "TOKEN=your_webshare_api_key" > .env +``` + +### Execution +```bash +# Run the main proxy fetcher +python3 fetch_proxies.py + +# Quick API test (manual) +bash pr.sh +``` + +### Output Files Generated +- `proxies_raw.txt`: Raw format (host:port:username:password) +- `proxies_http.txt`: HTTP format URLs +- `proxies_socks5.txt`: SOCKS5 format URLs +- `clash_config.yaml`: Clash client configuration +- `singbox_config.json`: SingBox client configuration +- `v2ray_config.json`: V2Ray client configuration +- `v2ray_subscription.txt`: Base64 encoded subscription + +## API Integration +- **Webshare.io API v2**: Primary proxy source +- Token-based authentication with download tokens +- RESTful endpoints for proxy list retrieval \ No newline at end of file diff --git a/SETUP-GUIDE.md b/SETUP-GUIDE.md new file mode 100644 index 0000000..e253877 --- /dev/null +++ b/SETUP-GUIDE.md @@ -0,0 +1,165 @@ +# Webshare 代理通过 Tailscale + 甲骨文中转设置指南 + +## 架构说明 +``` +本地应用 → 本地SOCKS5(20001-20020) → Tailscale → 甲骨文节点(10001-10020) → Webshare代理 +``` + +## 前置要求 +1. 甲骨文服务器已安装 Tailscale 并连接到您的网络 +2. 本地机器也已安装 Tailscale 并连接到同一网络 +3. 两台机器都能正常通信 + +## 设置步骤 + +### 第一步:甲骨文服务器设置 + +1. 将 `oracle-server-setup.sh` 上传到甲骨文服务器: +```bash +scp oracle-server-setup.sh user@your-oracle-server:~/ +``` + +2. 在甲骨文服务器上运行: +```bash +chmod +x oracle-server-setup.sh +./oracle-server-setup.sh +``` + +3. 启动代理中转服务: +```bash +cd ~/proxy-config +./start-proxy-relay.sh +``` + +4. 记下显示的 Tailscale IP 地址(如:100.64.0.1) + +### 第二步:本地设置 + +1. 运行本地客户端设置: +```bash +./local-client-setup.sh +``` +输入甲骨文服务器的 Tailscale IP + +2. 启动本地转发: +```bash +./start-local-forward.sh +``` + +3. 测试连接: +```bash +./test-proxies.sh +``` + +### 第三步:使用 Python 管理器(推荐) + +更简单的方式是使用 Python 管理器: + +```bash +# 安装依赖 +pip3 install requests pyyaml + +# 启动管理器(替换为实际的甲骨文 Tailscale IP) +python3 proxy-manager.py 100.64.0.1 +``` + +管理器会自动: +- 启动所有代理转发 +- 测试连接状态 +- 生成 Clash 配置文件 + +## 使用方式 + +### 直接使用 SOCKS5 代理 +```bash +# 测试代理 +curl --socks5 127.0.0.1:20001 http://httpbin.org/ip + +# 使用不同代理 +curl --socks5 127.0.0.1:20002 http://httpbin.org/ip +``` + +### 使用 Clash +```bash +# 使用生成的配置启动 Clash +clash -f clash-webshare-config.yaml + +# 或使用自动生成的配置 +clash -f clash-webshare-auto.yaml +``` + +### 在应用中使用 +- **浏览器**:设置 SOCKS5 代理为 `127.0.0.1:20001-20020` +- **curl**:`curl --socks5 127.0.0.1:20001 URL` +- **Python requests**: +```python +proxies = { + 'http': 'socks5://127.0.0.1:20001', + 'https': 'socks5://127.0.0.1:20001' +} +requests.get('http://example.com', proxies=proxies) +``` + +## 端口分配 + +| 服务 | 端口范围 | 说明 | +|------|----------|------| +| 甲骨文中转 | 10001-10020 | 接收本地连接,转发到 Webshare | +| 本地代理 | 20001-20020 | 本地应用连接这些端口 | +| Clash HTTP | 7890 | Clash HTTP 代理端口 | +| Clash SOCKS | 7891 | Clash SOCKS 代理端口 | + +## 故障排除 + +### 1. 连接失败 +- 检查 Tailscale 连接:`tailscale status` +- 检查甲骨文服务器防火墙 +- 确认甲骨文服务器代理服务正在运行 + +### 2. 代理不工作 +- 检查 Webshare 账号状态 +- 测试单个 Webshare 代理是否可用 +- 查看 gost 进程是否正常运行:`ps aux | grep gost` + +### 3. 性能优化 +- 根据需要调整代理数量 +- 使用负载均衡模式分散请求 +- 监控代理使用情况 + +## 管理命令 + +```bash +# 查看运行状态 +ps aux | grep gost + +# 停止所有代理 +pkill -f gost + +# 重启服务(在甲骨文) +cd ~/proxy-config && ./start-proxy-relay.sh + +# 重启本地转发 +./start-local-forward.sh +``` + +## 安全注意事项 + +1. 确保 Tailscale 网络安全 +2. 不要将代理端口暴露到公网 +3. 定期更新 Webshare 账号凭证 +4. 监控代理使用情况,避免滥用 + +## 自动化启动 + +### 甲骨文服务器(systemd 服务) +```bash +sudo systemctl enable webshare-proxy +sudo systemctl start webshare-proxy +``` + +### 本地(可选) +创建开机启动脚本或使用 crontab。 + +--- + +**提示**:首次设置建议先手动运行各个步骤,确认工作正常后再设置自动启动。 \ No newline at end of file diff --git a/fetch_proxies.py b/fetch_proxies.py old mode 100644 new mode 100755 diff --git a/local-client-setup.sh b/local-client-setup.sh new file mode 100755 index 0000000..f367366 --- /dev/null +++ b/local-client-setup.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +echo "=== 本地客户端设置 ===" + +# 配置你的甲骨文 Tailscale IP +ORACLE_IP="100.x.x.x" # 请替换为实际的甲骨文 Tailscale IP + +echo "请先设置甲骨文服务器的 Tailscale IP:" +read -p "输入甲骨文服务器的 Tailscale IP: " ORACLE_IP + +if [ -z "$ORACLE_IP" ]; then + echo "IP 地址不能为空" + exit 1 +fi + +# 1. 安装 gost(如果没有) +echo "检查 gost..." +if ! command -v gost &> /dev/null; then + echo "安装 gost..." + wget -O gost.gz https://github.com/ginuerzh/gost/releases/download/v2.11.5/gost-linux-amd64-2.11.5.gz + gunzip gost.gz + chmod +x gost-linux-amd64-2.11.5 + sudo mv gost-linux-amd64-2.11.5 /usr/local/bin/gost + echo "gost 安装完成" +fi + +# 2. 创建本地转发脚本 +cat > start-local-forward.sh << EOF +#!/bin/bash + +echo "启动本地代理转发..." +echo "甲骨文服务器: $ORACLE_IP" + +# 杀死之前的进程 +pkill -f "gost.*:2000" + +# 启动20个本地转发 +for i in {1..20}; do + local_port=\$((20000 + i)) + oracle_port=\$((10000 + i)) + + # 本地端口 -> 甲骨文端口 + gost -L "socks5://127.0.0.1:\$local_port" -F "socks5://$ORACLE_IP:\$oracle_port" & + + echo "本地端口 \$local_port -> 甲骨文 $ORACLE_IP:\$oracle_port" + + sleep 0.1 +done + +echo "" +echo "本地代理转发已启动!" +echo "SOCKS5 代理地址: 127.0.0.1:20001-20020" +echo "" +echo "测试命令:" +echo "curl --socks5 127.0.0.1:20001 http://httpbin.org/ip" +echo "" +echo "按 Ctrl+C 停止" + +wait +EOF + +chmod +x start-local-forward.sh + +# 3. 创建测试脚本 +cat > test-proxies.sh << 'EOF' +#!/bin/bash + +echo "测试代理连接..." + +for i in {1..5}; do # 只测试前5个 + port=$((20000 + i)) + echo -n "测试端口 $port: " + + result=$(timeout 10 curl -s --socks5 127.0.0.1:$port http://httpbin.org/ip 2>/dev/null | jq -r '.origin' 2>/dev/null) + + if [ -n "$result" ]; then + echo "✓ $result" + else + echo "✗ 连接失败" + fi +done +EOF + +chmod +x test-proxies.sh + +# 4. 创建 Clash 配置 +cat > clash-webshare-config.yaml << 'EOF' +port: 7890 +socks-port: 7891 +allow-lan: true +mode: Rule +log-level: info +external-controller: 127.0.0.1:9090 + +proxies: +EOF + +for i in {1..20}; do + port=$((20000 + i)) + cat >> clash-webshare-config.yaml << EOF + - name: "WebShare-$i" + type: socks5 + server: 127.0.0.1 + port: $port + +EOF +done + +cat >> clash-webshare-config.yaml << 'EOF' +proxy-groups: + - name: "WebShare" + type: select + proxies: +EOF + +for i in {1..20}; do + echo " - \"WebShare-$i\"" >> clash-webshare-config.yaml +done + +cat >> clash-webshare-config.yaml << 'EOF' + + - name: "LoadBalance" + type: load-balance + url: http://www.gstatic.com/generate_204 + interval: 300 + proxies: +EOF + +for i in {1..20}; do + echo " - \"WebShare-$i\"" >> clash-webshare-config.yaml +done + +cat >> clash-webshare-config.yaml << 'EOF' + +rules: + - MATCH,WebShare +EOF + +echo "" +echo "=== 设置完成 ===" +echo "" +echo "使用步骤:" +echo "1. 确保甲骨文服务器已启动代理中转" +echo "2. 运行: ./start-local-forward.sh" +echo "3. 测试: ./test-proxies.sh" +echo "4. 使用 Clash: clash -f clash-webshare-config.yaml" +echo "" +echo "本地 SOCKS5 代理: 127.0.0.1:20001-20020" \ No newline at end of file diff --git a/local-webshare-forward.py b/local-webshare-forward.py new file mode 100755 index 0000000..88578be --- /dev/null +++ b/local-webshare-forward.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +""" +将本地 webshare 的 SOCKS5 代理通过 Tailscale 转发到甲骨文节点 +""" + +import subprocess +import json +import time +import threading + +# 配置 +ORACLE_TAILSCALE_IP = "100.x.x.x" # 替换为你的甲骨文 Tailscale IP +WEBSHARE_PROXIES_FILE = "webshare_proxies.txt" # webshare 代理列表文件 +LOCAL_START_PORT = 20001 # 本地监听起始端口 + +def read_webshare_proxies(): + """读取 webshare 代理列表""" + proxies = [] + try: + with open(WEBSHARE_PROXIES_FILE, 'r') as f: + for line in f: + line = line.strip() + if line and ':' in line: + # 格式: ip:port:username:password + parts = line.split(':') + if len(parts) >= 4: + proxies.append({ + 'host': parts[0], + 'port': parts[1], + 'username': parts[2], + 'password': parts[3] + }) + except FileNotFoundError: + print(f"请创建 {WEBSHARE_PROXIES_FILE} 文件,每行一个代理: ip:port:username:password") + return [] + + return proxies[:20] # 只取前20个 + +def start_proxy_forward(local_port, oracle_port, webshare_proxy): + """启动单个代理转发""" + # 使用 gost 进行代理链转发 + cmd = f"""gost -L socks5://:{local_port} -F socks5://{webshare_proxy['username']}:{webshare_proxy['password']}@{webshare_proxy['host']}:{webshare_proxy['port']}""" + + print(f"启动本地端口 {local_port} -> 甲骨文 {oracle_port} -> webshare {webshare_proxy['host']}:{webshare_proxy['port']}") + + try: + subprocess.run(cmd, shell=True) + except Exception as e: + print(f"代理转发失败 {local_port}: {e}") + +def main(): + # 读取 webshare 代理列表 + webshare_proxies = read_webshare_proxies() + + if not webshare_proxies: + print("没有找到有效的 webshare 代理配置") + return + + print(f"找到 {len(webshare_proxies)} 个 webshare 代理") + + # 启动代理转发 + threads = [] + for i, proxy in enumerate(webshare_proxies): + local_port = LOCAL_START_PORT + i + oracle_port = 10001 + i + + thread = threading.Thread( + target=start_proxy_forward, + args=(local_port, oracle_port, proxy) + ) + thread.daemon = True + thread.start() + threads.append(thread) + + time.sleep(0.1) # 避免启动过快 + + print(f"已启动 {len(threads)} 个代理转发") + print(f"本地 SOCKS5 代理端口: {LOCAL_START_PORT}-{LOCAL_START_PORT + len(webshare_proxies) - 1}") + + # 等待所有线程 + try: + for thread in threads: + thread.join() + except KeyboardInterrupt: + print("\n正在停止代理转发...") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/oracle-proxy-config.json b/oracle-proxy-config.json new file mode 100644 index 0000000..d3710b2 --- /dev/null +++ b/oracle-proxy-config.json @@ -0,0 +1,28 @@ +{ + "Debug": false, + "Retries": 3, + "ServeNodes": [ + "socks5://:10001", + "socks5://:10002", + "socks5://:10003", + "socks5://:10004", + "socks5://:10005", + "socks5://:10006", + "socks5://:10007", + "socks5://:10008", + "socks5://:10009", + "socks5://:10010", + "socks5://:10011", + "socks5://:10012", + "socks5://:10013", + "socks5://:10014", + "socks5://:10015", + "socks5://:10016", + "socks5://:10017", + "socks5://:10018", + "socks5://:10019", + "socks5://:10020" + ], + "ChainNodes": [], + "Routes": [] +} \ No newline at end of file diff --git a/oracle-server-setup.sh b/oracle-server-setup.sh new file mode 100755 index 0000000..c48971d --- /dev/null +++ b/oracle-server-setup.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +echo "=== 甲骨文服务器代理中转设置 ===" + +# 1. 安装 gost +echo "安装 gost..." +if ! command -v gost &> /dev/null; then + wget -O gost.gz https://github.com/ginuerzh/gost/releases/download/v2.11.5/gost-linux-amd64-2.11.5.gz + gunzip gost.gz + chmod +x gost-linux-amd64-2.11.5 + sudo mv gost-linux-amd64-2.11.5 /usr/local/bin/gost + echo "gost 安装完成" +else + echo "gost 已安装" +fi + +# 2. 确保 Tailscale 已安装并运行 +if ! command -v tailscale &> /dev/null; then + echo "请先安装 Tailscale:" + echo "curl -fsSL https://tailscale.com/install.sh | sh" + echo "sudo tailscale up" + exit 1 +fi + +# 3. 获取 Tailscale IP +TAILSCALE_IP=$(tailscale ip -4) +echo "甲骨文服务器 Tailscale IP: $TAILSCALE_IP" + +# 4. 创建代理配置目录 +mkdir -p ~/proxy-config +cd ~/proxy-config + +# 5. 创建 webshare 代理列表 +cat > webshare-proxies.txt << 'EOF' +fbkjstyt:lvo4zphp2wwj@45.196.40.191:6269 +fbkjstyt:lvo4zphp2wwj@130.180.228.168:6452 +fbkjstyt:lvo4zphp2wwj@72.1.154.35:7926 +fbkjstyt:lvo4zphp2wwj@63.141.62.186:6479 +fbkjstyt:lvo4zphp2wwj@216.170.122.181:6219 +fbkjstyt:lvo4zphp2wwj@192.53.67.209:5758 +fbkjstyt:lvo4zphp2wwj@130.180.231.18:8160 +fbkjstyt:lvo4zphp2wwj@192.53.142.239:5936 +fbkjstyt:lvo4zphp2wwj@103.130.178.22:5686 +fbkjstyt:lvo4zphp2wwj@216.98.254.253:6563 +fbkjstyt:lvo4zphp2wwj@192.46.188.237:5896 +fbkjstyt:lvo4zphp2wwj@45.56.161.56:8932 +fbkjstyt:lvo4zphp2wwj@192.46.201.252:6766 +fbkjstyt:lvo4zphp2wwj@45.196.50.62:6384 +fbkjstyt:lvo4zphp2wwj@193.160.83.42:6363 +fbkjstyt:lvo4zphp2wwj@103.130.178.234:5898 +fbkjstyt:lvo4zphp2wwj@72.46.139.62:6622 +fbkjstyt:lvo4zphp2wwj@72.46.139.239:6799 +fbkjstyt:lvo4zphp2wwj@103.130.178.62:5726 +fbkjstyt:lvo4zphp2wwj@72.46.138.21:6247 +EOF + +# 6. 创建启动脚本 +cat > start-proxy-relay.sh << 'EOF' +#!/bin/bash + +echo "启动代理中转服务..." + +# 杀死之前的进程 +pkill -f "gost.*:1000" + +# 读取代理列表并启动 +i=1 +while IFS= read -r line; do + if [ $i -gt 20 ]; then break; fi + + port=$((10000 + i)) + + # 启动 gost 中转 + gost -L "socks5://0.0.0.0:$port" -F "socks5://$line" & + + echo "端口 $port -> webshare $line" + + i=$((i + 1)) + sleep 0.1 +done < webshare-proxies.txt + +echo "" +echo "代理中转已启动!" +echo "Tailscale IP: $(tailscale ip -4)" +echo "监听端口: 10001-10020" +echo "" +echo "在本地使用以下命令连接:" +echo "ssh -L 20001:localhost:10001 -L 20002:localhost:10002 ... user@$(tailscale ip -4)" +echo "" +echo "或使用 gost 本地转发" + +wait +EOF + +chmod +x start-proxy-relay.sh + +# 7. 创建系统服务(可选) +sudo tee /etc/systemd/system/webshare-proxy.service > /dev/null << EOF +[Unit] +Description=Webshare Proxy Relay Service +After=network.target tailscaled.service + +[Service] +Type=simple +User=$USER +WorkingDirectory=$HOME/proxy-config +ExecStart=$HOME/proxy-config/start-proxy-relay.sh +Restart=always +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF + +echo "" +echo "=== 设置完成 ===" +echo "现在运行: ./start-proxy-relay.sh" +echo "" +echo "或者启用系统服务:" +echo "sudo systemctl enable webshare-proxy" +echo "sudo systemctl start webshare-proxy" +echo "" +echo "Tailscale IP: $TAILSCALE_IP" +echo "代理端口: 10001-10020" \ No newline at end of file diff --git a/pr.sh b/pr.sh old mode 100644 new mode 100755 diff --git a/proxy-manager.py b/proxy-manager.py new file mode 100755 index 0000000..7a13adb --- /dev/null +++ b/proxy-manager.py @@ -0,0 +1,192 @@ +#!/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() \ No newline at end of file diff --git a/quick-start.sh b/quick-start.sh new file mode 100644 index 0000000..6139f96 --- /dev/null +++ b/quick-start.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +echo "=== Webshare 代理快速启动脚本 ===" +echo "" + +# 检查参数 +if [ $# -eq 0 ]; then + echo "使用方法:" + echo " $0 <甲骨文Tailscale IP> # 启动代理转发" + echo " $0 test # 测试现有连接" + echo " $0 stop # 停止所有代理" + echo "" + echo "示例:" + echo " $0 100.64.0.1" + exit 1 +fi + +case "$1" in + "test") + echo "测试代理连接..." + if command -v python3 &> /dev/null; then + python3 -c " +import requests +import concurrent.futures + +def test_proxy(port): + try: + proxy = f'socks5://127.0.0.1:{port}' + r = requests.get('http://httpbin.org/ip', + proxies={'http': proxy, 'https': proxy}, + timeout=5) + return port, r.json().get('origin', 'Unknown') + except: + return port, None + +ports = range(20001, 20006) # 测试前5个 +with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: + results = list(executor.map(test_proxy, ports)) + +for port, ip in results: + if ip: + print(f'✓ 端口 {port}: {ip}') + else: + print(f'✗ 端口 {port}: 连接失败') +" + else + echo "需要 Python3 来测试代理" + echo "手动测试:" + echo "curl --socks5 127.0.0.1:20001 http://httpbin.org/ip" + fi + ;; + + "stop") + echo "停止所有代理转发..." + pkill -f "gost.*:2000" 2>/dev/null + pkill -f "proxy-manager.py" 2>/dev/null + echo "已停止" + ;; + + *) + ORACLE_IP="$1" + echo "甲骨文服务器 IP: $ORACLE_IP" + + # 检查 gost + if ! command -v gost &> /dev/null; then + echo "错误: 未找到 gost,请先运行 local-client-setup.sh" + exit 1 + fi + + # 检查 Python 管理器 + if [ -f "proxy-manager.py" ] && command -v python3 &> /dev/null; then + echo "使用 Python 管理器启动..." + python3 proxy-manager.py "$ORACLE_IP" + else + echo "使用 shell 脚本启动..." + + # 停止旧的进程 + pkill -f "gost.*:2000" 2>/dev/null + + # 启动转发 + echo "启动代理转发..." + for i in {1..20}; do + local_port=$((20000 + i)) + oracle_port=$((10000 + i)) + + gost -L "socks5://127.0.0.1:$local_port" -F "socks5://$ORACLE_IP:$oracle_port" & + echo -n "." + sleep 0.1 + done + + echo "" + echo "代理转发已启动!" + echo "本地 SOCKS5 代理: 127.0.0.1:20001-20020" + echo "" + echo "测试连接: $0 test" + echo "停止服务: $0 stop" + echo "" + echo "按 Ctrl+C 停止..." + + # 等待 + trap 'echo "正在停止..."; pkill -f "gost.*:2000"; exit' INT + wait + fi + ;; +esac \ No newline at end of file diff --git a/simple-forward.sh b/simple-forward.sh new file mode 100755 index 0000000..9a2f0e8 --- /dev/null +++ b/simple-forward.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# 简化版本:直接在甲骨文服务器上转发 webshare 代理 +# 需要先在甲骨文服务器上配置 + +ORACLE_IP="你的甲骨文Tailscale IP" # 替换为实际IP + +# 本地安装 gost +if ! command -v gost &> /dev/null; then + echo "正在安装 gost..." + wget https://github.com/ginuerzh/gost/releases/download/v2.11.5/gost-linux-amd64-2.11.5.gz + gunzip gost-linux-amd64-2.11.5.gz + chmod +x gost-linux-amd64-2.11.5 + sudo mv gost-linux-amd64-2.11.5 /usr/local/bin/gost +fi + +# 读取 webshare 代理并启动转发 +echo "启动代理转发..." + +# 示例:将本地 20001-20020 端口转发到甲骨文的 10001-10020 端口 +for i in {1..20}; do + local_port=$((20000 + i)) + oracle_port=$((10000 + i)) + + # 启动本地到甲骨文的转发 + gost -L "socks5://:${local_port}" -F "socks5://${ORACLE_IP}:${oracle_port}" & + + echo "本地端口 ${local_port} -> 甲骨文 ${ORACLE_IP}:${oracle_port}" +done + +echo "代理转发已启动,本地 SOCKS5 端口: 20001-20020" +echo "按 Ctrl+C 停止" + +wait \ No newline at end of file diff --git a/simple-test.sh b/simple-test.sh new file mode 100755 index 0000000..cdda6ae --- /dev/null +++ b/simple-test.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +echo "=== 简单测试 Webshare SOCKS5 代理 ===" + +# 代理列表 +PROXIES=( + "fbkjstyt:lvo4zphp2wwj@45.196.40.191:6269" + "fbkjstyt:lvo4zphp2wwj@130.180.228.168:6452" + "fbkjstyt:lvo4zphp2wwj@72.1.154.35:7926" + "fbkjstyt:lvo4zphp2wwj@63.141.62.186:6479" + "fbkjstyt:lvo4zphp2wwj@216.170.122.181:6219" + "fbkjstyt:lvo4zphp2wwj@192.53.67.209:5758" + "fbkjstyt:lvo4zphp2wwj@130.180.231.18:8160" + "fbkjstyt:lvo4zphp2wwj@192.53.142.239:5936" + "fbkjstyt:lvo4zphp2wwj@103.130.178.22:5686" + "fbkjstyt:lvo4zphp2wwj@216.98.254.253:6563" + "fbkjstyt:lvo4zphp2wwj@192.46.188.237:5896" + "fbkjstyt:lvo4zphp2wwj@45.56.161.56:8932" + "fbkjstyt:lvo4zphp2wwj@192.46.201.252:6766" + "fbkjstyt:lvo4zphp2wwj@45.196.50.62:6384" + "fbkjstyt:lvo4zphp2wwj@193.160.83.42:6363" + "fbkjstyt:lvo4zphp2wwj@103.130.178.234:5898" + "fbkjstyt:lvo4zphp2wwj@72.46.139.62:6622" + "fbkjstyt:lvo4zphp2wwj@72.46.139.239:6799" + "fbkjstyt:lvo4zphp2wwj@103.130.178.62:5726" + "fbkjstyt:lvo4zphp2wwj@72.46.138.21:6247" +) + +WORKING=0 +FAILED=0 + +echo "开始测试 ${#PROXIES[@]} 个代理..." +echo "" + +for i in "${!PROXIES[@]}"; do + proxy="${PROXIES[$i]}" + num=$((i + 1)) + + printf "[%2d] 测试 %s ... " "$num" "${proxy%%@*}@***" + + # 使用curl测试代理 + result=$(timeout 15 curl -s --socks5 "$proxy" http://httpbin.org/ip 2>/dev/null) + + if [ $? -eq 0 ] && echo "$result" | grep -q "origin"; then + ip=$(echo "$result" | grep -o '"origin": "[^"]*"' | cut -d'"' -f4) + echo "✓ $ip" + WORKING=$((WORKING + 1)) + else + echo "✗ 连接失败" + FAILED=$((FAILED + 1)) + fi + + # 避免请求过快 + sleep 0.5 +done + +echo "" +echo "===============================================" +echo "测试完成!" +echo "✓ 工作正常: $WORKING 个" +echo "✗ 连接失败: $FAILED 个" +echo "成功率: $(( WORKING * 100 / (WORKING + FAILED) ))%" + +if [ $WORKING -gt 0 ]; then + echo "" + echo "建议: 使用工作正常的代理进行中转设置" +else + echo "" + echo "警告: 没有可用的代理,请检查 Webshare 账号状态" +fi \ No newline at end of file diff --git a/start-oracle-proxy.sh b/start-oracle-proxy.sh new file mode 100755 index 0000000..fe9a95e --- /dev/null +++ b/start-oracle-proxy.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# 启动 gost 代理服务器,监听20个端口 +gost -C oracle-proxy-config.json & + +# 或者使用命令行方式启动多个代理 +# for port in {10001..10020}; do +# gost -L socks5://:$port & +# done + +echo "Oracle proxy servers started on ports 10001-10020" +echo "Tailscale IP: $(tailscale ip -4)" + +# 保持脚本运行 +wait \ No newline at end of file diff --git a/test-webshare-proxies.py b/test-webshare-proxies.py new file mode 100755 index 0000000..6de83bf --- /dev/null +++ b/test-webshare-proxies.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +""" +测试 Webshare SOCKS5 代理连通性 +""" + +import requests +import time +import threading +from concurrent.futures import ThreadPoolExecutor, as_completed +import sys + +# 从 proxies_socks5.txt 读取的代理列表 +WEBSHARE_PROXIES = [ + "socks5://fbkjstyt:lvo4zphp2wwj@45.196.40.191:6269", + "socks5://fbkjstyt:lvo4zphp2wwj@130.180.228.168:6452", + "socks5://fbkjstyt:lvo4zphp2wwj@72.1.154.35:7926", + "socks5://fbkjstyt:lvo4zphp2wwj@63.141.62.186:6479", + "socks5://fbkjstyt:lvo4zphp2wwj@216.170.122.181:6219", + "socks5://fbkjstyt:lvo4zphp2wwj@192.53.67.209:5758", + "socks5://fbkjstyt:lvo4zphp2wwj@130.180.231.18:8160", + "socks5://fbkjstyt:lvo4zphp2wwj@192.53.142.239:5936", + "socks5://fbkjstyt:lvo4zphp2wwj@103.130.178.22:5686", + "socks5://fbkjstyt:lvo4zphp2wwj@216.98.254.253:6563", + "socks5://fbkjstyt:lvo4zphp2wwj@192.46.188.237:5896", + "socks5://fbkjstyt:lvo4zphp2wwj@45.56.161.56:8932", + "socks5://fbkjstyt:lvo4zphp2wwj@192.46.201.252:6766", + "socks5://fbkjstyt:lvo4zphp2wwj@45.196.50.62:6384", + "socks5://fbkjstyt:lvo4zphp2wwj@193.160.83.42:6363", + "socks5://fbkjstyt:lvo4zphp2wwj@103.130.178.234:5898", + "socks5://fbkjstyt:lvo4zphp2wwj@72.46.139.62:6622", + "socks5://fbkjstyt:lvo4zphp2wwj@72.46.139.239:6799", + "socks5://fbkjstyt:lvo4zphp2wwj@103.130.178.62:5726", + "socks5://fbkjstyt:lvo4zphp2wwj@72.46.138.21:6247" +] + +def test_single_proxy(index, proxy_url): + """测试单个代理""" + try: + print(f"[{index+1:2d}] 测试 {proxy_url} ...", end=" ", flush=True) + + # 设置代理 + proxies = { + 'http': proxy_url, + 'https': proxy_url + } + + # 测试连接 + start_time = time.time() + response = requests.get( + 'http://httpbin.org/ip', + proxies=proxies, + timeout=15, + verify=False + ) + + if response.status_code == 200: + data = response.json() + ip = data.get('origin', 'Unknown') + elapsed = time.time() - start_time + print(f"✓ {ip} ({elapsed:.2f}s)") + return index, True, ip, elapsed, None + else: + print(f"✗ HTTP {response.status_code}") + return index, False, None, 0, f"HTTP {response.status_code}" + + except requests.exceptions.Timeout: + print("✗ 超时") + return index, False, None, 0, "Timeout" + except requests.exceptions.ProxyError as e: + print(f"✗ 代理错误: {str(e)[:50]}") + return index, False, None, 0, "Proxy Error" + except Exception as e: + print(f"✗ 错误: {str(e)[:50]}") + return index, False, None, 0, str(e)[:50] + +def test_all_proxies(max_workers=10): + """测试所有代理""" + print(f"开始测试 {len(WEBSHARE_PROXIES)} 个 Webshare SOCKS5 代理...") + print("=" * 80) + + results = [] + working_proxies = [] + failed_proxies = [] + + # 使用线程池并发测试 + with ThreadPoolExecutor(max_workers=max_workers) as executor: + # 提交所有任务 + futures = { + executor.submit(test_single_proxy, i, proxy): i + for i, proxy in enumerate(WEBSHARE_PROXIES) + } + + # 收集结果 + for future in as_completed(futures): + try: + result = future.result() + results.append(result) + + index, success, ip, elapsed, error = result + if success: + working_proxies.append((index, WEBSHARE_PROXIES[index], ip, elapsed)) + else: + failed_proxies.append((index, WEBSHARE_PROXIES[index], error)) + + except Exception as e: + print(f"任务执行错误: {e}") + + # 按索引排序结果 + results.sort(key=lambda x: x[0]) + working_proxies.sort(key=lambda x: x[0]) + failed_proxies.sort(key=lambda x: x[0]) + + print("=" * 80) + print(f"测试完成!") + print(f"✓ 工作正常: {len(working_proxies)} 个") + print(f"✗ 连接失败: {len(failed_proxies)} 个") + + if working_proxies: + print(f"\n可用代理列表:") + for index, proxy, ip, elapsed in working_proxies: + print(f" [{index+1:2d}] {ip} ({elapsed:.2f}s) - {proxy}") + + if failed_proxies: + print(f"\n失败代理列表:") + for index, proxy, error in failed_proxies: + print(f" [{index+1:2d}] {error} - {proxy}") + + # 速度统计 + if working_proxies: + speeds = [elapsed for _, _, _, elapsed in working_proxies] + avg_speed = sum(speeds) / len(speeds) + print(f"\n平均响应时间: {avg_speed:.2f}s") + print(f"最快代理: {min(speeds):.2f}s") + print(f"最慢代理: {max(speeds):.2f}s") + + return working_proxies, failed_proxies + +def test_specific_proxy(index): + """测试指定索引的代理""" + if 0 <= index < len(WEBSHARE_PROXIES): + result = test_single_proxy(index, WEBSHARE_PROXIES[index]) + return result + else: + print(f"错误: 代理索引 {index} 超出范围 (0-{len(WEBSHARE_PROXIES)-1})") + return None + +def main(): + if len(sys.argv) > 1: + try: + # 测试指定的代理 + index = int(sys.argv[1]) - 1 # 用户输入从1开始 + print(f"测试第 {sys.argv[1]} 个代理...") + test_specific_proxy(index) + except ValueError: + if sys.argv[1] == "fast": + print("快速测试前5个代理...") + for i in range(min(5, len(WEBSHARE_PROXIES))): + test_single_proxy(i, WEBSHARE_PROXIES[i]) + elif sys.argv[1] == "working": + print("只显示工作中的代理...") + working, failed = test_all_proxies() + if working: + print(f"\n生成工作代理列表文件...") + with open('working_proxies.txt', 'w') as f: + for index, proxy, ip, elapsed in working: + f.write(f"{proxy}\n") + print(f"已保存到 working_proxies.txt") + else: + print("使用方法:") + print(" python3 test-webshare-proxies.py # 测试所有代理") + print(" python3 test-webshare-proxies.py 1-20 # 测试指定代理") + print(" python3 test-webshare-proxies.py fast # 快速测试前5个") + print(" python3 test-webshare-proxies.py working # 只保存工作的代理") + else: + # 测试所有代理 + test_all_proxies() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/webshare_proxies.txt.example b/webshare_proxies.txt.example new file mode 100644 index 0000000..58599b7 --- /dev/null +++ b/webshare_proxies.txt.example @@ -0,0 +1,22 @@ +# webshare 代理列表示例 +# 格式: IP:端口:用户名:密码 +proxy1.webshare.io:80:username1:password1 +proxy2.webshare.io:80:username2:password2 +proxy3.webshare.io:80:username3:password3 +proxy4.webshare.io:80:username4:password4 +proxy5.webshare.io:80:username5:password5 +proxy6.webshare.io:80:username6:password6 +proxy7.webshare.io:80:username7:password7 +proxy8.webshare.io:80:username8:password8 +proxy9.webshare.io:80:username9:password9 +proxy10.webshare.io:80:username10:password10 +proxy11.webshare.io:80:username11:password11 +proxy12.webshare.io:80:username12:password12 +proxy13.webshare.io:80:username13:password13 +proxy14.webshare.io:80:username14:password14 +proxy15.webshare.io:80:username15:password15 +proxy16.webshare.io:80:username16:password16 +proxy17.webshare.io:80:username17:password17 +proxy18.webshare.io:80:username18:password18 +proxy19.webshare.io:80:username19:password19 +proxy20.webshare.io:80:username20:password20 \ No newline at end of file