Merge pull request #273 from qinfendebingshuo/copilot/fix-vpn-deployment-issues
铸渊专线: fix shell injection, SMTP persistence, and incomplete config loading
This commit is contained in:
commit
557a49313c
|
|
@ -91,6 +91,8 @@ jobs:
|
|||
"cd /opt/zhuyuan/proxy-deploy && \
|
||||
export ZY_SERVER_HOST='${{ secrets.ZY_SERVER_HOST }}' && \
|
||||
export ZY_CN_RELAY_HOST='${{ secrets.ZY_CN_SERVER_HOST }}' && \
|
||||
export ZY_SMTP_USER='${{ secrets.ZY_SMTP_USER }}' && \
|
||||
export ZY_SMTP_PASS='${{ secrets.ZY_SMTP_PASS }}' && \
|
||||
bash deploy-proxy.sh ${{ github.event.inputs.action }}"
|
||||
|
||||
- name: '🧹 清理SSH密钥'
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ ensure_log_permissions() {
|
|||
chmod 755 "$PROXY_DIR/logs"
|
||||
}
|
||||
|
||||
# ── 共用: 保存ZY_SERVER_HOST到.env.keys ──
|
||||
# ── 共用: 保存环境变量到.env.keys ──
|
||||
save_server_host() {
|
||||
KEYS_FILE="$PROXY_DIR/.env.keys"
|
||||
if [ -n "${ZY_SERVER_HOST:-}" ] && [ -f "$KEYS_FILE" ]; then
|
||||
|
|
@ -84,6 +84,28 @@ save_server_host() {
|
|||
fi
|
||||
echo " ✅ ZY_CN_RELAY_HOST 已保存到 .env.keys"
|
||||
fi
|
||||
|
||||
# 保存SMTP凭据 (如果有) — 使守护Agent和流量监控可发送告警邮件
|
||||
# 注: 使用删除+追加方式避免sed特殊字符问题 (密码常含|&/$等)
|
||||
if [ -n "${ZY_SMTP_USER:-}" ] && [ -f "$KEYS_FILE" ]; then
|
||||
if grep -q "^ZY_SMTP_USER=" "$KEYS_FILE" 2>/dev/null; then
|
||||
grep -v "^ZY_SMTP_USER=" "$KEYS_FILE" > "${KEYS_FILE}.tmp" && mv "${KEYS_FILE}.tmp" "$KEYS_FILE"
|
||||
else
|
||||
echo "" >> "$KEYS_FILE"
|
||||
echo "# SMTP凭据 (部署时自动写入·守护Agent告警用)" >> "$KEYS_FILE"
|
||||
fi
|
||||
printf '%s\n' "ZY_SMTP_USER=${ZY_SMTP_USER}" >> "$KEYS_FILE"
|
||||
chmod 600 "$KEYS_FILE"
|
||||
echo " ✅ ZY_SMTP_USER 已保存到 .env.keys"
|
||||
fi
|
||||
if [ -n "${ZY_SMTP_PASS:-}" ] && [ -f "$KEYS_FILE" ]; then
|
||||
if grep -q "^ZY_SMTP_PASS=" "$KEYS_FILE" 2>/dev/null; then
|
||||
grep -v "^ZY_SMTP_PASS=" "$KEYS_FILE" > "${KEYS_FILE}.tmp" && mv "${KEYS_FILE}.tmp" "$KEYS_FILE"
|
||||
fi
|
||||
printf '%s\n' "ZY_SMTP_PASS=${ZY_SMTP_PASS}" >> "$KEYS_FILE"
|
||||
chmod 600 "$KEYS_FILE"
|
||||
echo " ✅ ZY_SMTP_PASS 已保存到 .env.keys"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── install: 首次完整安装 ─────────────────────
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ module.exports = {
|
|||
instances: 1,
|
||||
env: {
|
||||
NODE_ENV: 'production',
|
||||
ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data'
|
||||
ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data',
|
||||
ZY_PROXY_KEYS_FILE: '/opt/zhuyuan/proxy/.env.keys'
|
||||
},
|
||||
max_memory_restart: '64M',
|
||||
log_file: '/opt/zhuyuan/proxy/logs/monitor.log',
|
||||
|
|
@ -43,7 +44,8 @@ module.exports = {
|
|||
env: {
|
||||
NODE_ENV: 'production',
|
||||
ZY_PROXY_DATA_DIR: '/opt/zhuyuan/proxy/data',
|
||||
ZY_PROXY_LOG_DIR: '/opt/zhuyuan/proxy/logs'
|
||||
ZY_PROXY_LOG_DIR: '/opt/zhuyuan/proxy/logs',
|
||||
ZY_PROXY_KEYS_FILE: '/opt/zhuyuan/proxy/.env.keys'
|
||||
},
|
||||
max_memory_restart: '128M',
|
||||
log_file: '/opt/zhuyuan/proxy/logs/guardian.log',
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { execSync, exec } = require('child_process');
|
||||
const { execSync, execFileSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const https = require('https');
|
||||
|
|
@ -275,10 +275,11 @@ async function consultLLM(issue) {
|
|||
function sendAlertEmail(subject, body) {
|
||||
try {
|
||||
const sendScript = path.join(__dirname, 'send-subscription.js');
|
||||
execSync(
|
||||
`node "${sendScript}" alert "${subject}\n\n${body}"`,
|
||||
{ encoding: 'utf8', timeout: 30000 }
|
||||
);
|
||||
// 使用execFileSync避免Shell命令注入 (不经过shell解释器)
|
||||
execFileSync('node', [sendScript, 'alert', `${subject}\n\n${body}`], {
|
||||
encoding: 'utf8',
|
||||
timeout: 30000
|
||||
});
|
||||
console.log('[守护Agent] 告警邮件已发送');
|
||||
} catch (err) {
|
||||
console.error('[守护Agent] 邮件发送失败:', err.message);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ const path = require('path');
|
|||
const KEYS_FILE = process.env.ZY_PROXY_KEYS_FILE || '/opt/zhuyuan/proxy/.env.keys';
|
||||
|
||||
// ── 加载配置 ─────────────────────────────────
|
||||
// 优先级: 环境变量 > .env.keys文件
|
||||
// 通用读取所有键值对,确保guardian/monitor等服务也能获取完整配置
|
||||
function loadConfig() {
|
||||
const config = {
|
||||
smtp_user: process.env.ZY_SMTP_USER || '',
|
||||
|
|
@ -37,13 +39,21 @@ function loadConfig() {
|
|||
sub_token: process.env.ZY_PROXY_SUB_TOKEN || ''
|
||||
};
|
||||
|
||||
// 尝试从本地密钥文件读取Token
|
||||
// 从.env.keys文件读取所有键值对(环境变量未设置时回退)
|
||||
try {
|
||||
const content = fs.readFileSync(KEYS_FILE, 'utf8');
|
||||
for (const line of content.split('\n')) {
|
||||
if (line.startsWith('ZY_PROXY_SUB_TOKEN=')) {
|
||||
config.sub_token = line.split('=')[1].trim();
|
||||
}
|
||||
if (line.startsWith('#') || !line.includes('=')) continue;
|
||||
const [key, ...vals] = line.split('=');
|
||||
const k = key.trim();
|
||||
const v = vals.join('=').trim();
|
||||
if (!v) continue;
|
||||
|
||||
// 仅在环境变量未设置时使用文件中的值
|
||||
if (k === 'ZY_PROXY_SUB_TOKEN' && !config.sub_token) config.sub_token = v;
|
||||
if (k === 'ZY_SERVER_HOST' && !config.server_host) config.server_host = v;
|
||||
if (k === 'ZY_SMTP_USER' && !config.smtp_user) config.smtp_user = v;
|
||||
if (k === 'ZY_SMTP_PASS' && !config.smtp_pass) config.smtp_pass = v;
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const { execSync, execFileSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
|
|
@ -177,10 +177,11 @@ async function sendAlert(alert, quota) {
|
|||
const usedGB = ((quota.upload_bytes + quota.download_bytes) / (1024 ** 3)).toFixed(2);
|
||||
const totalGB = (quota.total_bytes / (1024 ** 3)).toFixed(0);
|
||||
|
||||
execSync(
|
||||
`node "${sendScript}" alert "${alert.message} 已用 ${usedGB}GB / ${totalGB}GB"`,
|
||||
{ encoding: 'utf8', timeout: 30000 }
|
||||
);
|
||||
// 使用execFileSync避免Shell命令注入 (不经过shell解释器)
|
||||
execFileSync('node', [sendScript, 'alert', `${alert.message} 已用 ${usedGB}GB / ${totalGB}GB`], {
|
||||
encoding: 'utf8',
|
||||
timeout: 30000
|
||||
});
|
||||
console.log(`[流量监控] 告警邮件已发送: ${alert.level}`);
|
||||
} catch (err) {
|
||||
console.error('[流量监控] 告警邮件发送失败:', err.message);
|
||||
|
|
|
|||
Loading…
Reference in New Issue