一、SSL证书概述
SSL/TLS证书为网站提供加密传输,是现代Web安全的基础。在Ubuntu服务器上为Nginx配置SSL证书,不仅能保护用户数据安全,还能提升搜索引擎排名。
SSL证书三大类型:
| 类型 | 验证级别 | 费用 | 签发速度 | 适用场景 |
|---|---|---|---|---|
| DV(域名验证) | 仅验证域名所有权 | 免费/低价 | 数分钟 | 博客、个人站点 |
| OV(组织验证) | 验证组织真实性 | 中等 | 1-3工作日 | 企业官网 |
| EV(扩展验证) | 严格验证组织+运营 | 较高 | 3-7工作日 | 金融、电商 |
二、环境准备
2.1 系统要求
- Ubuntu 22.04 LTS 或 24.04 LTS
- Nginx已安装并正常运行
- 域名已解析到服务器公网IP
- 80和443端口已在防火墙中开放
2.2 安装Nginx
sudo apt update
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
# 验证
nginx -v
curl -I http://your-server-ip
2.3 配置域名解析
在域名服务商后台添加A记录,将域名指向服务器IP:
类型 主机记录 记录值
A @ your-server-ip
A www your-server-ip
验证解析:
dig yourdomain.com +short
dig www.yourdomain.com +short
2.4 创建基础Nginx站点配置
# /etc/nginx/sites-available/myapp
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/myapp;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
三、使用Let’s Encrypt免费证书
3.1 安装Certbot
sudo apt update
sudo apt install -y certbot python3-certbot-nginx
3.2 获取SSL证书
# 单域名
sudo certbot --nginx -d yourdomain.com
# 多域名(主域名+www)
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Certbot会自动:
1. 验证域名所有权(通过HTTP-01挑战)
2. 获取证书并保存到/etc/letsencrypt/live/
3. 修改Nginx配置添加SSL指令
4. 设置HTTP到HTTPS的301重定向
3.3 验证证书
# 查看证书信息
sudo certbot certificates
# 使用openssl查看详情
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | openssl x509 -noout -subject -dates -issuer
# 在线测试(在浏览器中访问)
curl -I https://yourdomain.com
四、手动配置SSL(推荐方案)
Certbot自动配置较为保守,手动配置可以启用更多优化。
4.1 完整Nginx SSL配置
# /etc/nginx/sites-available/myapp
# HTTP → HTTPS重定向
server {
listen 80;
listen [::]:80;
server_name yourdomain.com www.yourdomain.com;
# 保留Let's Encrypt验证路径
location ^~ /.well-known/acme-challenge/ {
root /var/www/myapp;
}
location / {
return 301 https://$host$request_uri;
}
}
# HTTPS主配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
root /var/www/myapp;
index index.html index.htm;
# ===== SSL证书 =====
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# ===== SSL协议与加密套件(Mozilla Modern推荐) =====
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:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# ===== SSL会话缓存 =====
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
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;
# ===== DH参数(增强安全性) =====
ssl_dhparam /etc/nginx/dhparam.pem;
# ===== 安全响应头 =====
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# ===== 站点配置 =====
location / {
try_files $uri $uri/ =404;
}
# 静态资源缓存
location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
# 隐藏Nginx版本
server_tokens off;
}
4.2 生成DH参数
# 生成2048位DH参数(约需1-2分钟)
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
# 如需更高安全性,使用4096位(约需10分钟)
# sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
4.3 应用配置
sudo nginx -t
sudo systemctl reload nginx
五、通配符证书配置
通配符证书可以保护*.yourdomain.com下的所有子域名。
5.1 使用DNS验证获取通配符证书
sudo certbot certonly --manual --preferred-challenges dns \
-d "*.yourdomain.com" -d yourdomain.com
Certbot会提示添加DNS TXT记录:
请在DNS中添加以下记录:
_acme-challenge.yourdomain.com. TXT "xxxxxxxxxxxx"
在域名DNS管理后台添加后,等待DNS传播(通常1-5分钟),然后按回车继续。
5.2 通配符证书的Nginx配置
server {
listen 443 ssl http2;
server_name yourdomain.com *.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# 其他SSL配置同上...
}
六、商业SSL证书配置
如果使用商业证书(如DigiCert、GlobalSign等),配置方式相同,只需替换证书文件路径。
6.1 安装商业证书
# 创建证书目录
sudo mkdir -p /etc/nginx/ssl/yourdomain.com
# 将证书文件上传到服务器
# yourdomain.com.crt(证书文件)
# yourdomain.com.key(私钥文件)
# intermediate.crt(中间证书,部分CA提供)
# 合并证书链(如果需要)
cat yourdomain.com.crt intermediate.crt > /etc/nginx/ssl/yourdomain.com/fullchain.pem
cp yourdomain.com.key /etc/nginx/ssl/yourdomain.com/privkey.pem
# 设置权限
sudo chmod 600 /etc/nginx/ssl/yourdomain.com/privkey.pem
sudo chmod 644 /etc/nginx/ssl/yourdomain.com/fullchain.pem
6.2 Nginx配置中引用商业证书
ssl_certificate /etc/nginx/ssl/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/yourdomain.com/privkey.pem;
七、自动续期配置
7.1 Let’s Encrypt证书续期
Let’s Encrypt证书有效期90天,Certbot会自动创建定时任务:
# 查看自动续期定时器
sudo systemctl status certbot.timer
# 手动测试续期(不会真正续期)
sudo certbot renew --dry-run
# 手动强制续期
sudo certbot renew --force-renewal
7.2 续期后自动重载Nginx
# 创建续期后执行脚本
sudo nano /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
#!/bin/bash
# SSL证书续期后自动重载Nginx
systemctl reload nginx
# 可选:记录日志
echo "$(date) - SSL证书已续期并重载Nginx" >> /var/log/ssl-renewal.log
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh
7.3 监控证书有效期
# 查看证书到期时间
echo | openssl s_client -connect yourdomain.com:443 2>/dev/null | \
openssl x509 -noout -enddate
# 批量检查脚本
#!/bin/bash
for domain in yourdomain.com www.yourdomain.com; do
expiry=$(echo | openssl s_client -connect $domain:443 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
echo "$domain: $days 天后过期"
done
八、SSL安全测试
配置完成后,使用以下工具验证SSL安全性:
| 工具 | 网址 | 评分标准 |
|---|---|---|
| SSL Labs | ssllabs.com/ssltest | A+ 为最高 |
| HTBridge | htbridge.com/ssl | 综合评估 |
| CryptCheck | cryptcheck.fr | 加密套件分析 |
A+评分关键指标:
– TLS 1.3已启用
– 仅有安全的前向保密密码套件
– HSTS已启用且设置了preload
– OCSP Stapling正常工作
– 无已知的漏洞(POODLE、Heartbleed等)
九、常见问题排查
9.1 证书验证失败
# 检查证书链是否完整
openssl s_client -connect yourdomain.com:443 -showcerts
# 检查Nginx是否引用了正确的证书文件
nginx -T | grep ssl_certificate
9.2 混合内容警告
# 检查页面中的HTTP资源引用
curl -s https://yourdomain.com | grep -o 'http://[^"]*'
# 解决方案:将所有资源引用改为HTTPS或使用相对协议 //
9.3 证书续期失败
# 查看续期日志
sudo cat /var/log/letsencrypt/letsencrypt.log
# 常见原因:
# 1. DNS记录未更新 → 检查域名解析
# 2. 80端口不通 → 检查防火墙
# 3. Nginx未运行 → 启动Nginx
9.4 502 Bad Gateway(HTTPS后)
# 检查Nginx配置语法
sudo nginx -t
# 检查证书文件权限
ls -la /etc/letsencrypt/live/yourdomain.com/
# 确保证书文件存在且可读
sudo cat /etc/letsencrypt/live/yourdomain.com/fullchain.pem | head -2
十、配置优化检查清单
- [ ] Nginx已安装且HTTP可访问
- [ ] 域名A记录已解析到服务器IP
- [ ] 80和443端口已在防火墙开放
- [ ] Let’s Encrypt证书已获取
- [ ] HTTP自动跳转HTTPS(301)
- [ ] 仅启用TLS 1.2和1.3
- [ ] HSTS已启用(includeSubDomains + preload)
- [ ] OCSP Stapling已启用
- [ ] DH参数已生成(2048位+)
- [ ] 安全响应头已配置
- [ ] 自动续期定时器已启用
- [ ] 续期后Nginx自动重载脚本已配置
- [ ] SSL Labs评分达到A/A+
- [ ] Nginx版本号已隐藏
注:本文基于Ubuntu 22.04/24.04、Nginx 1.24+、Certbot 3.x编写。