Files
2026-05-22 15:21:21 +08:00

72 lines
3.2 KiB
Bash
Executable File

#!/bin/bash
read -p 'Enter the domain or IP: ' DOMAIN
# 核心自签根目录
BASE_DIR="/etc/letsencrypt/self_cert"
CA_DIR="$BASE_DIR/ca"
ARCHIVE_DIR="$BASE_DIR/archive/$DOMAIN"
LIVE_DIR="$BASE_DIR/live/$DOMAIN"
# 一键创建所有相关的自签子目录
mkdir -p "$CA_DIR" "$ARCHIVE_DIR" "$LIVE_DIR"
# [Step 1] 检查或在 self_cert/ca 下生成唯一的持久化 CA
if [[ -f "$CA_DIR/ca.crt" && -f "$CA_DIR/ca.key" ]]; then
echo -e "\e[32m[1/3] Found existing CA in $CA_DIR. Reusing it...\e[0m"
else
echo -e "\e[33m[1/3] No CA found. Generating new persistent CA Root Certificate...\e[0m"
openssl ecparam -genkey -name secp384r1 -out "$CA_DIR/ca.key"
openssl req -x509 -new -nodes -key "$CA_DIR/ca.key" -days 3650 -out "$CA_DIR/ca.crt" -subj "/C=CN/ST=State/L=City/O=UniversalSSL/CN=UniversalRootCA"
fi
# 将全局统一的 CA 复制到当前域名的 archive 目录中作为 chain1.pem
cp "$CA_DIR/ca.crt" "$ARCHIVE_DIR/chain1.pem"
# [Step 2] 生成当前服务的私钥和 CSR 请求
echo -e "\e[33m[2/3] Generating private key and CSR for $DOMAIN...\e[0m"
openssl ecparam -genkey -name secp384r1 -out "$ARCHIVE_DIR/privkey1.pem"
openssl req -new -key "$ARCHIVE_DIR/privkey1.pem" -out "$ARCHIVE_DIR/${DOMAIN}.csr" -subj "/C=CN/ST=State/L=City/O=UniversalService/CN=$DOMAIN"
# [Step 3] 基于统一的 CA 签发万能通用证书
echo -e "\e[33m[3/3] Signing the universal certificate...\e[0m"
cat > "$ARCHIVE_DIR/ext.ini" <<EOF
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyCertSign
extendedKeyUsage = serverAuth, clientAuth, emailProtection, codeSigning, timeStamping
EOF
# 自动判定输入的是 IP 还是域名,防止 OpenSSL 报错
if [[ "$DOMAIN" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "subjectAltName = IP:$DOMAIN" >> "$ARCHIVE_DIR/ext.ini"
else
echo "subjectAltName = DNS:$DOMAIN" >> "$ARCHIVE_DIR/ext.ini"
fi
# 使用位于 self_cert/ca/ 的主公章进行签发
openssl x509 -req -in "$ARCHIVE_DIR/${DOMAIN}.csr" \
-CA "$CA_DIR/ca.crt" -CAkey "$CA_DIR/ca.key" -CAcreateserial \
-out "$ARCHIVE_DIR/cert1.pem" -days 3650 -extfile "$ARCHIVE_DIR/ext.ini"
# 合并生成 fullchain1.pem
cat "$ARCHIVE_DIR/cert1.pem" "$ARCHIVE_DIR/chain1.pem" > "$ARCHIVE_DIR/fullchain1.pem"
# 擦除当前域名的临时残留文件,保持 archive 目录干净
rm -f "$ARCHIVE_DIR/${DOMAIN}.csr" "$ARCHIVE_DIR/ext.ini" "$CA_DIR/ca.srl"
# [Step 4] 在全新的 self_cert/live/ 结构内重建相对路径软链接
echo -e "\e[33mCreating relative symlinks in live directory...\e[0m"
rm -f "$LIVE_DIR/cert.pem" "$LIVE_DIR/privkey.pem" "$LIVE_DIR/chain.pem" "$LIVE_DIR/fullchain.pem"
cd "$LIVE_DIR"
ln -s "../../archive/$DOMAIN/cert1.pem" "cert.pem"
ln -s "../../archive/$DOMAIN/privkey1.pem" "privkey.pem"
ln -s "../../archive/$DOMAIN/chain1.pem" "chain.pem"
ln -s "../../archive/$DOMAIN/fullchain1.pem" "fullchain.pem"
echo -e "\e[32m==================================================\e[0m"
echo -e "\e[32mUniversal Certificates generated successfully!\e[0m"
echo -e "All assets saved under: $BASE_DIR/\e[0m"
echo -e "Your active symlinks: $LIVE_DIR/\e[0m"
echo -e "==================================================\e[0m"