一、自签名证书的核心原理
1. 自签名证书是什么?
-
定义:开发者自行生成并签发的 SSL 证书(非第三方 CA 签发)。
-
特点:
- 加密有效:数据通过 TLS 协议加密传输。
- 浏览器警告:因缺乏可信 CA 验证,需手动信任。
2. 适用场景与风险
-
适用:本地开发、内网测试、短期验证。
-
风险:
- 中间人攻击:攻击者伪造证书窃取数据。
- 信任滥用:用户可能忽略浏览器警告,误信恶意证书。
二、4 步生成自签名证书
步骤 1:生成私钥(Private Key)
bash
复制
bash
复制
openssl genrsa -out server.key 2048
-
参数解释:
genrsa:生成 RSA 私钥。2048:密钥长度(低于 2048 位会被视为不安全)。
-
输出文件:
server.key(私钥必须严格保密!)。
步骤 2:创建证书签名请求(CSR)
bash
复制
bash
复制
openssl req -new -key server.key -out server.csr
-
交互式填写示例:
plaintext 复制 plaintext 复制 Country Name (2 letter code) [XX]:CN Common Name (e.g., server FQDN) []:localhost # 必须与实际访问域名/IP一致! Email Address []:developer@example.com -
关键字段:
Common Name (CN)必须填写服务域名或 IP(如localhost或192.168.1.100)。
步骤 3:生成自签名证书(CRT)
bash
复制
bash
复制
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
-
参数解释:
-days 365:证书有效期(生产环境建议缩短至 90 天)。-signkey:用私钥直接签名,省去 CA 签发流程。
步骤 4:验证证书内容
bash
复制
bash
复制
openssl x509 -in server.crt -text -noout
-
检查重点:
Validity:有效期是否正确。Subject: CN:是否与目标域名/IP 一致。X509v3 Subject Alternative Name:是否包含备用域名/IP(如有)。
三、配置 HTTPS 服务(Nginx/Node.js 双方案)
方案 1:Nginx 反向代理
nginx
复制
nginx
复制
server {
listen 443 ssl;
server_name localhost;
# 证书路径(绝对路径)
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# 强制安全协议与加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 反向代理到本地 HTTP 服务
location /api {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
}
}
# HTTP 强制跳转 HTTPS
server {
listen 80;
server_name localhost;
return 301 https://$host$request_uri;
}
-
重启 Nginx:
bash 复制 bash 复制 sudo nginx -s reload
方案 2:Node.js 原生 HTTPS 服务
javascript
复制
javascript
复制
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
// 禁用不安全协议
minVersion: 'TLSv1.2',
ciphers: 'HIGH:!aNULL:!MD5'
};
https.createServer(options, (req, res) => {
res.end('HTTPS Success!');
}).listen(443, '0.0.0.0');
-
启动服务:
bash 复制 bash 复制 sudo node server.js # 需 root 权限监听 443 端口
四、浏览器信任证书(解决“不安全”警告)
Chrome 手动信任步骤
- 访问
https://localhost→ 点击地址栏“不安全”图标 → 导出证书(server.crt)。 - 打开
chrome://settings/certificates→ 导入证书 → 选择“受信任的根证书颁发机构”。
macOS/Linux 系统级信任
bash
复制
bash
复制
# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain server.crt
# Linux (Debian/Ubuntu)
sudo cp server.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
五、高频问题与解决方案
问题 1:ERR_CERT_COMMON_NAME_INVALID
- 原因:证书的
Common Name与实际访问域名/IP 不匹配。 - 解决:重新生成证书,确保
CN字段正确。
问题 2:SSL_CTX_use_PrivateKey_file error
- 原因:证书与私钥不匹配或文件路径错误。
- 解决:检查文件路径,重新生成证书(使用同一私钥)。
问题 3:浏览器缓存旧证书
-
解决:清除浏览器 SSL 缓存:
- Chrome:访问
chrome://net-internals/#hsts→ 输入域名 → 点击“Delete”。
- Chrome:访问
六、进阶:支持多域名/IP(SAN 扩展)
生成含 SAN 的证书
bash
复制
markdown
复制
openssl req -x509 -newkey rsa:2048 -keyout server.key -out server.crt \
-days 365 -subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:example.com"
- 参数:
-addext添加备用名称(支持多个 DNS/IP)。
七、生产环境替代方案
1. Let's Encrypt 免费证书
bash
复制
bash
复制
# 使用 Certbot 自动申请(需域名)
sudo certbot certonly --nginx -d example.com
- 优势:浏览器自动信任,支持自动续期。
2. 内网私有 CA 搭建
- 工具:
easy-rsa或OpenSSL CA命令。 - 流程:自建根 CA → 签发子证书 → 分发根证书到客户端。
总结
通过本文,你已掌握:
- 自签名证书生成:OpenSSL 命令行全流程。
- HTTPS 服务配置:Nginx/Node.js 双方案。
- 浏览器信任处理:解决“不安全”警告。
- 生产环境迁移:Let's Encrypt 或私有 CA 方案。
立即行动:
bash
复制
bash
复制
openssl genrsa -out server.key 2048 # 生成你的第一个私钥!