#!/bin/bash # 调试模式 set -x # 添加诊断函数 check_target_server() { local url="$1" local host="${url#*://}" host="${host%%/*}" echo "========== 网络诊断 ==========" echo "- 检查目标主机: $host" # 尝试解析主机名 if host "$host" > /dev/null 2>&1; then ip=$(host "$host" | grep "has address" | head -1 | awk '{print $4}') echo "- 主机解析成功: $host -> $ip" else echo "- 警告: 无法解析主机名 $host" fi # 尝试 ping 目标主机 if ping -c 1 -W 2 "$host" > /dev/null 2>&1; then echo "- Ping 测试成功" else echo "- 警告: Ping 测试失败 (可能被防火墙阻止)" fi # 尝试 TCP 连接到 443 端口 if nc -z -w2 "$host" 443 > /dev/null 2>&1; then echo "- TCP 连接成功 (443端口)" else echo "- 警告: 无法连接到 $host:443" fi # 尝试 TCP 连接到 80 端口 if nc -z -w2 "$host" 80 > /dev/null 2>&1; then echo "- TCP 连接成功 (80端口)" else echo "- 警告: 无法连接到 $host:80" fi # 检查是否与当前主机相同 current_host=$(hostname -f 2>/dev/null || hostname) if [[ "$host" == *"$current_host"* || "$current_host" == *"$host"* ]]; then echo "- 严重错误: 目标主机似乎是当前主机自身,这将导致循环代理!" echo "- 当前主机: $current_host" echo "- 目标主机: $host" echo "- 请检查环境变量 URL 是否设置正确" fi echo "==============================" } # 显示欢迎信息 echo "======================================" echo " WebSocket Proxy Converter (by gost)" echo "======================================" echo "Starting service at port 7860..." # 显示环境变量调试信息 echo "环境变量:" echo "- URL = $URL" echo "- TARGET_WSPROXY_URL = $TARGET_WSPROXY_URL" echo "- HOSTNAME = $(hostname)" # 检查目标 URL 是否已设置(兼容两种环境变量名) if [ -n "$URL" ]; then # 用户设置了 URL 环境变量(Hugging Face Secret) TARGET_BASE_URL="$URL" echo "使用 URL 环境变量: $TARGET_BASE_URL" elif [ -n "$TARGET_WSPROXY_URL" ]; then # 用户直接设置了完整的 WebSocket URL TARGET_BASE_URL="$TARGET_WSPROXY_URL" echo "使用 TARGET_WSPROXY_URL 环境变量: $TARGET_BASE_URL" else echo "Error: Neither URL nor TARGET_WSPROXY_URL environment variable is set." echo "Please set URL to your first Space URL, like: https://your-first-space.hf.space" exit 1 fi # 检查是否已经包含 /wsproxy 路径 if [[ "$TARGET_BASE_URL" != */wsproxy ]]; then # 添加 /wsproxy 路径 TARGET_BASE_URL="${TARGET_BASE_URL}/wsproxy" echo "添加 /wsproxy 路径: $TARGET_BASE_URL" fi # 检查是否需要转换 https:// 到 wss:// 或 http:// 到 ws:// if [[ "$TARGET_BASE_URL" == https://* ]]; then # 替换 https:// 为 wss:// TARGET_WSPROXY_URL="${TARGET_BASE_URL/https:\/\//wss:\/\/}" echo "转换 HTTPS 到 WSS: $TARGET_WSPROXY_URL" elif [[ "$TARGET_BASE_URL" == http://* ]]; then # 替换 http:// 为 ws:// TARGET_WSPROXY_URL="${TARGET_BASE_URL/http:\/\//ws:\/\/}" echo "转换 HTTP 到 WS: $TARGET_WSPROXY_URL" else # 假设已经是正确的 WebSocket URL TARGET_WSPROXY_URL="$TARGET_BASE_URL" echo "使用原始 URL (未转换): $TARGET_WSPROXY_URL" fi echo "最终目标 WebSocket 代理: $TARGET_WSPROXY_URL" # 执行网络诊断 check_target_server "$TARGET_BASE_URL" # 创建状态页面目录 (使用 /tmp) HTML_DIR="/tmp/html" mkdir -p "$HTML_DIR" if [ $? -ne 0 ]; then echo "Error: Failed to create directory $HTML_DIR" exit 1 fi # 创建状态页面文件 (写入 /tmp/html) HTML_FILE="$HTML_DIR/index.html" cat > "$HTML_FILE" << EOF Proxy Converter Status

WebSocket 代理转换器状态

