Nginx SSL/TLS 配置实战:从 HTTPS 证书到 A+ 安全加固
凌晨三点,监控报警突然响起。我打开手机一看,网站证书过期了——整整90天的免费证书,硬是被我忘得干干净净。浏览器那个红色的”不安全”警告,像一面嘲讽的旗帜,挂在我博客的首页上。
那次事故后,我花了整整一周时间,把 Nginx SSL/TLS 配置从头到尾啃了一遍。从 SSL Labs 评分 F 到 A+,从手动续期到全自动,从性能拖后腿到握手时间压到 100ms 以内——这条路上踩过的坑,今天我想完整地分享给你。
HTTPS 不只是给浏览器地址栏加把小锁。Google 明确表示 HTTPS 是搜索排名因素之一,数据上看,正确配置 HTTPS 后搜索流量能有 15-20% 的增长。更重要的是,它能阻止中间人窃听——百度智能云的数据说,HTTPS 能让数据泄露风险降低 83%。简单讲,不做 HTTPS,就等于在公共场合大声聊银行卡密码。
这篇文章会带你从零开始配置 Nginx HTTPS:Let’s Encrypt 证书申请、TLS 1.3 安全加固、SSL Labs A+ 评分配置模板,还有生产环境必备的自动续期方案。所有配置都可以直接复制使用。
第一章:HTTPS 基础概念与证书类型选择
1.1 为什么每个网站都需要 HTTPS
HTTP 明文传输,意味着你访问的每个页面、提交的每个表单,都在网络里裸奔。咖啡馆的公共 WiFi、公司的网络出口、小区的运营商设备——任何一个中间节点,都能看到你发了什么。
HTTPS 在 HTTP 和 TCP 之间加了一层 TLS 加密。数据在发出前加密,到达后解密,中间的窃听者看到的只是一堆乱码。
TLS 的作用远不止加密。它还提供身份验证——确保你访问的是真正的 example.com,而不是被 DNS 劫持后的钓鱼网站。这就是为什么浏览器会对过期证书或域名不匹配的证书显示红色警告:它在告诉你,“这个网站可能不是它声称的那个”。
1.2 SSL 证书的三大类型:DV、OV、EV
证书按照验证严格程度分成三类:
| 类型 | 验证方式 | 价格 | 适用场景 |
|---|---|---|---|
| DV(域名验证) | 验证域名所有权 | 免费 - 低 | 个人博客、测试环境、小型项目 |
| OV(组织验证) | 验证域名 + 组织身份 | 中等 | 企业官网、SaaS 产品 |
| EV(扩展验证) | 最严格的身份验证 | 较高 | 金融、支付、政府机构 |
说实话,对于大多数个人项目和小型团队,DV 证书完全够用。Let’s Encrypt 提供的免费 DV 证书,有效期 90 天,浏览器信任度跟付费 DV 证书没区别。唯一的”缺点”就是需要每 90 天续签一次——但配置好自动续期后,这根本不是问题。
OV 和 EV 证书的区别主要在浏览器地址栏的展示上。EV 证书会显示公司名称(比如”中国工商银行”),但这年头浏览器对 EV 证书的视觉强调越来越弱,Chrome 甚至默认不再显示 EV 证书的公司名了。加上 OV/EV 证书动辄几百上千的价格,性价比实在不高。
1.3 Let’s Encrypt:免费证书的最佳选择
Let’s Encrypt 是由 ISRG(Internet Security Research Group)运营的非营利证书颁发机构。它有几个核心优势:
- 完全免费:DV 证书永久免费
- 自动化:通过 ACME 协议自动签发和续期
- 广泛信任:所有主流浏览器和操作系统都信任
- 有效期 90 天:短期证书更安全,倒逼你配置自动化
缺点也有:只有 DV 证书,不提供 OV/EV;通配符证书需要 DNS 验证(稍微麻烦一点)。但对于 99% 的个人项目和中小型网站,这些”缺点”根本不算问题。
接下来我们用 Certbot——Let’s Encrypt 的官方客户端——来申请证书。
第二章:Let’s Encrypt 证书申请实战
2.1 安装 Certbot
Certbot 的安装方式因操作系统而异。Ubuntu 用户最简单:
# Ubuntu 20.04+ / Debian 10+
sudo apt update
sudo apt install certbot python3-certbot-nginx
CentOS/RHEL 用户需要先启用 EPEL 仓库:
# CentOS 8 / RHEL 8
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx
安装完成后,可以用 certbot --version 检查版本。确认无误后,下一步就是申请证书。
2.2 申请证书
Certbot 支持多种验证方式,最常用的是 standalone(独立验证)和 webroot(网站根目录验证)。如果你的 Nginx 已经在运行,推荐 webroot 模式:
# webroot 模式:网站已运行时使用
sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com
-w 指定网站根目录,-d 指定域名。一次可以申请多个域名的证书。
如果 Nginx 还没启动,或者你只是临时开一个服务器测试,用 standalone 模式:
# standalone 模式:需要临时占用 80 端口
sudo certbot certonly --standalone -d example.com -d www.example.com
这个模式下 Certbot 会临时启动一个 HTTP 服务器,验证完成后自动关闭。验证过程需要 80 端口空闲,所以如果你的 Nginx 已经在跑,需要先停掉。
还有一种更简单的方式——Certbot 的 Nginx 插件可以自动修改 Nginx 配置:
# 自动配置模式:Certbot 自动修改 Nginx 配置
sudo certbot --nginx -d example.com -d www.example.com
这个命令会自动申请证书、修改 Nginx 配置、设置 HTTPS 重定向。适合新手快速上手,但生产环境建议手动配置,以便更精细地控制 SSL 参数。
2.3 证书文件结构
申请成功后,证书文件默认存放在 /etc/letsencrypt/live/example.com/ 目录下:
/etc/letsencrypt/live/example.com/
├── cert.pem # 域名证书
├── chain.pem # 中间证书链
├── fullchain.pem # 完整证书链(cert + chain)
└── privkey.pem # 私钥文件
Nginx 配置中需要用到两个文件:fullchain.pem(ssl_certificate)和 privkey.pem(ssl_certificate_key)。privkey.pem 是敏感文件,权限应该是 600,千万别泄露。
第三章:Nginx SSL 基础配置
3.1 最基础的 HTTPS 配置
有了证书,下一步就是在 Nginx 里配置 HTTPS。最简单的配置长这样:
server {
listen 443 ssl;
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;
# 其他配置...
root /var/www/example.com;
index index.html;
}
这段配置能让 HTTPS 跑起来,但只能打个 D 分。问题在于:没有指定 TLS 版本,默认支持 TLS 1.0 和 1.1——这两个版本早就被认定不安全了。
3.2 HTTP 重定向到 HTTPS
光配置 HTTPS 还不够,用户可能直接访问 HTTP 版本。你需要把所有 HTTP 请求重定向到 HTTPS:
server {
listen 80;
server_name example.com www.example.com;
# 永久重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
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;
# 其他配置...
}
return 301 是永久重定向,浏览器会缓存这个跳转。下次用户再输入 http://,浏览器会直接跳转到 https://,省去一次请求。
3.3 一个常见的配置错误
我见过不少人在 listen 443 ssl; 后面加上 http2,写成 listen 443 ssl http2;。在 Nginx 1.25.1 之后,HTTP/2 支持已经被移到 http2 指令里了:
# Nginx 1.25.1+ 的新写法
server {
listen 443 ssl;
http2 on; # 独立的 http2 指令
server_name example.com;
# ...
}
如果你的 Nginx 版本较新,建议用新的写法,避免配置警告。可以用 nginx -v 检查版本。
第四章:TLS 1.3 安全加固配置
4.1 TLS 版本选择
TLS 有四个版本:1.0、1.1、1.2、1.3。其中 1.0 和 1.1 已经被废弃,所有主流浏览器都在 2020 年停止支持。
| 版本 | 安全性 | 性能 | 兼容性 | 建议 |
|---|---|---|---|---|
| TLS 1.0 | 不安全 | 慢 | 广泛支持 | 禁用 |
| TLS 1.1 | 不安全 | 慢 | 广泛支持 | 禁用 |
| TLS 1.2 | 安全 | 一般 | 几乎全支持 | 可保留 |
| TLS 1.3 | 最安全 | 最快 | 现代浏览器 | 必须启用 |
TLS 1.3 的核心优势在于性能:握手从 2-RTT(往返)降到 1-RTT,理论上能减少一半的握手延迟。实测中,TLS 1.3 的握手时间能压到 100ms 以内。
Nginx 配置里用 ssl_protocols 指令指定 TLS 版本:
ssl_protocols TLSv1.2 TLSv1.3;
不建议只启用 TLS 1.3。虽然 2026 年几乎所有浏览器都支持 TLS 1.3,但一些老旧的 HTTP 客户端(比如某些 API 调用工具、嵌入式设备)可能还不支持。保留 TLS 1.2 作为兼容选项,是更稳妥的选择。
4.2 Cipher Suite 配置
Cipher Suite(密码套件)决定了加密算法、密钥交换方式和消息认证码。选错了,HTTPS 可能形同虚设。
2026 年推荐的 TLS 1.3 cipher suite 列表:
ssl_protocols TLSv1.2 TLSv1.3;
# TLS 1.3 的 cipher(Nginx 会自动使用 OpenSSL 的默认列表)
# 这行可以省略,但保留也无妨
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
# TLS 1.2 的 cipher(向后兼容)
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;
# 优先使用服务器指定的 cipher
ssl_prefer_server_ciphers on;
这套配置的要点:
- ECDHE:优先使用椭圆曲线密钥交换,比 RSA 更安全、更快
- AES-GCM:GCM 模式提供认证加密,比 CBC 模式更安全
- CHACHA20-POLY1305:移动端性能更好,适合没有 AES 硬件加速的设备
如果你不确定,可以用 Mozilla SSL Configuration Generator 生成配置:https://ssl-config.mozilla.org/
4.3 HSTS:强制 HTTPS 访问
HSTS(HTTP Strict Transport Security)告诉浏览器:“这个网站只接受 HTTPS 访问”。即使用户手动输入 http://,浏览器也会在本地强制跳转到 https://,省去一次网络请求。
# HSTS 头部
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
参数解释:
max-age=31536000:有效期 1 年(单位秒)includeSubDomains:包括所有子域名preload:加入 HSTS Preload List(需要在 hstspreload.org 提交)
注意:HSTS 一旦启用,浏览器会缓存很长时间。如果你还需要测试 HTTP 版本,先不要加 preload,或者把 max-age 设短一点。
第五章:SSL 性能优化技巧
5.1 SSL Session Cache
每次 TLS 握手都需要进行密钥交换和证书验证,开销不小。Session Cache 让客户端在一定时间内复用之前的会话,跳过完整握手流程。
# Session Cache 配置
ssl_session_cache shared:SSL:10m; # 10MB 缓存,约 40000 个会话
ssl_session_timeout 1d; # 会话有效期 1 天
ssl_session_tickets off; # 禁用 Session Ticket(更安全)
shared:SSL:10m 表示所有 worker 进程共享一个 10MB 的缓存区。1MB 大概能存 4000 个会话,10MB 足够应对中小型网站。
ssl_session_tickets off 是安全考虑。Session Ticket 机制需要服务端维护一个密钥来加密 Ticket,如果这个密钥泄露,攻击者可以解密所有历史会话。禁用后更安全,但会增加服务器负担——适合安全性要求高的场景。
5.2 OCSP Stapling
浏览器验证证书时,需要检查证书是否被吊销。传统方式是向 CA 发起 OCSP 查询,这会增加一次网络请求,暴露用户访问了哪些网站。
OCSP Stapling 让服务器代替浏览器查询 OCSP 状态,并缓存结果,一次性发给浏览器。既保护隐私,又减少延迟。
# OCSP Stapling 配置
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
resolver 指定 DNS 服务器,用于解析 OCSP 服务器的域名。Google 的 8.8.8.8 和 8.8.4.4 是常用选择。
配置完成后,可以用 OpenSSL 测试:
openssl s_client -connect example.com:443 -status < /dev/null 2>&1 | grep -A 17 "OCSP response"
如果看到 “OCSP Response Status: successful”,说明 OCSP Stapling 工作正常。
5.3 ssl_buffer_size 调优
ssl_buffer_size 控制 TLS 记录的大小。默认 16KB,对于小响应(比如 API 请求)来说太大了,会增加 TTFB(首字节时间)。
对于以小响应为主的 API 服务器或博客网站,可以调小这个值:
ssl_buffer_size 4k; # 适合小响应场景
对于大文件下载服务器,保持默认 16KB 或调到 32KB 更合适。
第六章:证书自动续期配置
6.1 Certbot 自动续期命令
Let’s Encrypt 证书有效期只有 90 天,必须定期续期。Certbot 提供了 renew 命令:
# 测试续期(不实际续期,只检查)
sudo certbot renew --dry-run
# 实际续期
sudo certbot renew
renew 命令会检查所有证书的到期时间,只有剩余有效期少于 30 天的证书才会被续期。这意味着你可以放心地每天运行这个命令——它不会浪费 Let’s Encrypt 的速率限制配额。
6.2 配置 crontab 定时任务
最可靠的方式是用 crontab 设置自动续期:
# 编辑 root 用户的 crontab
sudo crontab -e
添加以下两行:
# 每天凌晨 3:00 和下午 3:00 各检查一次
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
0 15 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
--quiet 静默模式,不输出日志。--post-hook "systemctl reload nginx" 在续期成功后重载 Nginx 配置,让新证书生效。
为什么一天检查两次?因为续期失败的情况偶尔会发生(比如 DNS 暂时解析失败),多检查几次能增加成功率。
6.3 续期测试和故障排查
续期失败时,Certbot 会在 /var/log/letsencrypt/letsencrypt.log 记录详细日志。常见问题:
- 端口被占用:standalone 模式需要 80 端口,确保 Nginx 没有占用
- DNS 解析失败:检查域名 DNS 记录是否正确指向服务器
- 速率限制:Let’s Encrypt 每周最多申请 5 次相同证书,测试时用
--dry-run - 证书目录权限:确保 Certbot 有权限读写
/etc/letsencrypt/
测试续期的完整流程:
# 1. 先 dry-run 测试
sudo certbot renew --dry-run
# 2. 如果 dry-run 成功,实际续期
sudo certbot renew
# 3. 检查证书有效期
sudo certbot certificates
# 4. 重载 Nginx
sudo systemctl reload nginx
完整配置模板
下面是一个生产环境可用的 Nginx SSL 配置模板,已达到 SSL Labs A+ 评分:
# HTTP 重定向
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 服务
server {
listen 443 ssl;
http2 on;
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;
# TLS 版本
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher Suite
ssl_ciphers TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256: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;
# 安全头部
add_header Strict-Transport-Security "max-age=31536000; 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;
# Session Cache
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;
# 性能调优
ssl_buffer_size 4k;
# 网站配置
root /var/www/example.com;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
配置完成后,用 SSL Labs 测试评分:https://www.ssllabs.com/ssltest/
总结
配置 HTTPS 这件事,入门不难——几行配置就能跑起来。但要达到 SSL Labs A+ 评分,同时兼顾性能和兼容性,就需要理解 TLS 版本、Cipher Suite、Session Cache、OCSP Stapling 这些细节。
核心配置要点回顾:
- 证书申请:Let’s Encrypt 免费好用,Certbot 自动化省心
- TLS 版本:TLS 1.2 + 1.3,禁用 1.0 和 1.1
- Cipher Suite:优先 ECDHE 和 AES-GCM,兼顾 CHACHA20
- HSTS:强制 HTTPS,减少重定向开销
- 性能优化:Session Cache 和 OCSP Stapling 缺一不可
- 自动续期:crontab 双保险,续期后自动重载 Nginx
把上面的配置模板复制到你的 Nginx 配置里,改一下域名和证书路径,就能直接用。配置完成后记得测一下 SSL Labs 评分,评论区告诉我你的结果——我猜大概率是 A+。
配置 Nginx SSL/TLS 实现 A+ 安全评分
从证书申请到安全加固的完整配置流程
⏱️ 预计耗时: 30 分钟
- 1
步骤1: 安装 Certbot 并申请证书
使用 Certbot 申请 Let's Encrypt 免费 SSL 证书:
• Ubuntu/Debian: sudo apt install certbot python3-certbot-nginx
• CentOS/RHEL: sudo dnf install certbot python3-certbot-nginx
• 申请证书: sudo certbot certonly --webroot -w /var/www/example.com -d example.com
• 证书目录: /etc/letsencrypt/live/example.com/
• 需要两个文件: fullchain.pem 和 privkey.pem - 2
步骤2: 配置 Nginx HTTPS 基础设置
在 Nginx 配置中添加 SSL 证书和 HTTP 重定向:
• listen 443 ssl; 配置 HTTPS 监听
• http2 on; 启用 HTTP/2(Nginx 1.25.1+)
• ssl_certificate 指向 fullchain.pem
• ssl_certificate_key 指向 privkey.pem
• return 301 https://$server_name$request_uri; 重定向 HTTP 到 HTTPS - 3
步骤3: 配置 TLS 1.3 和 Cipher Suite
启用安全的 TLS 版本和加密套件:
• ssl_protocols TLSv1.2 TLSv1.3; 禁用旧版本
• ssl_ciphers 配置 ECDHE + AES-GCM + CHACHA20
• ssl_prefer_server_ciphers on; 优先服务器选择
• add_header Strict-Transport-Security 启用 HSTS - 4
步骤4: 优化 SSL 性能
配置 Session Cache 和 OCSP Stapling 提升性能:
• ssl_session_cache shared:SSL:10m; 共享会话缓存
• ssl_session_timeout 1d; 会话有效期 1 天
• ssl_stapling on; 启用 OCSP Stapling
• ssl_buffer_size 4k; 优化小响应场景 - 5
步骤5: 配置证书自动续期
使用 crontab 配置 Certbot 自动续期:
• sudo crontab -e 编辑定时任务
• 0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
• 每天检查两次(凌晨和下午各一次)
• --post-hook 确保续期后 Nginx 重载新证书 - 6
步骤6: 测试 SSL 配置安全性
验证配置是否达到 A+ 评分:
• 访问 https://www.ssllabs.com/ssltest/ 测试 SSL 配置
• 使用 openssl s_client -connect example.com:443 -status 测试 OCSP
• 检查 certbot certificates 确认证书有效期
• 确保 HSTS、OCSP Stapling、Session Cache 都生效
常见问题
Let's Encrypt 证书有效期多久?需要手动续期吗?
如何测试 Nginx SSL 配置的安全性?
• A+ 为最高评分,表示配置安全且性能优秀
• 也可以用 openssl s_client 命令本地测试 OCSP Stapling
• 测试命令:openssl s_client -connect example.com:443 -status
HTTPS 会影响网站性能吗?如何优化?
• TLS 1.3 握手从 2-RTT 降到 1-RTT,延迟减半
• Session Cache 让客户端复用会话,跳过完整握手
• OCSP Stapling 减少证书验证的网络请求
• 优化后握手时间可控制在 100ms 以内
证书续期失败怎么办?如何排查问题?
• 端口被占用:standalone 模式需确保 80 端口空闲
• DNS 解析失败:检查域名是否正确指向服务器 IP
• 速率限制:Let's Encrypt 每周最多申请 5 次相同证书
• 查看日志:/var/log/letsencrypt/letsencrypt.log
TLS 1.2 和 TLS 1.3 有什么区别?为什么要同时启用?
• 性能:握手从 2-RTT 降到 1-RTT,延迟减半
• 安全:移除了不安全的加密算法
• 兼容性:同时启用是为了支持老旧客户端,TLS 1.2 作为兼容选项
HSTS 配置有什么注意事项?
• max-age 建议设为 31536000(1 年)
• includeSubDomains 会影响所有子域名
• preload 需要在 hstspreload.org 提交才能生效
• 首次配置建议先设较短的 max-age 测试,确认无误后再延长
如何选择 SSL 证书类型?DV、OV、EV 有什么区别?
• DV 证书:免费,验证域名所有权,适合个人博客和小型项目
• OV 证书:验证组织身份,显示公司信息,适合企业官网
• EV 证书:严格验证,Chrome 已不显示公司名,性价比不高
• 99% 的场景推荐 Let's Encrypt 免费 DV 证书
12 分钟阅读 · 发布于: 2026年4月20日 · 修改于: 2026年4月20日
相关文章
Nginx 反向代理完全指南:upstream、缓冲与超时
Nginx 反向代理完全指南:upstream、缓冲与超时
Supabase Edge Functions 实战:Deno 运行时与 TypeScript 开发指南
Supabase Edge Functions 实战:Deno 运行时与 TypeScript 开发指南
Docker 多阶段构建实战:生产镜像从 1GB 瘦身到 10MB

评论
使用 GitHub 账号登录后即可评论