完整脚本:生成 CA 并签署网站证书
#!/bin/bash
# 配置信息 下面变量按需更改
CA_DIR="/etc/pki/CA"
WEB_DIR="/etc/pki/tls"
CA_CN="MyCompany Root CA"
WEB_DOMAIN="www.a.com"
COUNTRY="CN"
STATE="Beijing"
CITY="Beijing"
ORG="MyCompany"
OU="IT Department"
EMAIL="admin@${WEB_DOMAIN}"
CA_DAYS=3650 # CA证书有效期(10年)
WEB_DAYS=730 # 网站证书有效期(2年)
# 创建目录结构
mkdir -p ${CA_DIR}/{private,certs,csr,newcerts,crl} \
${WEB_DIR}/{private,certs,csr}
chmod 700 ${CA_DIR}/private ${WEB_DIR}/private
# 初始化CA数据库
touch ${CA_DIR}/index.txt
echo "01" > ${CA_DIR}/serial
echo "01" > ${CA_DIR}/crlnumber
# 配置文件路径
CA_CONFIG="${CA_DIR}/openssl.cnf"
WEB_CONFIG="${WEB_DIR}/openssl.cnf"
# 创建CA配置文件
cat > ${CA_CONFIG} << EOF
[ ca ]
default_ca = CA_default
[ CA_default ]
dir = ${CA_DIR}
certs = \$dir/certs
crl_dir = \$dir/crl
database = \$dir/index.txt
new_certs_dir = \$dir/newcerts
certificate = \$dir/certs/ca.crt
private_key = \$dir/private/ca.key
serial = \$dir/serial
crlnumber = \$dir/crlnumber
crl = \$dir/crl/crl.pem
default_days = ${CA_DAYS}
default_crl_days= 30
default_md = sha256
policy = policy_strict
[ policy_strict ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 4096
default_keyfile = ca.key
distinguished_name = req_distinguished_name
string_mask = utf8only
x509_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
[ v3_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_server ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = ${WEB_DOMAIN}
DNS.2 = ${WEB_DOMAIN#*.} # 泛域名支持
EOF
# 创建网站证书配置文件
cat > ${WEB_CONFIG} << EOF
[ req ]
default_bits = 2096
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_req
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
[ req_ext ]
subjectAltName = @alt_names
[ v3_req ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = ${WEB_DOMAIN}
DNS.2 = ${WEB_DOMAIN#*.}
EOF
# 生成CA私钥(带密码保护)
echo "正在生成CA私钥..."
openssl genrsa -aes256 -out ${CA_DIR}/private/ca.key 4096
chmod 400 ${CA_DIR}/private/ca.key
# 生成CA证书
echo "正在生成CA证书..."
openssl req -new -x509 -days ${CA_DAYS} -key ${CA_DIR}/private/ca.key \
-out ${CA_DIR}/certs/ca.crt -config ${CA_CONFIG} \
-subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/CN=${CA_CN}" \
-extensions v3_ca
# 生成网站私钥
echo "正在生成网站私钥..."
openssl genrsa -out ${WEB_DIR}/private/${WEB_DOMAIN}.key 2048
chmod 400 ${WEB_DIR}/private/${WEB_DOMAIN}.key
# 生成网站证书请求
echo "正在生成网站证书请求..."
openssl req -new -key ${WEB_DIR}/private/${WEB_DOMAIN}.key \
-out ${WEB_DIR}/csr/${WEB_DOMAIN}.csr -config ${WEB_CONFIG} \
-subj "/C=${COUNTRY}/ST=${STATE}/L=${CITY}/O=${ORG}/OU=${OU}/CN=${WEB_DOMAIN}/emailAddress=${EMAIL}"
# 使用CA签署网站证书
echo "正在使用CA签署网站证书..."
openssl ca -batch -config ${CA_CONFIG} -extensions v3_server \
-days ${WEB_DAYS} -notext -in ${WEB_DIR}/csr/${WEB_DOMAIN}.csr \
-out ${WEB_DIR}/certs/${WEB_DOMAIN}.crt
# 生成证书链文件(包含CA证书)
echo "正在生成证书链文件..."
cat ${WEB_DIR}/certs/${WEB_DOMAIN}.crt ${CA_DIR}/certs/ca.crt > \
${WEB_DIR}/certs/${WEB_DOMAIN}.chain.crt
# 生成吊销列表
echo "正在生成证书吊销列表..."
openssl ca -gencrl -out ${CA_DIR}/crl/crl.pem -config ${CA_CONFIG}
echo "证书生成完成!"
echo "CA证书: ${CA_DIR}/certs/ca.crt"
echo "网站证书: ${WEB_DIR}/certs/${WEB_DOMAIN}.crt"
echo "网站私钥: ${WEB_DIR}/private/${WEB_DOMAIN}.key"
echo "证书链: ${WEB_DIR}/certs/${WEB_DOMAIN}.chain.crt"
使用说明
- 保存脚本:将上述代码保存为
generate-ssl-certs.sh
- 赋予执行权限:
chmod +x generate-ssl-certs.sh
- 运行脚本:
sudo ./generate-ssl-certs.sh
- 按提示输入 CA 私钥密码(建议使用强密码)
生成的证书文件
- CA 证书:
/etc/pki/CA/certs/ca.crt
- 网站证书:
/etc/pki/tls/certs/www.a.com.crt
- 网站私钥:
/etc/pki/tls/private/www.a.com.key
- 证书链:
/etc/pki/tls/certs/www.a.com.chain.crt
(包含网站证书和 CA 证书)
配置 Nginx 使用证书
server {
listen 443 ssl http2;
server_name www.a.com;
ssl_certificate /etc/pki/tls/certs/www.a.com.chain.crt;
ssl_certificate_key /etc/pki/tls/private/www.a.com.key;
# 安全强化配置
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256";
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# 其他配置...
}
安全注意事项
-
CA 私钥安全:
- 生成后立即备份到安全位置(如离线存储)
- 限制访问权限:
chmod 400 /etc/pki/CA/private/ca.key
-
证书有效期:
- CA 证书设置为 10 年,网站证书设置为 2 年
- 建立证书监控和续期机制
-
客户端信任:
- 将 CA 证书(
ca.crt
)分发给客户端并导入受信任的根证书存储区
- 将 CA 证书(
这个脚本实现了完整的 CA 证书和网站证书生成流程,遵循了最佳安全实践,适用于生产环境的内部系统或测试环境。