状态: 代理转换器正在运行

代理信息:

使用说明

将您的应用配置为使用此 Space 的地址作为 HTTP 代理:

状态页面 (端口 7861) 每30秒自动刷新

EOF if [ $? -ne 0 ]; then echo "Error: Failed to write to $HTML_FILE" exit 1 fi # 设置 gost 日志级别 (info, warn, error, debug, fatal) # LOG_LEVEL="warn" # 注释掉,因为 gost v2.11.5 不支持 -loglevel # --- curl 内部测试 (AFTER gost start,现在测试 SOCKS5) --- echo "====== 开始内部 Curl 测试 (Gost将启动为SOCKS5) ======" INTERNAL_PROXY_URL="socks5://127.0.0.1:7860" # 使用 SOCKS5 TEST_TARGET="https://httpbin.org/ip" echo "测试代理: $INTERNAL_PROXY_URL -> $TEST_TARGET" # curl 对 SOCKS5 的支持可能需要 socks5h 以便代理服务器解析域名 curl -v -k --socks5-hostname "$INTERNAL_PROXY_URL" "$TEST_TARGET" --connect-timeout 15 if [ $? -eq 0 ]; then echo "内部 Curl 测试成功 (Gost已启动为SOCKS5)" else echo "内部 Curl 测试失败 (Gost已启动为SOCKS5) (退出码 $?)" fi echo "====== 结束内部 Curl 测试 (Gost已启动为SOCKS5) ======" # --- 创建健康检查文件 --- # 健康检查服务仍然使用HTTP,因为它只检查端口是否开放 mkdir -p /tmp/health echo "OK" > /tmp/health/healthz cd /tmp/health && python3 -m http.server 7862 & HEALTH_PID=$! # --- 启动gost (改为监听 SOCKS5) --- echo "启动gost SOCKS5 代理 (监听 7860,转发到 $TARGET_WSPROXY_URL)..." /usr/local/bin/gost -L socks5://:7860 -F "$TARGET_WSPROXY_URL" -D & GOST_PID=$! echo "Gost PID: $GOST_PID" echo "等待5秒让gost完全启动..." sleep 5 # --- curl 内部测试 (AFTER SOCKS5 gost start) --- echo "====== 再次运行内部 Curl 测试 (Gost SOCKS5已启动) ======" curl -v -k --socks5-hostname "$INTERNAL_PROXY_URL" "$TEST_TARGET" --connect-timeout 15 if [ $? -eq 0 ]; then echo "内部 Curl SOCKS5 测试成功 (Gost已启动)" else echo "内部 Curl SOCKS5 测试失败 (Gost已启动) (退出码 $?)" fi echo "====== 结束内部 Curl SOCKS5 测试 (Gost已启动) ======" # --- 启动状态页面服务 (改为监听7861) --- # 确保状态页面监听不同端口 HTML_DIR="/tmp/html" echo "Starting status page server (port 7861)..." (cd "$HTML_DIR" && python3 -m http.server 7861) & STATUS_PID=$! sleep 1 # --- 进程检查 --- echo "Checking if gost process (PID: $GOST_PID) started..." if ! kill -0 $GOST_PID > /dev/null 2>&1; then echo "Error: Failed to start or find gost process (PID: $GOST_PID). Exiting." exit 1 fi echo "Checking if status page server (PID: $STATUS_PID) started..." if ! kill -0 $STATUS_PID > /dev/null 2>&1; then echo "Warning: Failed to start or find status page server (PID: $STATUS_PID). Status page might be unavailable." fi echo "Checking if health check server (PID: $HEALTH_PID) started..." if ! kill -0 $HEALTH_PID > /dev/null 2>&1; then echo "Warning: Failed to start or find health check server (PID: $HEALTH_PID). Health checks might fail." fi # --- 运行信息 --- echo "Proxy converter is running..." echo "- Main SOCKS5 proxy listening internally at port 7860" echo "- Status page server running internally at port 7861" echo "- Health check server running internally at port 7862" echo "- Connected to target WebSocket: $TARGET_WSPROXY_URL" # --- 信号处理与等待 --- trap "echo 'Shutting down...'; kill $GOST_PID $STATUS_PID $HEALTH_PID; exit" SIGINT SIGTERM # 等待 gost 进程结束 (主服务进程) wait $GOST_PID EXIT_CODE=$? echo "Gost process exited with code $EXIT_CODE." # 清理后台进程 kill $STATUS_PID $HEALTH_PID > /dev/null 2>&1 exit $EXIT_CODE