一、SSL证书配置基础(告别443报错的起点)
核心SSL指令
nginx
server {
listen 443 ssl http2; # Nginx 1.15.0+ 推荐写法
server_name example.com www.example.com;
# 证书路径(使用完整链)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 后续的安全、性能配置在此添加...
}
要点说明:
`listen 443 ssl http2;`:同时启用SSL和HTTP/2,这是1.15.0+版本的推荐写法,不要与已废弃的`ssl on;`混用。
`ssl_certificate`必须指向**完整证书链**(`fullchain.pem`),否则浏览器可能报“证书不受信任”。
证书路径和文件名必须与服务器实际存放完全一致,建议直接复制路径粘贴到配置中避免拼写错误。
自动跳转HTTPS(HTTP → HTTPS)
nginx
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
二、安全加固配置
基础安全配置
nginx
在443 server块内添加
1. TLS协议版本:仅启用安全版本
ssl_protocols TLSv1.2 TLSv1.3;
2. 加密套件:优先ECDHE(支持前向保密PFS)和AEAD模式
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
3. 服务器优先选择加密套件
ssl_prefer_server_ciphers on;
高级安全增强(推荐添加)
nginx
# HSTS - 强制浏览器仅通过HTTPS访问
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# 防点击劫持
add_header X-Frame-Options DENY always;
# 防MIME类型嗅探
add_header X-Content-Type-Options nosniff always;
# 关闭Nginx版本号暴露
server_tokens off;
安全配置说明:
TLS协议:禁用SSLv3、TLSv1.0、TLSv1.1,仅启用TLSv1.2+。
HSTS:`max-age=63072000`(约2年),配合`preload`可申请加入浏览器HSTS预加载列表。
加密套件:优先使用ECDHE密钥交换获得前向保密,搭配AES-GCM或CHACHA20-POLY1305加密模式。
三、性能优化配置
nginx
# 在443 server块内添加
# SSL会话缓存 - 减少重复握手
ssl_session_cache shared:SSL:10m; # 10MB ≈ 4000个会话
ssl_session_timeout 10m;
# 可选:禁用会话票据(安全性优先)
ssl_session_tickets off;
# OCSP Stapling - 加速证书状态验证
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# HTTP/2 - 已在listen指令中通过http2开启
性能优化说明:
会话缓存:减少重复TLS握手,显著降低延迟。
OCSP Stapling:服务器主动获取证书状态,避免客户端向CA查询,降低验证延迟。
HTTP/2:支持多路复用和头部压缩,提升并发性能。
四、常见443端口报错与排查
1. 模块缺失:`the "ssl" parameter requires ngx_http_ssl_module`
原因:Nginx未编译SSL模块。
排查:`nginx -V 2>&1 | grep http_ssl_module`,若无输出则需重新编译Nginx添加`--with-http_ssl_module`。
2. 证书/私钥路径错误或权限不足
排查:
- 检查`ssl_certificate`和`ssl_certificate_key`路径是否正确
- 确保Nginx进程(通常为`www-data`)可读证书文件:
```bash
chmod 600 /path/to/privkey.pem # 私钥严格权限
chmod 644 /path/to/cert.pem
3. 端口冲突或防火墙拦截
排查:
bash
# 检查443端口是否被占用
netstat -tuln | grep 443
# 放行防火墙(以UFW为例)
sudo ufw allow 443/tcp
sudo ufw reload
4. 证书链不完整
现象:浏览器提示“证书不受信任”。
修复:确保`ssl_certificate`指向包含完整链的文件(如`fullchain.pem`)。
5. SSL_ERROR_RX_RECORD_TOO_LONG
原因:访问到了未启用SSL的端口(如443端口配置成了明文HTTP)。
修复:使用`listen 443 ssl;`,不要把`ssl on;`与`listen 443`混用。
6. 系统时间不正确
现象:证书验证失败。
修复:
bash
sudo timedatectl set-ntp true # 启用NTP同步
sudo systemctl restart nginx
7. 配置文件语法错误
验证:
bash
sudo nginx -t # 测试配置语法,定位具体错误行
快速排查命令汇总
排查项 命令
配置语法 `sudo nginx -t`
查看错误日志 `sudo tail -f /var/log/nginx/error.log`
检查端口监听 `ss -lntp \| grep 443`
测试SSL握手 `openssl s_client -connect example.com:443 -servername example.com`
检查证书有效期 `openssl x509 -in /path/to/cert.pem -noout -dates`
验证证书链完整性 `openssl s_client -connect example.com:443 -showcerts`
五、工具推荐
配置生成工具
Mozilla SSL Config Generator(`ssl-config.mozilla.org`):提供预定义的Nginx SSL配置,按安全等级(Modern/Intermediate/Old)自动生成。
NginxConfig.io:可视化界面,支持SSL、反向代理、gzip、缓存等选项,可直接复制配置。
安全评估工具
Qualys SSL Labs(`ssllabs.com/ssltest`):扫描域名,提供详细安全报告和评分,目标达到A+评级。
- 其他免费工具:SSL Certificate Checker、HTTP Header Checker等可用于快速检查配置合规性。
六、证书自动化管理(Certbot + Let's Encrypt)
安装与获取证书
bash
Ubuntu/Debian
sudo apt install certbot python3-certbot-nginx
自动获取SSL证书并配置Nginx
sudo certbot --nginx -d example.com -d www.example.com
自动续期配置
bash
测试续期
sudo certbot renew --dry-run
添加定时任务(每周一凌晨执行)
crontab -e 添加以下行:
0 0 * * 1 /usr/bin/certbot renew --quiet && /usr/sbin/service nginx reload
说明:Let's Encrypt证书有效期为90天,务必配置自动续期避免服务中断。
七、验证与测试
本地验证
bash
1. 语法检查
sudo nginx -t
2. 重载配置
sudo systemctl reload nginx
3. 测试HTTPS连通性
curl -Iv https://example.com
远程安全评估
1. 访问 Qualys SSL Labs(`ssllabs.com/ssltest`)
2. 输入域名,等待扫描完成
3. 查看报告中的Protocols、Cipher Suites、Handshake Simulation等模块
4. 目标:安全评级达到 A+
证书链验证
bash
openssl s_client -connect example.com:443 -showcerts
输出中应包含完整的证书链(域名证书 + 中间证书),且`Verify return code: 0 (ok)`。
生产级完整配置模板
nginx
/etc/nginx/conf.d/example.conf
HTTP → HTTPS 跳转
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
HTTPS 主配置
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# 证书
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 安全
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305';
ssl_prefer_server_ciphers on;
# 性能
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# 安全头
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
server_tokens off;
# 站点配置
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
配置完成后执行`sudo nginx -t && sudo systemctl reload nginx`即可生效。