#!/bin/bash # ═══════════════════════════════════════════════ # 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 # 📜 Copyright: 国作登字-2026-A-00037559 # ═══════════════════════════════════════════════ # server/proxy/setup/generate-keys.sh # 🔑 生成Xray VLESS + Reality所需的所有密钥 # # 输出: # - UUID (VLESS用户ID) # - Reality X25519密钥对 (私钥/公钥) # - Reality ShortId # - 订阅访问Token # # ⚠️ 生成的密钥需要添加到GitHub Secrets # ═══════════════════════════════════════════════ set -uo pipefail # 注意: 不使用 set -e,手动处理错误以确保密钥生成的健壮性 # 清理临时文件 _TMPFILES=() cleanup_tmp() { for f in "${_TMPFILES[@]}"; do rm -f "$f" 2>/dev/null; done; } trap cleanup_tmp EXIT # 工具函数: 将二进制数据转为base64url编码 to_base64url() { base64 | tr '+/' '-_' | tr -d '=' } echo "════════════════════════════════════════" echo "🔑 铸渊专线 · 密钥生成" echo "════════════════════════════════════════" echo "" HAS_ERROR=0 # ── 生成UUID ───────────────────────────────── UUID=$(xray uuid 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || openssl rand -hex 16 | sed 's/\(.\{8\}\)\(.\{4\}\)\(.\{4\}\)\(.\{4\}\)\(.\{12\}\)/\1-\2-\3-\4-\5/') echo "ZY_PROXY_UUID=$UUID" # ── 生成Reality X25519密钥对 ────────────────── PRIVATE_KEY="" PUBLIC_KEY="" # 方法1: 使用 xray x25519 if command -v xray &>/dev/null; then echo " 尝试 xray x25519 ..." KEYS_OUTPUT="" KEYS_STDERR="" # 捕获stdout和stderr分别处理 KEYS_STDERR_FILE=$(mktemp) _TMPFILES+=("$KEYS_STDERR_FILE") KEYS_OUTPUT=$(xray x25519 2>"$KEYS_STDERR_FILE") || true KEYS_STDERR=$(cat "$KEYS_STDERR_FILE" 2>/dev/null) || true rm -f "$KEYS_STDERR_FILE" # 如果stdout为空,尝试从stderr获取(某些版本输出到stderr) if [ -z "$KEYS_OUTPUT" ] && [ -n "$KEYS_STDERR" ]; then echo " xray x25519 输出在stderr,自动切换" KEYS_OUTPUT="$KEYS_STDERR" fi if [ -n "$KEYS_OUTPUT" ]; then # 灵活解析: 支持多种输出格式 # 格式1: "Private key: " (标准格式) # 格式2: "PrivateKey: " # 格式3: 仅输出两行key PRIVATE_KEY=$(echo "$KEYS_OUTPUT" | grep -i "private" | awk '{print $NF}') || true PUBLIC_KEY=$(echo "$KEYS_OUTPUT" | grep -i "public" | awk '{print $NF}') || true # 如果上面的解析失败,尝试按行解析(假设第一行私钥第二行公钥) if [ -z "$PRIVATE_KEY" ]; then LINE_COUNT=$(echo "$KEYS_OUTPUT" | wc -l) if [ "$LINE_COUNT" -ge 2 ]; then PRIVATE_KEY=$(echo "$KEYS_OUTPUT" | sed -n '1p' | awk '{print $NF}') PUBLIC_KEY=$(echo "$KEYS_OUTPUT" | sed -n '2p' | awk '{print $NF}') fi fi fi if [ -n "$PRIVATE_KEY" ] && [ -n "$PUBLIC_KEY" ]; then echo " ✅ xray x25519 密钥生成成功" else echo " ⚠️ xray x25519 解析失败" if [ -n "$KEYS_OUTPUT" ]; then echo " stdout: $KEYS_OUTPUT" fi if [ -n "$KEYS_STDERR" ]; then echo " stderr: $KEYS_STDERR" fi PRIVATE_KEY="" PUBLIC_KEY="" fi fi # 方法2: 使用 openssl 生成 X25519 密钥 if [ -z "$PRIVATE_KEY" ] && command -v openssl &>/dev/null; then echo " 尝试 openssl X25519 ..." TMPKEY=$(mktemp) if openssl genpkey -algorithm X25519 -out "$TMPKEY" 2>/dev/null; then # 从DER格式提取原始32字节密钥,转为base64url (43字符) PRIVATE_KEY=$(openssl pkey -in "$TMPKEY" -outform DER 2>/dev/null \ | tail -c 32 | to_base64url) || true PUBLIC_KEY=$(openssl pkey -in "$TMPKEY" -pubout -outform DER 2>/dev/null \ | tail -c 32 | to_base64url) || true fi rm -f "$TMPKEY" if [ -n "$PRIVATE_KEY" ]; then echo " ✅ openssl X25519 密钥生成成功" if [ -z "$PUBLIC_KEY" ]; then PUBLIC_KEY="(需要在服务器上运行 xray x25519 重新生成公钥)" fi else echo " ⚠️ openssl X25519 生成失败" fi fi # 方法3: 最终兜底 - 生成随机占位密钥 if [ -z "$PRIVATE_KEY" ]; then echo " ⚠️ 所有X25519生成方法均失败,使用随机占位密钥" echo " ⚠️ 请在服务器上手动运行: xray x25519" echo " ⚠️ Reality公钥为占位符,VPN不可用直到手动替换" PRIVATE_KEY=$(openssl rand 32 | to_base64url | head -c 43) PUBLIC_KEY="PLACEHOLDER_REGENERATE_WITH_XRAY_X25519" HAS_ERROR=1 fi echo "" echo "ZY_PROXY_REALITY_PRIVATE_KEY=$PRIVATE_KEY" if [ "$PUBLIC_KEY" = "PLACEHOLDER_REGENERATE_WITH_XRAY_X25519" ]; then echo "ZY_PROXY_REALITY_PUBLIC_KEY=$PUBLIC_KEY" echo "" echo "❌ 公钥生成失败!请在服务器上手动执行以下步骤:" echo " 1. SSH到服务器: ssh root@your-server" echo " 2. 运行: xray x25519" echo " 3. 将输出的Public key添加到GitHub Secrets: ZY_PROXY_REALITY_PUBLIC_KEY" else echo "ZY_PROXY_REALITY_PUBLIC_KEY=$PUBLIC_KEY" fi # ── 生成ShortId ────────────────────────────── SHORT_ID=$(openssl rand -hex 8 || head -c 8 /dev/urandom | xxd -p) echo "ZY_PROXY_REALITY_SHORT_ID=$SHORT_ID" # ── 生成订阅Token ──────────────────────────── SUB_TOKEN=$(openssl rand -hex 32 || head -c 32 /dev/urandom | xxd -p) echo "ZY_PROXY_SUB_TOKEN=$SUB_TOKEN" echo "" echo "════════════════════════════════════════" echo "⚠️ 请将以上密钥添加到 GitHub Secrets" echo "" echo " 需要添加的Secrets:" echo " ZY_PROXY_UUID" echo " ZY_PROXY_REALITY_PRIVATE_KEY" echo " ZY_PROXY_REALITY_PUBLIC_KEY" echo " ZY_PROXY_REALITY_SHORT_ID" echo " ZY_PROXY_SUB_TOKEN" echo "" echo " ⚠️ 这些密钥仅在此处显示一次" echo " ⚠️ 请立即复制到安全位置" echo "════════════════════════════════════════" # ── 保存到服务器本地(仅root可读) ────────────── KEYS_FILE="/opt/zhuyuan/proxy/.env.keys" mkdir -p /opt/zhuyuan/proxy cat > "$KEYS_FILE" < 'xray x25519'" echo " 然后更新 $KEYS_FILE 和 GitHub Secrets" fi