convert / start.sh
clash-linux's picture
Upload start.sh
dc23284 verified
#!/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
<!DOCTYPE html>
<html>
<head>
<title>Proxy Converter Status</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
line-height: 1.6;
}
.status {
padding: 15px;
background-color: #d4edda;
border-radius: 5px;
color: #155724;
margin: 20px 0;
border-left: 4px solid #28a745;
}
h1 {
color: #333;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
code {
background: #f4f4f4;
padding: 2px 5px;
border-radius: 3px;
}
.info {
background-color: #e9f5ff;
border-left: 4px solid #0088ff;
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>WebSocket 代理转换器状态</h1>
<div class="status">
<strong>状态:</strong> 代理转换器正在运行
</div>
<div class="info">
<h3>代理信息:</h3>
<ul>
<li><strong>HTTP 代理监听内部端口:</strong> <code>7860</code></li>
<li><strong>目标 WebSocket 代理:</strong> <code>${TARGET_WSPROXY_URL}</code></li>
<li><strong>源自URL:</strong> <code>${TARGET_BASE_URL}</code></li>
</ul>
</div>
<h3>使用说明</h3>
<p>将您的应用配置为使用此 Space 的地址作为 HTTP 代理:</p>
<ul>
<li><strong>主机:</strong> <code>$(hostname)</code> 或 <code>您的Space地址.hf.space</code></li>
<li><strong>端口:</strong> <code>443</code> (推荐, HTTPS) 或 <code>80</code> (HTTP)</li>
<li><strong>类型:</strong> <code>HTTP / HTTPS</code></li>
</ul>
<p><em>状态页面 (端口 7861) 每30秒自动刷新</em></p>
<script>
setTimeout(function() {
location.reload();
}, 30000);
</script>
</body>
</html>
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