From 6c20c7efb4e63555f2fc68636e410632936c76c2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 05:48:38 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20=E4=BF=AE=E5=A4=8D=E9=93=B8?= =?UTF-8?q?=E6=B8=8A=E4=B8=93=E7=BA=BF=E8=AE=A2=E9=98=85=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E5=A4=B1=E8=B4=A5=20=C2=B7=20=E7=BB=91?= =?UTF-8?q?=E5=AE=9A0.0.0.0+Nginx=E5=8F=8D=E4=BB=A3+=E5=AF=86=E9=92=A5?= =?UTF-8?q?=E6=8C=81=E4=B9=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: subscription-server.js绑定127.0.0.1导致外部客户端无法连接 修复: - subscription-server.js: 绑定改为0.0.0.0, getServerHost()增加.env.keys回退 - zhuyuan-sovereign.conf: 添加/api/proxy-sub/反代location块 - deploy-proxy.sh: 新增save_server_host()持久化ZY_SERVER_HOST - deploy-proxy-service.yml: 部署时export ZY_SERVER_HOST Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/f70d170f-1916-4f79-a461-2b674592df30 Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com> --- .github/workflows/deploy-proxy-service.yml | 4 +- server/nginx/zhuyuan-sovereign.conf | 12 ++++++ server/proxy/deploy-proxy.sh | 46 +++++++++++++++++---- server/proxy/service/subscription-server.js | 36 ++++++++++++---- 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/.github/workflows/deploy-proxy-service.yml b/.github/workflows/deploy-proxy-service.yml index 5549ea70..6b2aa4ca 100644 --- a/.github/workflows/deploy-proxy-service.yml +++ b/.github/workflows/deploy-proxy-service.yml @@ -87,7 +87,9 @@ jobs: ssh -i ~/.ssh/id_deploy \ -o StrictHostKeyChecking=accept-new \ ${{ secrets.ZY_SERVER_USER }}@${{ secrets.ZY_SERVER_HOST }} \ - "cd /opt/zhuyuan/proxy-deploy && bash deploy-proxy.sh ${{ github.event.inputs.action }}" + "cd /opt/zhuyuan/proxy-deploy && \ + export ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \ + bash deploy-proxy.sh ${{ github.event.inputs.action }}" - name: '🧹 清理SSH密钥' if: always() diff --git a/server/nginx/zhuyuan-sovereign.conf b/server/nginx/zhuyuan-sovereign.conf index ab1f7d39..73d307d4 100644 --- a/server/nginx/zhuyuan-sovereign.conf +++ b/server/nginx/zhuyuan-sovereign.conf @@ -92,6 +92,18 @@ server { proxy_read_timeout 86400; } + # ─── 铸渊专线订阅服务 (端口 3802) ─── + location /api/proxy-sub/ { + proxy_pass http://127.0.0.1:3802/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + add_header X-Content-Type-Options nosniff always; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + } + # ─── 健康探针 ─── location = /health { proxy_pass http://127.0.0.1:3800/api/health; diff --git a/server/proxy/deploy-proxy.sh b/server/proxy/deploy-proxy.sh index c121140e..4ba5e030 100644 --- a/server/proxy/deploy-proxy.sh +++ b/server/proxy/deploy-proxy.sh @@ -51,6 +51,29 @@ ensure_log_permissions() { chmod 755 "$PROXY_DIR/logs" } +# ── 共用: 保存ZY_SERVER_HOST到.env.keys ── +save_server_host() { + KEYS_FILE="$PROXY_DIR/.env.keys" + if [ -n "${ZY_SERVER_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then + # 检查是否已存在 + if grep -q "^ZY_SERVER_HOST=" "$KEYS_FILE" 2>/dev/null; then + # 更新已有的值 + sed -i "s|^ZY_SERVER_HOST=.*|ZY_SERVER_HOST=${ZY_SERVER_HOST}|" "$KEYS_FILE" + else + # 追加新行 + echo "" >> "$KEYS_FILE" + echo "# 服务器地址 (部署时自动写入)" >> "$KEYS_FILE" + echo "ZY_SERVER_HOST=${ZY_SERVER_HOST}" >> "$KEYS_FILE" + fi + echo " ✅ ZY_SERVER_HOST 已保存到 .env.keys" + elif [ -n "${ZY_SERVER_HOST:-}" ] && [ ! -f "$KEYS_FILE" ]; then + echo " ⚠️ .env.keys 不存在,创建并写入 ZY_SERVER_HOST" + echo "# 服务器地址 (部署时自动写入)" > "$KEYS_FILE" + echo "ZY_SERVER_HOST=${ZY_SERVER_HOST}" >> "$KEYS_FILE" + chmod 600 "$KEYS_FILE" + fi +} + # ── install: 首次完整安装 ───────────────────── install() { echo "" @@ -83,6 +106,7 @@ install() { echo "" echo "═══ [4/7] 部署代理服务代码 ═══" deploy_services + save_server_host echo "" echo "═══ [5/7] 配置Nginx ═══" @@ -166,21 +190,24 @@ deploy_services() { # ── 配置Nginx ───────────────────────────────── configure_nginx() { - # 检查Nginx配置片段是否已添加 + # 检查主Nginx配置是否已有proxy-sub NGINX_CONF="/etc/nginx/sites-enabled/default" - SNIPPET="$REPO_PROXY_DIR/config/nginx-proxy-snippet.conf" - if ! grep -q "proxy-sub" "$NGINX_CONF" 2>/dev/null; then - echo " 添加Nginx代理订阅反向代理..." - # 在最后一个 } 之前插入 - # 注意: 实际应该由铸渊智能合并到主nginx配置 - echo " ⚠️ 请手动将以下配置添加到Nginx:" - echo " $SNIPPET" + if [ -f "$NGINX_CONF" ] && ! grep -q "proxy-sub" "$NGINX_CONF" 2>/dev/null; then + echo " 添加Nginx代理订阅反向代理配置..." + # 在第一个 location = /health 之前插入 proxy-sub location + sed -i '/# ─── 健康探针 ───/{ + # 只在第一次匹配时插入 + i\ # ─── 铸渊专线订阅服务 (端口 3802) ───\n location /api/proxy-sub/ {\n proxy_pass http://127.0.0.1:3802/;\n proxy_http_version 1.1;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n add_header X-Content-Type-Options nosniff always;\n add_header Cache-Control "no-store, no-cache, must-revalidate" always;\n }\n + }' "$NGINX_CONF" || true + echo " ✅ Nginx proxy-sub配置已注入" else - echo " Nginx代理配置已存在" + echo " Nginx代理配置已存在 (或主配置不存在)" fi + if nginx -t 2>/dev/null; then nginx -s reload || true + echo " ✅ Nginx配置验证通过并已重载" fi } @@ -235,6 +262,7 @@ health_check() { update() { echo "更新代理服务..." deploy_services + save_server_host configure_xray ensure_xray_root_user diff --git a/server/proxy/service/subscription-server.js b/server/proxy/service/subscription-server.js index 3cd7e72f..fac774fc 100644 --- a/server/proxy/service/subscription-server.js +++ b/server/proxy/service/subscription-server.js @@ -11,7 +11,7 @@ // - Clash YAML (Clash Verge / ClashMi) // - Base64 URI (Shadowrocket) // -// 端口: 3802 (仅本地访问,通过Nginx反代) +// 端口: 3802 (绑定0.0.0.0,支持外部直连 + Nginx反代) // 认证: URL中的token参数 // // 环境变量 (从 /opt/zhuyuan/proxy/.env.keys 加载): @@ -52,14 +52,32 @@ function loadKeys() { // ── 获取服务器IP ──────────────────────────── // ⚠️ 仓库公开,不在代码中硬编码IP -// 从环境变量读取,部署时由PM2或GitHub Secrets注入 +// 优先级: 环境变量 > .env.keys文件 > 回退 function getServerHost() { - const host = process.env.ZY_SERVER_HOST; - if (!host) { - console.error('⚠️ ZY_SERVER_HOST 未设置'); - return '0.0.0.0'; + // 1. 优先从环境变量读取 + if (process.env.ZY_SERVER_HOST) { + return process.env.ZY_SERVER_HOST; } - return host; + + // 2. 从.env.keys文件读取 + try { + const content = fs.readFileSync(KEYS_FILE, 'utf8'); + for (const line of content.split('\n')) { + if (line.startsWith('#') || !line.includes('=')) continue; + const [key, ...vals] = line.split('='); + if (key.trim() === 'ZY_SERVER_HOST') { + const val = vals.join('=').trim(); + if (val) return val; + } + } + } catch (err) { + if (err.code !== 'ENOENT') { + console.error(`⚠️ 读取 ${KEYS_FILE} 失败: ${err.code || err.message}`); + } + } + + console.error('⚠️ ZY_SERVER_HOST 未设置 (环境变量和.env.keys均未找到)'); + return '0.0.0.0'; } // ── 读取流量配额信息 ──────────────────────── @@ -282,8 +300,8 @@ const server = http.createServer((req, res) => { res.end('Not Found'); }); -server.listen(PORT, '127.0.0.1', () => { - console.log(`🌐 铸渊专线订阅服务已启动: http://127.0.0.1:${PORT}`); +server.listen(PORT, '0.0.0.0', () => { + console.log(`🌐 铸渊专线订阅服务已启动: http://0.0.0.0:${PORT}`); console.log(` 订阅端点: /sub/{token}`); console.log(` 配额查询: /quota`); console.log(` 健康检查: /health`);