我家的方案是路由器部署了 nginx
然后用 acme 使用 dns_api 的方式申请和续订证书,域名在 dnspod 注册的
然后写了一个脚本来生成自签名 ca 证书给内网 ip 签发:
#!/bin/sh
# 检查 openssl 版本
OPENSSL_VERSION=$(openssl version | awk '{print $2}')
REQUIRED_VERSION="3.0.0"
echo "OpenSSL 版本为 $OPENSSL_VERSION"
if [ "$(printf '%s\n' "$REQUIRED_VERSION" "$OPENSSL_VERSION" | sort -V | head -n1)" != "$REQUIRED_VERSION" ]; then
echo "OpenSSL 版本低于 $REQUIRED_VERSION,无法继续。"
exit 1
fi
# 检查当前目录下是否存在 ca.key 和 ca.crt 文件
if [ -f "ca.key" ] && [ -f "ca.crt" ]; then
# 提取证书和私钥的公钥指纹
CRT_PUB_KEY=$(openssl x509 -in ca.crt -noout -pubkey | openssl pkey -pubin -outform DER | openssl dgst -sha256)
KEY_PUB_KEY=$(openssl ec -in ca.key -pubout -outform DER | openssl dgst -sha256)
if [ "$CRT_PUB_KEY" != "$KEY_PUB_KEY" ]; then
echo "ca.crt 和 ca.key 不匹配,无法继续。"
exit 1
fi
CREATETIME=$(openssl x509 -in ca.crt -noout -startdate | cut -d'=' -f2)
EXPIRETIME=$(openssl x509 -in ca.crt -noout -enddate | cut -d'=' -f2)
CA=$(openssl x509 -in ca.crt -noout -subject | sed -n 's/.*CN[[:space:]]*=[[:space:]]*\(.*\)/\1/p')
echo "存在的 CA 证书信息:"
echo "创建时间:$CREATETIME"
echo "过期时间:$EXPIRETIME"
echo "CN:$CA"
echo "是否创建新的 CA 证书?(y/n, 默认为 n):"
read CREATE_NEW_CA
if [ "$CREATE_NEW_CA" = "y" ]; then
CREATETIME=$(date -d "$CREATETIME" +"%Y%m%d%H%M%S")
EXPIRETIME=$(date -d "$EXPIRETIME" +"%Y%m%d%H%M%S")
mv ca.key "${CA}.${CREATETIME}-${EXPIRETIME}.ca.key"
mv ca.crt "${CA}.${CREATETIME}-${EXPIRETIME}.ca.crt"
fi
else
CREATE_NEW_CA=y
fi
if [ "$CREATE_NEW_CA" = "y" ]; then
# 生成新的 CA 证书
echo "请输入根证书 CN:"
read CA
openssl ecparam -genkey -name prime256v1 -out ca.key
openssl req -x509 -sha256 -new -nodes -key ca.key -days 3650 -out ca.crt -subj "/CN=${CA}" -addext "subjectAltName=DNS:${CA}"
fi
# 生成要签名的证书
echo "请输入要签名的证书 CN:"
read CN
generate_bundle_and_pkcs12() {
local format=$1
local cn=$2
echo "是否生成打包证书?(y/n, 默认为 n):"
read CREATE_BUNDLE
if [ "$CREATE_BUNDLE" = "y" ]; then
cat "${cn}.${format}.crt" "${cn}.${format}.key" > "${cn}.${format}.bundle.pem"
fi
echo "是否生成 pkcs12 证书?(y/n, 默认为 n):"
read CREATE_PKCS12
if [ "$CREATE_PKCS12" = "y" ]; then
openssl pkcs12 -export -in "${cn}.${format}.crt" -inkey "${cn}.${format}.key" -out "${cn}.${format}.p12" -passout pass:
fi
}
while true; do
echo "请选择要签名的证书格式:"
echo "1. ecc"
echo "2. rsa"
read CERT_FORMAT
if [ "$CERT_FORMAT" = "1" ]; then
openssl ecparam -genkey -name prime256v1 -out "${CN}.ecc.key"
openssl req -sha256 -new -key "${CN}.ecc.key" -out "${CN}.ecc.csr" -subj "/CN=${CN}" -addext "subjectAltName=DNS:${CN}"
openssl x509 -sha256 -req -in "${CN}.ecc.csr" -CA ca.crt -CAkey ca.key -CAcreateserial -out "${CN}.ecc.crt" -days 3650 -extensions v3_req -extfile /etc/ssl/openssl.cnf
generate_bundle_and_pkcs12 "ecc" "$CN"
break
elif [ "$CERT_FORMAT" = "2" ]; then
while true; do
echo "请选择生成的密钥长度:"
echo "1. 4096"
echo "2. 2048"
read KEY_LENGTH
if [ "$KEY_LENGTH" = "1" ]; then
openssl genpkey -algorithm RSA -out "${CN}.rsa.key" -pkeyopt rsa_keygen_bits:4096
break
elif [ "$KEY_LENGTH" = "2" ]; then
openssl genpkey -algorithm RSA -out "${CN}.rsa.key" -pkeyopt rsa_keygen_bits:2048
break
else
echo "无效的选择。"
fi
done
openssl req -sha256 -new -key "${CN}.rsa.key" -out "${CN}.rsa.csr" -subj "/CN=${CN}" -addext "subjectAltName=DNS:${CN}"
openssl x509 -sha256 -req -in "${CN}.rsa.csr" -CA ca.crt -CAkey ca.key -CAcreateserial -out "${CN}.rsa.crt" -days 3650 -extensions v3_req -extfile /etc/ssl/openssl.cnf
generate_bundle_and_pkcs12 "rsa" "$CN"
break
else
echo "无效的选择。"
fi
done
echo "证书生成完成。"
echo "反代时配置 nginx proxy_ssl_trusted_certificate 信任 ca.crt 文件。"
echo "将 ${CN}.ecc.crt 或 ${CN}.rsa.crt 用作原服务器 ssl 证书。"
echo "将 ${CN}.ecc.key 或 ${CN}.rsa.key 用作原服务器 ssl 密钥。"
自签名证书是10年的,给ha用,然后nginx 反代 ha ,这段通信也走了 https
正常使用时用nginx的域名就行。 |