HTTPS 与 SSL 配置

给网站装上"小绿锁"(HTTPS)已经从加分项变成必修项——Chrome/Firefox 会把 HTTP 站点直接标记为"不安全",Google 也把 HTTPS 作为搜索排名因素。好消息是,配合 Nginx 和 Let's Encrypt,免费启用 HTTPS 只要 5 分钟。这一章我们完整过一遍。

1. 为什么需要 HTTPS?

HTTP 是明文传输,存在三大风险:

HTTPS(HTTP over TLS)通过非对称加密 + 数字证书解决这三个问题。对开发者来说,它还能解锁 PWA、HTTP/2、地理定位、Service Worker 等现代浏览器特性。

2. 最基础的 HTTPS 配置

先看一个能跑起来的最小配置:

# 最基础的 HTTPS 配置
server {
    listen 443 ssl;
    server_name example.com;

    # 证书文件(包含公钥 + 中间证书)
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    # 私钥文件(绝对不能泄露!)
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        root /var/www/example;
        index index.html;
    }
}

核心就两条指令:ssl_certificate(证书)和 ssl_certificate_key(私钥)。剩下的工作就是怎么搞到这两个文件

3. SSL 证书从哪来?三种选择

4. Let's Encrypt + Certbot:一键申请

Certbot 是 Let's Encrypt 官方推荐的客户端工具,它能自动验证域名、申请证书、修改 Nginx 配置、设置自动续期

# 1. 安装 Certbot(Ubuntu/Debian)
sudo apt install -y certbot python3-certbot-nginx

# 2. 一键申请证书并自动修改 Nginx 配置
sudo certbot --nginx -d example.com -d www.example.com

# Certbot 会自动:
#   - 验证你确实拥有该域名(HTTP-01 challenge)
#   - 申请证书并保存到 /etc/letsencrypt/live/example.com/
#   - 修改 Nginx 配置,加上 ssl_certificate 等指令
#   - 配置 HTTP→HTTPS 强制跳转

# 3. 测试自动续期(Let's Encrypt 证书 90 天有效,需定期续)
sudo certbot renew --dry-run

# 4. Certbot 会自动写入 systemd timer 定时续期
sudo systemctl list-timers | grep certbot

几个关键点:

5. HTTP 强制跳转 HTTPS

光配 443 端口还不够,必须把 80 端口的请求也跳转到 HTTPS,否则用户输入 http:// 时还是明文:

# === HTTP 强制跳转 HTTPS(推荐写法)===
server {
    listen 80;
    server_name example.com www.example.com;

    # 直接 301 永久跳转到 HTTPS
    return 301 https://$host$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;

    # 主站配置...
    location / {
        root /var/www/example;
    }
}

# 也可以用 rewrite,但 return 性能更好
# rewrite ^ https://$host$request_uri? permanent;   # 不推荐

注意:不要把整个站点配置在 80 和 443 两份,正确做法是 80 端口只负责 301 跳转。

6. SSL 安全最佳实践(生产必读)

默认的 SSL 配置不够安全——很多老协议(SSLv3、TLS 1.0)存在已知漏洞。生产环境应该用 Mozilla SSL Configuration Generator 的"Intermediate"档:

server {
    listen 443 ssl http2;             # 启用 HTTP/2(性能大幅提升)
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # === 1. 仅启用安全协议 ===
    ssl_protocols TLSv1.2 TLSv1.3;    # 禁用 SSLv3/TLSv1.0/1.1(已不安全)
    ssl_prefer_server_ciphers off;    # 让客户端选密码套件(TLS 1.3 推荐)

    # === 2. 安全的密码套件 ===
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    # 优先使用 ECDHE(前向保密)+ GCM(认证加密)

    # === 3. 会话缓存(性能优化)===
    ssl_session_cache shared:SSL:10m;       # 共享缓存 10MB(约 4 万个会话)
    ssl_session_timeout 10m;                # 缓存有效期
    ssl_session_tickets off;                # 关闭 session ticket(前向保密更严格)

    # === 4. HSTS(强制浏览器以后都走 HTTPS)===
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # === 5. OCSP Stapling(提升 TLS 握手速度)===
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;
}

几个关键安全指令解释:

配置后用 SSL Labs 测试,目标拿到 A 或 A+ 评级。

7. 启用 HTTP/2

HTTP/2 相比 HTTP/1.1 有质的飞跃——多路复用、头部压缩、服务器推送,对页面性能提升明显。HTTPS 是 HTTP/2 的前置条件(所有现代浏览器都只在 HTTPS 上启用 HTTP/2):

# 启用 HTTP/2 的两种写法(Nginx 1.25.1+ 推荐第二种)

# === 旧写法(Nginx 1.9.5 ~ 1.25.0)===
server {
    listen 443 ssl http2;            # 在 listen 上一起声明
    ...
}

# === 新写法(Nginx 1.25.1+,官方推荐)===
server {
    listen 443 ssl;
    http2 on;                        # 用独立指令声明
    ...
}

# 验证是否启用 HTTP/2
curl -I --http2 https://example.com/
# 输出: HTTP/2 200

# 浏览器 DevTools 的 Network 面板,看 Protocol 列是 h2 才对

注意 Nginx 1.25.1 之后官方推荐用独立的 http2 on 指令,旧写法虽然还能用但即将废弃。

8. 一个完整的 HTTPS 生产模板

把上面的内容整合,下面是一个直接可用的 HTTPS 模板(80 跳转 + 443 安全配置 + HTTP/2):

把域名、证书路径改成你的,nginx -s reload 即可。然后用 SSL Labs 跑一遍,拿 A+ 不难。

9. 常见坑与排查

小结

HTTPS 是现代网站的标配,配合 Let's Encrypt + Certbot,免费、自动、安全。这一章你学会了申请证书、配置 SSL、强制跳转、安全加固和 HTTP/2 启用。下一篇讲gzip 压缩——把传输体积砍掉 70%,让页面飞起来。

← 上一篇 反向代理与负载均衡

下一篇 gzip 压缩

✈️💬