1. 为什么需要自签SSL证书?
每次在本地开发环境测试HTTPS功能时,看到浏览器那个刺眼的"不安全"提示就头疼。虽然Let's Encrypt提供了免费证书,但本地开发环境没有公网域名的情况下,自签证书才是最高效的解决方案。最近在给团队搭建内部测试环境时,就遇到了需要批量配置可信SSL证书的需求。
自签证书最大的优势在于完全自主可控,特别适合以下场景:
- 本地开发环境(localhost或192.168.x.x)
- 内网服务(如测试环境、CI/CD系统)
- 需要特定CN(Common Name)的证书
- 需要长期有效的证书(商业证书通常只有90天有效期)
注意:自签证书绝对不要用于生产环境!浏览器会标记为不安全,且缺乏证书吊销机制。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 证书生成全流程实操
2.1 准备OpenSSL环境
大多数Linux系统已预装OpenSSL,可以通过openssl version确认。如果没有,用对应包管理器安装:
bash复制# CentOS/RHEL
yum install openssl -y
# Ubuntu/Debian
apt-get install openssl -y
2.2 生成CA根证书
先创建证书存储目录并初始化序列号:
bash复制mkdir -p /etc/nginx/ssl/{certs,private}
cd /etc/nginx/ssl
echo 1000 > serial
touch index.txt
生成CA私钥(2048位RSA):
bash复制openssl genrsa -out private/ca.key 2048
创建CA根证书(有效期10年):
bash复制openssl req -new -x509 -days 3650 -key private/ca.key \
-out certs/ca.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=Dev/CN=MyRootCA"
关键参数说明:
-subj:证书主题信息,/C国家/ST省/L市/O组织/OU部门/CN通用名-days 3650:10年有效期(仅限内部使用)-x509:直接生成自签名证书
2.3 生成服务器证书
创建服务器私钥:
bash复制openssl genrsa -out private/server.key 2048
生成证书签名请求(CSR):
bash复制openssl req -new -key private/server.key \
-out certs/server.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=Dev/CN=dev.test.com"
技巧:如果要支持多域名,需要额外创建extfile.cnf包含SAN扩展:
code复制subjectAltName = @alt_names [alt_names] DNS.1 = dev.test.com DNS.2 = *.dev.test.com IP.1 = 192.168.1.100
用CA证书签署服务器证书:
bash复制openssl ca -in certs/server.csr -out certs/server.crt \
-cert certs/ca.crt -keyfile private/ca.key \
-days 365 -policy policy_anything
验证证书链:
bash复制openssl verify -CAfile certs/ca.crt certs/server.crt
3. Nginx配置HTTPS
3.1 基础SSL配置
编辑Nginx站点配置文件(如/etc/nginx/conf.d/ssl_test.conf):
nginx复制server {
listen 443 ssl;
server_name dev.test.com;
ssl_certificate /etc/nginx/ssl/certs/server.crt;
ssl_certificate_key /etc/nginx/ssl/private/server.key;
# 优化SSL配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
测试配置并重载:
bash复制nginx -t && nginx -s reload
3.2 强制HTTPS跳转
在80端口的server块中添加跳转:
nginx复制server {
listen 80;
server_name dev.test.com;
return 301 https://$host$request_uri;
}
4. 让系统信任自签证书
4.1 Windows系统导入
- 将ca.crt复制到Windows
- 运行certmgr.msc
- 右键"受信任的根证书颁发机构" → 所有任务 → 导入
- 选择ca.crt完成导入
4.2 macOS系统导入
bash复制# 将CA证书添加到钥匙串
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ca.crt
4.3 Linux系统导入
bash复制# Ubuntu/Debian
sudo cp ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
# CentOS/RHEL
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
4.4 浏览器单独导入
- Chrome/Edge:设置 → 隐私和安全 → 安全 → 管理证书 → 受信任的根证书颁发机构
- Firefox:选项 → 隐私与安全 → 证书 → 查看证书 → 证书机构 → 导入
5. 高级配置与问题排查
5.1 证书链问题
如果浏览器提示"证书链不完整",需要合并证书:
bash复制cat certs/server.crt certs/ca.crt > certs/server-chain.crt
然后在Nginx配置中使用server-chain.crt
5.2 证书过期续期
查看证书有效期:
bash复制openssl x509 -in certs/server.crt -noout -dates
续期步骤:
- 重新生成CSR(同2.3步骤)
- 使用CA重新签署(注意serial递增)
- 替换旧证书并重载Nginx
5.3 常见错误代码
| 错误码 | 可能原因 | 解决方案 |
|---|---|---|
| SSL_ERROR_BAD_CERT_DOMAIN | 证书CN与访问域名不匹配 | 确保证书CN包含访问域名 |
| SEC_ERROR_UNKNOWN_ISSUER | 未导入CA根证书 | 按第4节操作导入CA |
| SSL_ERROR_EXPIRED_CERTIFICATE | 证书过期 | 重新生成并签署证书 |
5.4 性能优化建议
nginx复制ssl_session_tickets on;
ssl_buffer_size 4k;
ssl_stapling on;
ssl_stapling_verify on;
6. 自动化脚本示例
创建自动生成证书的脚本gen_ssl.sh:
bash复制#!/bin/bash
DOMAIN=${1:-dev.test.com}
DAYS=${2:-365}
mkdir -p ssl/{certs,private}
echo 1000 > ssl/serial
touch ssl/index.txt
# 生成CA
openssl genrsa -out ssl/private/ca.key 2048
openssl req -new -x509 -days 3650 -key ssl/private/ca.key \
-out ssl/certs/ca.crt -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=Dev/CN=MyRootCA"
# 生成服务器证书
openssl genrsa -out ssl/private/server.key 2048
openssl req -new -key ssl/private/server.key \
-out ssl/certs/server.csr -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/OU=Dev/CN=$DOMAIN"
openssl ca -in ssl/certs/server.csr -out ssl/certs/server.crt \
-cert ssl/certs/ca.crt -keyfile ssl/private/ca.key \
-days $DAYS -policy policy_anything
# 生成合并证书
cat ssl/certs/server.crt ssl/certs/ca.crt > ssl/certs/server-chain.crt
echo "证书生成完成!"
echo "CA证书路径: ssl/certs/ca.crt"
echo "服务器证书路径: ssl/certs/server-chain.crt"
echo "私钥路径: ssl/private/server.key"
使用方式:
bash复制chmod +x gen_ssl.sh
./gen_ssl.sh your.domain.com 730 # 生成2年有效期证书
