4. 为内部 Web 服务器签发服务器证书
任务拆解:从私钥到可用的 HTTPS 站点
本案例的目标是让内部 Web 服务器通过 HTTPS 对外提供服务。完整链路包含四个关键对象:服务器私钥、CSR(证书签名请求)、由中间 CA 签发的服务器证书、以及 Nginx 的 TLS 配置。核心约束是证书必须包含 SAN 扩展,且 SAN 中的 DNS 名称要与浏览器实际访问的地址一致,否则会触发证书名称不匹配告警。
生成服务器私钥与 CSR
在 Web 服务器上创建私钥和 CSR。私钥使用 RSA 2048 位,CSR 中通过 -addext 直接写入 SAN 扩展,避免后续签发时遗漏。
# 1. 生成服务器私钥(不加密,便于 Nginx 自动加载)
openssl genrsa -out server.key 2048
# 2. 生成 CSR,同时写入 SAN 扩展
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=Internal/CN=web.internal" \
-addext "subjectAltName=DNS:web.internal,DNS:www.web.internal,IP:192.168.10.20"
# 3. 确认 CSR 中的 SAN 内容
openssl req -in server.csr -noout -text | grep -A1 "Subject Alternative Name"
执行第 3 条命令后,应看到 DNS:web.internal, DNS:www.web.internal, IP Address:192.168.10.20。如果 SAN 为空,说明 -addext 未生效,需要检查 OpenSSL 版本是否支持该参数(1.1.1 及以上)。
由中间 CA 签发服务器证书
使用中间 CA 的证书和私钥对 CSR 进行签发。签发时通过 -extfile 指定扩展文件,确保 SAN 被写入最终证书。
# 创建扩展配置文件
cat > server_ext.cnf <<'EOF'
basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = DNS:web.internal, DNS:www.web.internal, IP:192.168.10.20
EOF
# 用中间 CA 签发,有效期 825 天
openssl x509 -req -in server.csr \
-CA intermediate.crt -CAkey intermediate.key -CAcreateserial \
-out server.crt -days 825 -sha256 -extfile server_ext.cnf
# 验证签发结果
openssl x509 -in server.crt -noout -text | grep -E "Issuer:|Subject:|DNS:|IP Address:"
签发结果中,Issuer 应为中间 CA 的 Subject,Subject 为 CN=web.internal,且 SAN 中应包含三个条目。若 SAN 缺失,浏览器会直接报 NET::ERR_CERT_COMMON_NAME_INVALID。
配置 Nginx 并测试 HTTPS
将证书链文件合并后配置到 Nginx。注意 ssl_certificate 需要包含服务器证书和中间 CA 证书,顺序为服务器证书在前、中间 CA 在后。
# 合并证书链
cat server.crt intermediate.crt > fullchain.crt
# 设置私钥权限
chmod 600 server.key
chown root:root server.key
# Nginx 配置片段
server {
listen 443 ssl;
server_name web.internal www.web.internal;
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
root /var/www/html;
index index.html;
}
}
配置完成后执行 nginx -t 检查语法,再 nginx -s reload 重载。使用 curl -vk https://web.internal 观察握手过程,重点确认 SSL certificate verify ok 以及证书链中是否包含中间 CA。