lolly/docs/nginx/05-nginx-ssl-https.md
xfy 972eab4267 refactor(docs): 重构文档目录结构,nginx 文档移至子目录
将 docs/ 根目录下的 nginx 相关文档统一移动到 docs/nginx/ 子目录,
提高文档组织性和可维护性。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 10:48:14 +08:00

9.9 KiB
Raw Permalink Blame History

NGINX SSL/TLS 与 HTTPS 配置指南

1. HTTPS 基础配置

最简配置

server {
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}

完整配置示例

server {
    listen 443 ssl http2;
    server_name www.example.com;

    # 证书配置
    ssl_certificate      /etc/nginx/ssl/www.example.com.crt;
    ssl_certificate_key  /etc/nginx/ssl/www.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;
    ssl_session_tickets  off;

    # OCSP Stapling
    ssl_stapling         on;
    ssl_stapling_verify  on;
    resolver             8.8.8.8 8.8.4.4 valid=300s;

    # 安全头部
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        root /var/www/html;
    }
}

2. SSL 指令详解

证书与密钥

指令 说明
ssl_certificate PEM 格式证书文件路径
ssl_certificate_key PEM 格式私钥文件路径
ssl_password_file 私钥密码文件(每行一个密码)
ssl_certificate     /path/to/cert.crt;
ssl_certificate_key /path/to/key.key;

# 多证书类型RSA + ECDSA
ssl_certificate     /path/to RSA.crt;
ssl_certificate     /path/to ECDSA.crt;
ssl_certificate_key /path/to RSA.key;
ssl_certificate_key /path/to ECDSA.key;

注意

  • 证书是公开实体,可设置较宽松权限
  • 私钥需限制访问权限600但 nginx 主进程可读
  • 私钥可与证书存放在同一文件中

协议配置

指令 说明 默认值
ssl_protocols 启用的协议 TLSv1.2 TLSv1.3
ssl_ciphers 启用的加密套件 HIGH:!aNULL:!MD5
ssl_prefer_server_ciphers 服务器套件优先 off
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;

ssl_prefer_server_ciphers on;

协议版本建议

版本 建议
SSLv2 禁用(不安全)
SSLv3 禁用POODLE 攻击)
TLSv1.0 禁用(旧浏览器兼容时可用)
TLSv1.1 禁用
TLSv1.2 启用
TLSv1.3 启用(推荐)

3. 会话缓存

缓存类型

