From 0d2433d8504e340068a38ee3a7f3799009e5aa02 Mon Sep 17 00:00:00 2001 From: hotyue <52734432+hotyue@users.noreply.github.com> Date: Tue, 21 Apr 2026 06:27:58 +0000 Subject: [PATCH] =?UTF-8?q?feat(security):=20=E5=BC=95=E5=85=A5=E5=8A=A8?= =?UTF-8?q?=E6=80=81=20TLS=20=E9=99=8D=E7=BA=A7=E6=9C=BA=E5=88=B6=E4=B8=8E?= =?UTF-8?q?=E8=87=AA=E7=AD=BE=E5=90=8D=E8=AF=81=E4=B9=A6=EF=BC=8C=E5=85=A8?= =?UTF-8?q?=E5=9F=9F=20Webhook=20=E9=80=9A=E8=AE=AF=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E4=B8=BA=E5=BC=BA=E5=8A=A0=E5=AF=86=20HTTPS=EF=BC=8C=E5=BD=BB?= =?UTF-8?q?=E5=BA=95=E9=98=BB=E6=96=AD=E6=98=8E=E6=96=87=E5=97=85=E6=8E=A2?= =?UTF-8?q?=E9=A3=8E=E9=99=A9=E5=B9=B6=E5=AE=8C=E7=BE=8E=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E5=AE=98=E6=96=B9=E7=BD=91=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/agent_daemon.sh | 38 ++++++++++++++++++++++++++++++++++++++ master/tg_master.sh | 16 ++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/core/agent_daemon.sh b/core/agent_daemon.sh index 6007fe0..fe67485 100755 --- a/core/agent_daemon.sh +++ b/core/agent_daemon.sh @@ -61,6 +61,20 @@ if [ -n "$AGENT_IP" ]; then fi fi +# ================== [v3.6.3 新增: 自动生成自签名 TLS 加密证书] ================== +# [修复] 仅在私有中枢模式下生成证书。官方网关模式下,CF Worker 严格拒绝自签名,必须回退 HTTP +if [ "$TG_TOKEN" != "OFFICIAL_GATEWAY_MODE" ]; then + CERT_FILE="${INSTALL_DIR}/core/cert.pem" + KEY_FILE="${INSTALL_DIR}/core/key.pem" + if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then + echo "🔐 [Agent] 正在生成本地自签名 TLS 加密证书 (2048位 RSA)..." + openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \ + -keyout "$KEY_FILE" -out "$CERT_FILE" \ + -subj "/C=US/O=IP-Sentinel/CN=Agent-Sec" >/dev/null 2>&1 || true + fi +fi +# ============================================================================== + # 3. 启动轻量级 Python3 Webhook 监听服务 (v3.0.4 动态 HMAC 签名防重放) cat > "${INSTALL_DIR}/core/webhook.py" << 'EOF' import http.server @@ -431,6 +445,30 @@ except Exception: ThreadedServer.address_family = socket.AF_INET httpd = ThreadedServer(("0.0.0.0", PORT), AgentHandler) +# ================== [v3.6.3 核心: 挂载 TLS 加密隧道 (动态适配兼容版)] ================== +import ssl +cert_path = '/opt/ip_sentinel/core/cert.pem' +key_path = '/opt/ip_sentinel/core/key.pem' + +# 核心判定:提取配置中的 TOKEN 标识 +is_official_gateway = False +if os.path.exists('/opt/ip_sentinel/config.conf'): + with open('/opt/ip_sentinel/config.conf', 'r') as f: + for line in f: + if line.startswith('TG_TOKEN=') and 'OFFICIAL_GATEWAY_MODE' in line: + is_official_gateway = True + break + +# 仅在非官方网关且证书存在时,才挂载 TLS 装甲 +if not is_official_gateway and os.path.exists(cert_path) and os.path.exists(key_path): + try: + context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) + context.load_cert_chain(certfile=cert_path, keyfile=key_path) + httpd.socket = context.wrap_socket(httpd.socket, server_side=True) + except Exception as e: + print(f"SSL 隧道构建失败,退化为 HTTP: {e}") +# ====================================================================================== + try: httpd.serve_forever() except Exception as e: diff --git a/master/tg_master.sh b/master/tg_master.sh index 0e8276e..14f7785 100755 --- a/master/tg_master.sh +++ b/master/tg_master.sh @@ -65,7 +65,7 @@ generate_signed_url() { local signature=$(echo -n "$payload" | openssl dgst -sha256 -hmac "$CHAT_ID" | awk '{print $NF}') # 返回最终带签名的 URL - echo "http://${target_ip}:${target_port}${action_path}?t=${current_t}&sign=${signature}" + echo "https://${target_ip}:${target_port}${action_path}?t=${current_t}&sign=${signature}" } # ======================================================================== @@ -237,7 +237,7 @@ while true; do send_msg "$CHAT_ID" "📢 **司令部指令下达:正在唤醒全舰队执行 OTA 升级...**%0A*(节点升级成功后会主动发回新的入库确认,请注意查收)*" echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_ota") - curl -s -m 5 "$TARGET_URL" > /dev/null & + curl -k -s -m 5 "$TARGET_URL" > /dev/null & sleep 0.3 # 严格流量削峰 done fi @@ -297,7 +297,7 @@ while true; do send_msg "$CHAT_ID" "📢 **司令部指令下达:正在召唤所有哨兵回传简报...**" echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_report") - curl -s -m 5 "$TARGET_URL" > /dev/null & + curl -k -s -m 5 "$TARGET_URL" > /dev/null & sleep 0.2 # [新增] 流量削峰:每秒最多并发下发 5 个,保护 Master 网络栈 done fi @@ -312,7 +312,7 @@ while true; do send_msg "$CHAT_ID" "📢 **司令部指令下达:正在唤醒所有哨兵执行系统维护...**" echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_run") - curl -s -m 5 "$TARGET_URL" > /dev/null & + curl -k -s -m 5 "$TARGET_URL" > /dev/null & sleep 0.2 # [新增] 流量削峰:防止瞬间 fork 导致句柄耗尽 done fi @@ -436,7 +436,7 @@ while true; do TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_toggle") TARGET_URL="${TARGET_URL}&mod=${MOD_NAME}&state=${TARGET_STATE}" - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") + RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED") if [[ "$RESPONSE" == *"Action Accepted"* ]]; then # 下发成功,更新 DB,原位重绘 db_exec "UPDATE nodes SET enable_${MOD_NAME}='$TARGET_STATE' WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';" @@ -536,7 +536,7 @@ while true; do ALIAS_B64=$(echo -n "$NEW_ALIAS" | base64 | tr -d '\n' | tr '+/' '-_') TARGET_URL="${TARGET_URL}&b64=${ALIAS_B64}" - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") + RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED") if [ "$RESPONSE" == "FAILED" ]; then send_msg "$CHAT_ID" "❌ 指令下发超时!请检查节点连通性。" @@ -576,7 +576,7 @@ while true; do fi TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_ota") - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") + RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED") if [ "$RESPONSE" == "FAILED" ]; then TEXT_RES="❌ OTA 指令下发超时!请检查节点公网连通性。" @@ -617,7 +617,7 @@ while true; do # 🛡️ [v3.0.4] 动态签名生成与触发 (防重放与防篡改) TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_${ACTION_TYPE}") - RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED") + RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED") # 结果判定 if [ "$RESPONSE" == "FAILED" ]; then