🌐 修复铸渊专线订阅服务连接失败 · 绑定0.0.0.0+Nginx反代+密钥持久化

根因: 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>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-31 05:48:38 +00:00 committed by GitHub
parent 0bdad420a8
commit 6c20c7efb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 19 deletions

View File

@ -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()

View File

@ -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;

View File

@ -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

View File

@ -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`);