类型 说明
off 禁用会话缓存
none 不使用缓存,但允许会话票据
builtin 内置 OpenSSL 缓存(单 worker
shared 共享内存缓存(所有 worker

配置示例

# 推荐:共享缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

# 1MB 约存储 4000 个会话
# 多 worker 共享,避免重复握手

会话票据

ssl_session_tickets on;              # 默认 on
ssl_session_ticket_key /path/to/key; # 加密票据密钥

密钥轮转

ssl_session_ticket_key /path/to/old.key;
ssl_session_ticket_key /path/to/current.key;
ssl_session_ticket_key /path/to/new.key;

4. OCSP Stapling

减少 SSL 握手时间,提升性能。

ssl_stapling on;
ssl_stapling_verify on;
ssl_stapling_file /path/to/ocsp.der;          # 可选:手动指定 OCSP 响应
ssl_stapling_responder http://ocsp.example.com;  # 可选:覆盖响应者 URL
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

5. 客户端证书验证

基础配置

ssl_client_certificate /path/to/ca.crt;
ssl_verify_client on;                # on | off | optional | optional_no_ca
ssl_verify_depth 2;
参数 说明
on 必须提供有效证书
off 不验证客户端证书
optional 可选验证,失败仍允许访问
optional_no_ca 可选证书,不验证有效性

错误处理

# 验证错误返回 495
error_page 495 /cert_error.html;

# 未提供证书返回 496
error_page 496 /no_cert.html;

# HTTP 请求发送到 HTTPS 端口返回 497
error_page 497 /redirect.html;

6. HTTPS 服务器优化

CPU 资源优化

SSL 握手消耗 CPU 资源,建议:

worker_processes auto;               # 与 CPU 核心数相同
keepalive_timeout 70;                # 延长连接,减少握手
ssl_session_cache shared:SSL:10m;    # 会话缓存

DH 参数

增强 DHE 加密套件安全性:

ssl_dhparam /path/to/dhparam.pem;

# 生成 DH 参数
openssl dhparam -out dhparam.pem 2048

ECDH 曲线

ssl_ecdh_curve auto;                 # 默认 auto
ssl_ecdh_curve prime256v1:secp384r1; # 指定曲线

7. SSL 证书链

证书链问题

浏览器报错证书可信度问题,可能缺少中间证书。

解决方案

# 合并证书链
cat www.example.com.crt bundle.crt > www.example.com.chained.crt

注意顺序:服务器证书必须排在中间证书之前。

验证证书链

openssl s_client -connect www.example.com:443

8. 单服务器 HTTP/HTTPS

server {
    listen 80;
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
}

HTTP 重定向到 HTTPS

server {
    listen 80;
    server_name www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name www.example.com;
    # ...
}

9. 多域名 HTTPSSNI

问题

在单个 IP 上配置多个 HTTPS 服务器时SSL 握手发生在 HTTP 请求之前,默认返回默认服务器证书。

解决方案

方案一SNIServer Name Indication

server {
    listen 443 ssl;
    server_name www.example.com;
    ssl_certificate www.example.com.crt;
    ssl_certificate_key www.example.com.key;
}

server {
    listen 443 ssl;
    server_name www.example.org;
    ssl_certificate www.example.org.crt;
    ssl_certificate_key www.example.org.key;
}

要求

  • OpenSSL 0.9.8f+(启用 --enable-tlsext
  • 0.9.8j+ 默认启用
  • 大多数现代浏览器支持

验证 SNI 支持

nginx -V | grep "TLS SNI support enabled"

方案二:多名称证书

使用 SubjectAltName 或通配符证书:

# 通配符证书(仅匹配一级子域名)
ssl_certificate *.example.com.crt;

# SubjectAltName 证书(多个域名)
# 包含 example.com 和 example.org

方案三:共享证书

http {
    ssl_certificate     shared.crt;
    ssl_certificate_key shared.key;

    server {
        listen 443 ssl;
        server_name www.example.com;
    }

    server {
        listen 443 ssl;
        server_name www.example.org;
    }
}

10. HTTP/2 配置

启用 HTTP/2

server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;
}

HTTP/2 推送

http2_push /style.css;
http2_push /image.png;

# 条件推送
http2_push_preload on;
# 配合 Link 响应头Link: </style.css>; rel=preload; as=style

11. HTTP/3 (QUIC) 配置

版本要求

NGINX 1.25.0+,需编译 --with-http_v3_module

SSL 库要求

推荐 OpenSSL 3.5.1+,支持 early data。可选 BoringSSL、LibreSSL、QuicTLS。

配置示例

server {
    listen 443 quic reuseport;
    listen 443 ssl;
    server_name www.example.com;

    ssl_certificate     www.example.com.crt;
    ssl_certificate_key www.example.com.key;

    ssl_protocols TLSv1.3;            # HTTP/3 需要 TLSv1.3

    quic_retry on;                    # 地址验证
    quic_gso on;                      # Generic Segmentation Offloading
    quic_host_key /path/to/key;       # Token 密钥

    ssl_early_data on;                # 0-RTT
    add_header Alt-Svc 'h3=":443"; ma=86400';  # 声明 HTTP/3 支持
}

12. 安全头部配置

# HSTS强制 HTTPS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

# 防止 MIME 类型嗅探
add_header X-Content-Type-Options "nosniff" always;

# XSS 保护
add_header X-XSS-Protection "1; mode=block" always;

# 禁止 iframe 嵌入
add_header X-Frame-Options "SAMEORIGIN" always;

# CSP
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'" always;

13. 内置变量

变量 说明
$ssl_protocol 建立的 SSL 协议版本
$ssl_cipher 当前连接使用的加密套件
$ssl_ciphers 客户端支持的加密套件列表
$ssl_client_cert 客户端证书PEM 格式)
$ssl_client_fingerprint 客户端证书 SHA1 指纹
$ssl_client_s_dn 客户端证书 Subject DN
$ssl_client_i_dn 客户端证书 Issuer DN
$ssl_client_serial 客户端证书序列号
$ssl_client_verify 验证结果SUCCESS/FAILED/NONE
$ssl_server_name SNI 请求的服务器名称
$ssl_session_id 会话 ID
$ssl_session_reused 会话是否复用r 或 .
$ssl_early_data 是否使用 TLS 1.3 early data

14. 配置检查与测试

检查配置

nginx -t

测试 SSL 配置

# 检查证书
openssl s_client -connect www.example.com:443 -servername www.example.com

# 检查协议支持
openssl s_client -connect www.example.com:443 -tls1_2
openssl s_client -connect www.example.com:443 -tls1_3

# 检查加密套件
nmap --script ssl-enum-ciphers -p 443 www.example.com

# 使用 testssl.sh 工具
testssl.sh www.example.com

在线测试工具