3. 搭建 HTTPS Web 服务器:Nginx 配置实战
好,我们进入第三章。前两章我们把证书签发了,也理解了握手原理。这一章很实在——把 Nginx 配起来,让 HTTPS 真正跑通。
我个人习惯,不管项目多急,都会先在本地搭一遍。你想想看,线上环境出问题排查成本太高了。本地搞通了,再推到生产,心里有底。
3.1 基础环境准备
假设你已经装好了 Nginx。没装的话,CentOS 用 yum install nginx,Ubuntu 用 apt install nginx。版本最好在 1.18 以上,老版本对 HTTP/2 和现代密码套件支持不太好。
检查一下当前版本:
nginx -v
# nginx version: nginx/1.24.0
嗯,这里要注意:确认编译参数里有没有 --with-http_ssl_module。没有的话,后面配 HTTPS 会报错。
nginx -V 2>&1 | grep ssl
# 输出里应该有 --with-http_ssl_module
3.2 配置 SSL 证书与 HTTPS 服务
把上一章签发的证书文件准备好。假设你的证书放在 /etc/nginx/ssl/ 目录下:
example.com.crt— 服务器证书example.com.key— 私钥文件ca.crt— 中间证书链(如果有的话)
我建议把证书链合并成一个文件,Nginx 处理起来更干净:
cat example.com.crt ca.crt > fullchain.crt
然后编辑 Nginx 配置文件。我个人习惯把 HTTPS 配置单独放在 /etc/nginx/conf.d/ssl.conf,方便管理。
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html;
}
}
这里有几个关键点:
- listen 443 ssl http2 — 同时启用 SSL 和 HTTP/2。HTTP/2 能显著提升并发性能,我实测过,页面加载能快 30% 以上。
- ssl_protocols — 只允许 TLSv1.2 和 TLSv1.3。SSLv3 和 TLSv1.0/1.1 都太老了,有已知漏洞。
- ssl_ciphers — 只选强加密套件。ECDHE 提供前向安全性,AES-GCM 是硬件加速的。
nginx -t 测试语法。我每次改完配置都会跑一遍,避免手误导致服务重启失败。
3.3 强制 HTTPS 重定向
光配好 443 端口还不够。用户可能直接输入 http://example.com,这时候需要把 HTTP 请求重定向到 HTTPS。
配置很简单,加一个监听 80 端口的 server 块:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
301 是永久重定向。浏览器收到后会记住这个跳转,下次直接访问 HTTPS。不过,我建议第一次部署时先用 302 临时重定向,等确认 HTTPS 完全正常了再改成 301。
为什么会这样?因为 301 会被浏览器缓存,万一你配错了,用户得清缓存才能恢复。我吃过这个亏,线上配完发现证书有问题,结果用户死活访问不了,排查了半天才发现是浏览器缓存了 301。
3.4 安全加固与性能优化
基础配置跑通了,我们再加几层防护。这些是我在项目中总结出来的「必选项」:
| 配置项 | 推荐值 | 说明 |
|---|---|---|
| ssl_session_cache | shared:SSL:10m | 缓存 SSL 会话,减少握手开销。10m 大约能存 40000 个会话 |
| ssl_session_timeout | 10m | 会话超时时间,太短会增加握手次数,太长有安全风险 |
| ssl_stapling | on | OCSP Stapling,让 Nginx 代浏览器查询证书吊销状态,提升访问速度 |
| ssl_stapling_verify | on | 验证 OCSP 响应签名,防止伪造 |
| add_header Strict-Transport-Security | max-age=31536000; includeSubDomains | HSTS 头,告诉浏览器强制使用 HTTPS,连第一次 HTTP 请求都省了 |
把这些加到你的 HTTPS 配置里:
server {
listen 443 ssl http2;
server_name example.com;
# 证书配置
ssl_certificate /etc/nginx/ssl/fullchain.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# 协议与加密套件
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;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
root /var/www/html;
index index.html;
}
}
includeSubDomains,否则子域名 HTTP 服务会全部失效。
3.5 验证配置
配置写完了,重启 Nginx:
nginx -t # 测试语法
systemctl reload nginx # 重新加载配置
然后用浏览器访问 https://example.com,地址栏应该出现小锁图标。点开证书信息,确认签发机构、有效期都正确。
我习惯再用命令行验证一遍:
curl -I https://example.com
# 返回头里应该有 HTTP/2 200 和 strict-transport-security
检查重定向是否生效:
curl -I http://example.com
# 应该返回 301 Moved Permanently,Location 指向 HTTPS 地址
最后,用在线工具(比如 SSL Labs)扫一遍,看看评级。A 级是及格线,A+ 才放心。我一般会盯着这几个指标:
- 证书链是否完整
- 是否支持前向安全性
- 是否启用 HSTS
- 是否禁用不安全的协议
3.6 核心流程回顾
这一章的内容,说白了就是三步:配证书、开 HTTPS、强制定向。但每一步都有细节,漏一个就可能出问题。
下面这张图总结了整个配置流程,你可以对照着检查自己的配置:
嗯,这一章就到这里。配置 HTTPS 其实不复杂,但每一步都关系到安全性和可用性。你按这个流程走一遍,应该能跑通。如果遇到问题,先检查证书路径和端口监听,这两个地方最容易出错。