OpenSSL 自签证书
环境准备
请确认你的操作系统已安装 OpenSSL(推荐 3.x 版本):
openssl version如果版本低于 1.1.1,建议升级至最新版本以获得对 TLS 1.3 和更强加密算法的支持。
1. 生成 Root CA(根证书)
根证书是整个信任链的基础。我们使用椭圆曲线(ECC)算法 secp384r1,相比传统 RSA 密钥更短、性能更好、安全性更高。
1.1 生成 CA 私钥
openssl ecparam -name secp384r1 -genkey -noout -out rootCA.key| 参数 | 说明 |
| ecparam | 椭圆曲线密钥参数命令 |
| -name secp384r1 | 选择 NIST P-384 椭圆曲线(推荐,安全性等效 RSA 7680 位) |
| -genkey | 生成密钥 |
| -noout | 不输出参数到标准输出 |
| -out rootCA.key | 私钥输出文件 |
设置私钥文件权限,确保安全:
chmod 400 rootCA.key1.2 生成自签名 CA 证书
openssl req -x509 -new -nodes -key rootCA.key -sha384 -days 3650 \
-out rootCA.crt \
-subj "/C=CN/O=MyOrg/CN=MyECCRootCA"| 参数 | 说明 |
| -x509 | 输出自签名 X.509 证书(而非 CSR) |
| -sha384 | 使用 SHA-384 摘要算法(配合 ECC P-384 推荐) |
| -days 3650 | 有效期 10 年 |
| -subj | 证书主题,可根据实际情况自定义 |
💡 产出文件:rootCA.key(CA 私钥,严格保密)、rootCA.crt(CA 公钥证书,可分发)
2. 生成服务端证书
2.1 生成服务端私钥
openssl ecparam -name secp384r1 -genkey -noout -out server.key
chmod 400 server.key2.2 创建 OpenSSL 配置文件(推荐方式)
使用配置文件可以更清晰地管理 SAN(Subject Alternative Name)等扩展字段,避免命令行过长且容易出错。
创建 server.cnf:
[req]
prompt = no
distinguished_name = dn
req_extensions = v3_req
[dn]
C = CN
O = MyOrg
CN = www.example.com
[v3_req]
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
IP.1 = 127.0.0.1⚠️ subjectAltName(SAN)是现代浏览器和客户端验证证书的关键字段,仅设置 CN 已不被信任。务必在 SAN 中列出所有需要的域名和 IP。
2.3 生成服务端证书请求(CSR)
openssl req -new -key server.key -out server.csr -config server.cnf2.4 使用 CA 签发服务端证书
创建签发用扩展文件 server_ext.cnf:
subjectAltName = @alt_names
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[alt_names]
DNS.1 = www.example.com
DNS.2 = example.com
IP.1 = 127.0.0.1签发证书:
openssl x509 -req -in server.csr \
-CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-out server.crt -days 825 -sha384 \
-extfile server_ext.cnf📌 Apple 等平台要求 TLS 服务端证书有效期不超过 825 天,建议遵循此限制以保证最大兼容性。
3. 生成客户端证书(mTLS 双向认证)
如果你需要双向 TLS(mTLS),还需为客户端生成证书。
3.1 生成客户端私钥
openssl ecparam -name secp384r1 -genkey -noout -out client.key
chmod 400 client.key3.2 创建客户端配置文件
创建 client.cnf:
[req]
prompt = no
distinguished_name = dn
req_extensions = v3_req
[dn]
C = CN
O = MyOrg
CN = client.local
[v3_req]
subjectAltName = DNS:client.local
keyUsage = digitalSignature
extendedKeyUsage = clientAuth3.3 生成客户端 CSR 并签发
openssl req -new -key client.key -out client.csr -config client.cnf创建签发用扩展文件 client_ext.cnf:
subjectAltName = DNS:client.local
keyUsage = digitalSignature
extendedKeyUsage = clientAuth签发客户端证书:
openssl x509 -req -in client.csr \
-CA rootCA.crt -CAkey rootCA.key -CAcreateserial \
-out client.crt -days 825 -sha384 \
-extfile client_ext.cnf4. 验证证书
查看证书详细信息:
openssl x509 -in server.crt -text -noout验证证书链是否正确:
openssl verify -CAfile rootCA.crt server.crt
openssl verify -CAfile rootCA.crt client.crt5. 证书文件说明
| 文件名 | 说明 | 是否保密 |
| rootCA.key | CA 私钥 | 严格保密 |
| rootCA.crt | CA 公钥证书 | 可公开分发 |
| server.key | 服务端私钥 | 保密 |
| server.csr | 服务端证书请求 | 签发后可删除 |
| server.crt | 服务端证书 | 可公开 |
| client.key | 客户端私钥 | 保密 |
| client.csr | 客户端证书请求 | 签发后可删除 |
| client.crt | 客户端证书 | 可公开 |
6. Nginx 配置示例
6.1 单向 TLS(标准 HTTPS)
将证书文件复制到 Nginx 可访问的目录:
sudo mkdir -p /etc/nginx/ssl
sudo cp server.crt server.key rootCA.crt /etc/nginx/ssl/
sudo chmod 600 /etc/nginx/ssl/server.keyNginx 配置(/etc/nginx/conf.d/example.conf):
server {
listen 80;
server_name www.example.com example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com example.com;
# 证书与私钥
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# TLS 协议版本(仅启用 TLS 1.2 和 1.3)
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件(优先使用服务端配置)
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305';
# ECDH 曲线
ssl_ecdh_curve secp384r1:X25519;
# SSL 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# HSTS(HTTP 严格传输安全)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# OCSP Stapling(自签证书可跳过此项)
# ssl_stapling on;
# ssl_stapling_verify on;
# ssl_trusted_certificate /etc/nginx/ssl/rootCA.crt;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}6.2 双向 TLS(mTLS)
在上述配置基础上,添加客户端证书验证:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305';
# 客户端证书验证
ssl_client_certificate /etc/nginx/ssl/rootCA.crt;
ssl_verify_client on;
ssl_verify_depth 2;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-SSL-Client-CN $ssl_client_s_dn_cn;
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
}
}6.3 测试配置并重载
# 检查 Nginx 配置语法
sudo nginx -t
# 重载配置
sudo nginx -s reload使用 curl 验证连接:
# 单向 TLS(需信任自签 CA)
curl --cacert rootCA.crt https://www.example.com
# 双向 TLS(附带客户端证书)
curl --cacert rootCA.crt --cert client.crt --key client.key https://www.example.com