Nginx 配置 HTTPS (SSL/TLS) 完全教程 – wiki基地


Nginx 配置 HTTPS (SSL/TLS) 完全教程:从入门到精通

在当今互联网环境中,数据安全和用户隐私至关重要。HTTPS(基于 SSL/TLS 的 HTTP)已不再是可选项,而是现代网站的标配。它通过加密客户端和服务器之间的通信,防止数据在传输过程中被窃听或篡改,同时也能验证服务器的身份,增强用户信任。Nginx 作为全球最受欢迎的高性能 Web 服务器和反向代理服务器之一,配置 HTTPS 是其核心功能。

本教程将详细、深入地指导您如何在 Nginx 上配置 HTTPS,涵盖从基本概念、获取证书到高级优化和故障排除的各个方面,旨在为您提供一份全面、实用的操作指南。

文章结构:

  1. HTTPS 与 SSL/TLS 基础
    • 什么是 HTTPS?
    • SSL/TLS 的作用与区别
    • 为什么需要 HTTPS?(安全性、信任度、SEO 优势)
  2. SSL/TLS 证书详解
    • 证书的作用:加密与身份验证
    • 证书类型:DV、OV、EV
    • 证书的组成部分:公钥、私钥、中间证书、根证书
  3. 获取 SSL/TLS 证书
    • 方法一:使用 Let’s Encrypt 获取免费证书 (推荐)
      • Certbot 工具介绍与安装
      • 使用 Certbot 独立模式 (Standalone) 获取证书
      • 使用 Certbot Nginx 插件获取并自动配置
      • 证书文件位置与说明
    • 方法二:购买商业证书
      • 选择证书颁发机构 (CA)
      • 生成证书签名请求 (CSR)
      • 域名验证过程
      • 获取并整合证书文件 (服务器证书、中间证书链)
    • 方法三:生成自签名证书 (仅限测试/内部环境)
      • 使用 OpenSSL 生成自签名证书
      • 自签名证书的局限性
  4. Nginx 配置 HTTPS 核心步骤
    • 基本配置 (nginx.confsites-available/your_domain)
      • 监听 443 端口 (listen 443 ssl;)
      • 启用 HTTP/2 (推荐: http2)
      • 指定证书和私钥文件路径 (ssl_certificate, ssl_certificate_key)
      • 处理证书链 (合并证书文件或使用 ssl_trusted_certificate)
    • 配置安全的 SSL/TLS 协议和加密套件
      • 禁用不安全的协议 (ssl_protocols TLSv1.2 TLSv1.3;)
      • 选择强加密套件 (ssl_ciphers)
      • 优先使用服务器端加密套件 (ssl_prefer_server_ciphers on;)
    • 启用 HSTS (HTTP Strict Transport Security)
      • add_header Strict-Transport-Security "max-age=...";
      • includeSubDomainspreload 参数详解
    • 配置 OCSP Stapling (在线证书状态协议 Stapling)
      • ssl_stapling on;
      • ssl_stapling_verify on;
      • ssl_resolver 指令配置
    • 生成和配置 Diffie-Hellman 参数
      • 使用 openssl dhparam 生成强 DH 参数文件
      • ssl_dhparam 指令配置
    • 将 HTTP 流量重定向到 HTTPS
      • 方法一:在 HTTP server 块中使用 return 301
      • 方法二:为 HTTP 和 HTTPS 使用单独的 server 块 (推荐)
  5. 配置示例与验证
    • 一个完整的 Nginx HTTPS server 块配置示例
    • 检查 Nginx 配置语法 (nginx -t)
    • 重启或重新加载 Nginx (systemctl restart/reload nginxservice nginx restart/reload)
    • 使用浏览器访问验证 (检查地址栏挂锁图标)
    • 使用在线 SSL 测试工具 (如 SSL Labs) 进行全面评估
  6. 证书自动续期 (Let’s Encrypt)
    • Certbot 的自动续期机制 (certbot renew)
    • 配置 Cron Job 或 Systemd Timer
    • 测试自动续期 (certbot renew --dry-run)
  7. 高级主题与最佳实践
    • 启用会话复用 (Session Resumption)
      • ssl_session_cache
      • ssl_session_timeout
      • ssl_session_tickets (谨慎使用)
    • 多域名证书 (SAN 证书) 与通配符证书
    • SNI (Server Name Indication) 支持 (Nginx 默认支持)
    • 性能优化考量
    • 安全相关的 HTTP 头部 (Content-Security-Policy, X-Frame-Options 等)
  8. 常见问题与故障排除
    • Nginx 无法启动/加载配置失败
    • 浏览器显示证书错误 (无效、过期、不匹配)
    • 混合内容 (Mixed Content) 警告
    • SSL 握手失败
    • OCSP Stapling 无法工作
    • HSTS 配置问题
  9. 总结

1. HTTPS 与 SSL/TLS 基础

什么是 HTTPS?
HTTPS (HyperText Transfer Protocol Secure) 是 HTTP 的安全版本。它在 HTTP 协议基础上,通过 SSL/TLS 协议对通信进行加密和身份验证。当您访问一个使用 HTTPS 的网站时,浏览器地址栏通常会显示一个挂锁图标,表示连接是安全的。

SSL/TLS 的作用与区别
SSL (Secure Sockets Layer) 是早期用于网络通信安全的协议。TLS (Transport Layer Security) 是 SSL 的继任者,提供了更强的安全性和性能。虽然我们常说 “SSL 证书”,但现代实践中使用的几乎都是 TLS 协议 (TLS 1.2 和 TLS 1.3 是当前推荐的版本)。SSL/TLS 协议主要提供三个核心功能:

  • 加密 (Encryption): 确保客户端和服务器之间传输的数据是加密的,防止中间人窃听。
  • 数据完整性 (Integrity): 确保数据在传输过程中没有被篡改。
  • 身份验证 (Authentication): 验证您正在与之通信的服务器确实是它声称的那个服务器(通过 SSL/TLS 证书)。

为什么需要 HTTPS?

  • 安全性: 保护敏感信息(如登录凭据、支付信息、个人数据)在传输过程中的安全。
  • 信任度: 地址栏的挂锁图标能显著提升用户对网站的信任感。浏览器会对没有 HTTPS 的网站标记为 “不安全”。
  • SEO 优势: Google 等搜索引擎已将 HTTPS 作为排名因素之一,优先收录和排名 HTTPS 网站。
  • 合规性要求: 许多行业法规(如 PCI DSS)要求对敏感数据传输进行加密。
  • 现代 Web 功能需要: 许多新的浏览器特性(如地理位置 API、Service Workers、HTTP/2)只在 HTTPS 环境下可用。

2. SSL/TLS 证书详解

证书的作用
SSL/TLS 证书就像网站的数字身份证。它由受信任的第三方机构——证书颁发机构 (Certificate Authority, CA) 签发,包含以下关键信息:

  • 域名信息: 证书适用的域名(或多个域名)。
  • 所有者信息: 网站所有者的信息(根据证书类型不同,详细程度各异)。
  • CA 信息: 签发该证书的 CA 的信息和数字签名。
  • 公钥: 用于加密数据和验证签名的公钥。
  • 有效期: 证书的有效起始和截止日期。
  • 序列号: 证书的唯一标识符。

证书类型

  • 域名验证 (Domain Validated, DV): 最基础的证书类型。CA 只验证申请者对域名的控制权(通常通过 DNS 记录或邮箱验证)。颁发速度快,成本低(甚至免费,如 Let’s Encrypt)。适合个人博客、小型网站等。
  • 组织验证 (Organization Validated, OV): 除了域名验证,CA 还会对申请组织的真实性进行审核(如核查营业执照等)。证书中会包含组织名称等信息,提供更高的信任度。适合企业、电子商务网站。
  • 扩展验证 (Extended Validation, EV): 最高级别的验证。CA 会进行非常严格的组织身份审核。在部分旧版浏览器中,地址栏会显示为绿色,并直接显示组织名称,提供最高的视觉信任度。适合金融机构、大型电商等对信任度要求极高的网站。

证书的组成部分

  • 服务器证书 (Server Certificate): 包含公钥和身份信息的文件,通常是 .crt.pem 格式。这是配置 Nginx 时 ssl_certificate 指令需要的文件。
  • 私钥 (Private Key): 与服务器证书中的公钥配对的密钥,必须严格保密。用于解密客户端发送的数据和生成数字签名。通常是 .key.pem 格式。这是 ssl_certificate_key 指令需要的文件。
  • 中间证书 (Intermediate Certificate) / 证书链 (Certificate Chain): 为了提高安全性,根 CA 通常不会直接签发服务器证书,而是授权一个或多个中间 CA 来签发。中间证书用于连接您的服务器证书和受信任的根 CA 证书,形成一个信任链。浏览器需要这个链来验证服务器证书的有效性。这些证书通常需要与服务器证书合并成一个文件(通常是 .pem.crt),或者在 Nginx 中使用 ssl_trusted_certificate (主要用于 OCSP Stapling) 指令指定。
  • 根证书 (Root Certificate): 由顶级 CA 签发,预装在操作系统和浏览器中。它们是信任链的起点。

3. 获取 SSL/TLS 证书

方法一:使用 Let’s Encrypt 获取免费证书 (推荐)

Let’s Encrypt 是一个免费、自动化、开放的证书颁发机构 (CA),极大地推动了 HTTPS 的普及。Certbot 是 Let’s Encrypt 推荐的客户端工具,可以自动化证书的获取、安装和续期。

  1. Certbot 工具介绍与安装:
    Certbot 可以通过多种方式安装,推荐使用 snapd (如果系统支持) 或操作系统的包管理器 (如 apt, yum)。

    • 使用 Snap (推荐):
      bash
      sudo snap install core; sudo snap refresh core
      sudo snap install --classic certbot
      sudo ln -s /snap/bin/certbot /usr/bin/certbot
    • 使用 apt (Debian/Ubuntu):
      bash
      sudo apt update
      sudo apt install certbot python3-certbot-nginx # 安装 Nginx 插件
    • 使用 yum (CentOS/RHEL):
      bash
      sudo yum install epel-release # 可能需要先安装 EPEL 源
      sudo yum install certbot python3-certbot-nginx
  2. 使用 Certbot Nginx 插件获取并自动配置 (推荐):
    这是最简单的方式,Certbot 会自动检测您的 Nginx 配置,获取证书,并修改 Nginx 配置文件以启用 HTTPS。
    bash
    sudo certbot --nginx -d your_domain.com -d www.your_domain.com

    • -d 参数用于指定需要申请证书的域名,可以指定多个。
    • Certbot 会引导您完成过程,包括输入邮箱地址(用于接收续期提醒)、同意服务条款,以及选择是否将 HTTP 流量自动重定向到 HTTPS。
  3. 使用 Certbot 独立模式 (Standalone) 获取证书:
    如果您不想让 Certbot 修改 Nginx 配置,或者 Nginx 暂时未运行,可以使用独立模式。此模式下,Certbot 会临时启动一个小型 Web 服务器监听 80 端口来完成域名验证。执行前需要确保 80 端口未被占用(可以临时停止 Nginx)。
    bash
    sudo certbot certonly --standalone -d your_domain.com -d www.your_domain.com

    • certonly 表示只获取证书,不进行安装。
    • 获取证书后,您需要手动配置 Nginx。
  4. 证书文件位置与说明:
    通过 Certbot 获取的证书通常位于 /etc/letsencrypt/live/your_domain.com/ 目录下。这里的文件是符号链接,指向 /etc/letsencrypt/archive/ 目录下的实际版本化文件。在 Nginx 配置中,应始终使用 /etc/letsencrypt/live/ 路径下的文件,因为 Certbot 在续期时会自动更新这些符号链接。

    • cert.pem: 服务器证书。
    • chain.pem: 中间证书链。
    • fullchain.pem: 服务器证书 + 中间证书链 (推荐在 Nginx ssl_certificate 中使用这个)。
    • privkey.pem: 私钥 (用于 Nginx ssl_certificate_key)。

方法二:购买商业证书

  1. 选择证书颁发机构 (CA): 如 DigiCert, Sectigo, GlobalSign 等。根据需求(DV/OV/EV)、价格、服务等因素选择。
  2. 生成证书签名请求 (CSR): CSR 包含您的公钥和一些身份信息(如域名、组织名称、地点等)。通常使用 openssl 命令生成:
    bash
    openssl req -new -newkey rsa:2048 -nodes -keyout your_domain.key -out your_domain.csr

    • -newkey rsa:2048: 生成一个新的 2048 位 RSA 私钥 (your_domain.key)。
    • -nodes: 不加密私钥文件(如果需要密码保护私钥,去掉此选项)。
    • -keyout: 指定私钥文件名。
    • -out: 指定 CSR 文件名 (your_domain.csr)。
    • 执行过程中会提示输入国家、省份、城市、组织名称、通用名称 (Common Name, CN – 必须是您的主域名) 等信息。
  3. 域名验证: 将生成的 CSR 文件内容提交给 CA。CA 会要求您通过某种方式验证您对域名的所有权(如添加 DNS TXT 记录、在特定路径上传文件、回复验证邮件等)。OV/EV 证书还需要额外的组织身份验证。
  4. 获取并整合证书文件: 验证通过后,CA 会提供证书文件。通常包括:

    • 服务器证书 (例如 your_domain.crt)
    • 中间证书 (可能是一个或多个文件,或一个包含所有中间证书的 .ca-bundle 文件)
    • 根证书 (通常不需要配置,浏览器/操作系统自带)

    您需要将服务器证书和所有中间证书合并成一个文件,供 Nginx ssl_certificate 指令使用。顺序通常是:服务器证书 -> 中间证书 1 -> 中间证书 2 -> …
    bash
    cat your_domain.crt intermediate_bundle.crt > your_domain_fullchain.crt

    然后将 your_domain_fullchain.crt 和之前生成的 your_domain.key 用于 Nginx 配置。

方法三:生成自签名证书 (仅限测试/内部环境)

自签名证书不由受信任的 CA 签发,而是由您自己签发。浏览器会警告用户连接不安全,因为它无法验证证书的真实性。绝不能用于公共网站。

使用 OpenSSL 生成:
bash
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

* -x509: 输出自签名证书而不是 CSR。
* -days 365: 证书有效期为 365 天。
* -keyout-out: 指定私钥和证书的输出路径。确保目录存在且权限安全 (sudo chmod 600 /etc/ssl/private/nginx-selfsigned.key)。
* 同样会提示输入证书信息,CN 应为您的域名或 IP 地址。

4. Nginx 配置 HTTPS 核心步骤

HTTPS 的配置通常在 Nginx 的 server 块中进行,该块可以位于主配置文件 nginx.conf 内,或者更常见的做法是在 sites-available 目录下为每个站点创建一个配置文件,然后链接到 sites-enabled 目录。

假设您的配置文件位于 /etc/nginx/sites-available/your_domain

基本配置

“`nginx
server {
listen 80; # 监听 HTTP 端口
listen [::]:80;
server_name your_domain.com www.your_domain.com;

# ... (稍后添加重定向配置)

}

server {
listen 443 ssl http2; # 监听 443 端口,启用 SSL/TLS,启用 HTTP/2
listen [::]:443 ssl http2;
server_name your_domain.com www.your_domain.com;

# --- SSL Certificate Configuration ---
# 使用 Let's Encrypt 证书 (推荐使用 fullchain.pem)
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;

# 使用商业证书 (合并后的文件和私钥)
# ssl_certificate /etc/nginx/ssl/your_domain_fullchain.crt;
# ssl_certificate_key /etc/nginx/ssl/your_domain.key;

# 使用自签名证书
# ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
# ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

# --- 其他 SSL/TLS 优化配置将在这里添加 ---

# --- 您的网站根目录和 location 配置 ---
root /var/www/your_domain/html;
index index.html index.htm index.nginx-debian.html;

location / {
    try_files $uri $uri/ =404;
}

# 其他 location, PHP-FPM 等配置...

}
“`

  • listen 443 ssl;: 告诉 Nginx 在 443 端口监听,并处理 SSL/TLS 连接。
  • http2: 启用 HTTP/2 协议,它可以显著提高 HTTPS 连接的性能。推荐启用。
  • ssl_certificate: 指定包含服务器证书和中间证书链的 PEM 文件路径。
  • ssl_certificate_key: 指定服务器私钥的 PEM 文件路径。权限必须严格控制,只有 root 和 Nginx 进程用户可读。

配置安全的 SSL/TLS 协议和加密套件

禁用已知不安全的旧协议 (SSLv3, TLSv1.0, TLSv1.1),只启用安全的 TLSv1.2 和 TLSv1.3。选择强加密套件,并优先使用服务器端选择的套件。

将以下配置添加到 HTTPS server 块的 SSL 配置部分:

nginx
# --- Secure SSL/TLS Protocols and Ciphers ---
ssl_protocols TLSv1.2 TLSv1.3; # 只允许 TLS 1.2 和 1.3
ssl_prefer_server_ciphers on; # 优先使用服务器端选择的加密套件
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; # 推荐的强加密套件组合 (兼容性较好)
# 对于 TLS 1.3, 加密套件由 ssl_conf_command 指令管理,或默认使用安全的
# ssl_conf_command Options -ServerPreference; # 如果你想让客户端优先选择 TLS 1.3 套件

  • ssl_protocols: 指定允许的协议版本。TLSv1.2 和 TLSv1.3 是当前安全的标准。
  • ssl_prefer_server_ciphers on;: 防止客户端强制使用较弱的加密套件。
  • ssl_ciphers: 定义允许使用的加密套件列表,按优先顺序排列。上述列表是一个兼顾安全性和兼容性的推荐组合(参考 Mozilla SSL Configuration Generator 等)。

启用 HSTS (HTTP Strict Transport Security)

HSTS 告诉浏览器,该网站在未来指定的时间内(max-age)只能通过 HTTPS 访问。这可以防止 SSL 剥离攻击 (SSL stripping)。

nginx
# --- HSTS Configuration (add inside the https server block) ---
# max-age 单位为秒, 63072000 秒 = 2 年
# includeSubDomains 表示策略也应用于所有子域名
# preload 表示授权浏览器将此域名加入 HSTS 预加载列表 (需要先满足条件并手动提交到 hstspreload.org)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

  • max-age: 浏览器应该记住只使用 HTTPS 的时间长度(秒)。建议设置较长时间,如 6 个月 (15552000) 或更长。
  • includeSubDomains: 可选,如果您的所有子域名也都强制 HTTPS,则添加此项。
  • preload: 可选,只有当您确认网站完全支持 HTTPS 并且打算长期维持,并且已将域名提交到 HSTS 预加载列表 (hstspreload.org) 时才添加。首次配置 HSTS 时,建议先使用较短的 max-age (如 300 秒) 并去掉 preload,测试无误后再逐步增加 max-age 并考虑 preload
  • always: 确保 HSTS 头部在所有响应中(包括错误页面)都被发送。

配置 OCSP Stapling

OCSP Stapling 允许 Nginx 定期从 CA 获取证书的有效性状态(OCSP 响应),并将其“钉”在 TLS 握手过程中发送给客户端。这避免了客户端浏览器自己去查询 OCSP 服务器,提高了连接速度和用户隐私。

“`nginx
# — OCSP Stapling Configuration —
ssl_stapling on; # 启用 OCSP Stapling
ssl_stapling_verify on; # 验证 Nginx 获取到的 OCSP 响应
# 需要指定包含中间证书和根证书的链文件 (Let’s Encrypt 的 fullchain.pem 通常已包含)
# 如果使用商业证书, 确保 ssl_certificate 文件包含完整的链, 或者单独指定:
# ssl_trusted_certificate /path/to/your_ca_chain.pem; # 通常指向包含中间证书和根证书的文件
ssl_trusted_certificate /etc/letsencrypt/live/your_domain.com/chain.pem; # 对于 Let’s Encrypt, 可以用 chain.pem

# 需要 DNS 解析器来查询 OCSP 服务器地址
resolver 8.8.8.8 8.8.4.4 valid=300s; # 使用 Google Public DNS
resolver_timeout 5s;

“`

  • ssl_stapling on;: 开启 OCSP Stapling。
  • ssl_stapling_verify on;: 让 Nginx 验证从 OCSP Responder 收到的响应。
  • ssl_trusted_certificate: 指定包含 CA 信任链的文件,用于验证 OCSP 响应签名。对于 Let’s Encrypt,chain.pemfullchain.pem 通常都可以。
  • resolver: 必须配置 DNS 解析器,以便 Nginx 能够解析 OCSP 服务器的域名。可以使用公共 DNS 或您自己的 DNS 服务器。

生成和配置 Diffie-Hellman 参数

对于支持 DHE (Diffie-Hellman Ephemeral) 密钥交换的加密套件,需要一组强的 Diffie-Hellman 参数来增强前向保密性 (Forward Secrecy)。

  1. 生成 DH 参数文件 (需要一些时间):
    bash
    sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
    # 推荐使用 2048 位,也可以选择 4096 位(更安全但更耗时)
    # 确保目录 /etc/nginx/ssl/ 存在
  2. 在 Nginx 配置中指定 DH 参数文件:
    nginx
    # --- Diffie-Hellman Parameters ---
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;

将 HTTP 流量重定向到 HTTPS

确保所有通过 HTTP (80 端口) 访问您网站的用户都被自动重定向到安全的 HTTPS (443 端口)。

修改前面提到的 HTTP server 块 (监听 80 端口的那个):

“`nginx
server {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;

# --- Method 1: Simple Redirect (Recommended) ---
# 对所有请求返回 301 永久重定向到 HTTPS 版本
return 301 https://$host$request_uri;

# --- Method 2: Redirect for Let's Encrypt ACME Challenge ---
# 如果使用 certbot webroot 插件,需要允许 /.well-known/acme-challenge 访问
# location /.well-known/acme-challenge/ {
#     root /var/www/certbot; # 或者你指定的 webroot 路径
# }
# location / {
#     return 301 https://$host$request_uri;
# }

}
“`

  • return 301 https://$host$request_uri;: 这是最简洁高效的方式。$host 获取请求头中的 Host 字段 (即域名),$request_uri 获取请求的路径和查询参数。301 表示永久重定向,对 SEO 友好。

5. 配置示例与验证

完整的 Nginx HTTPS server 块配置示例

“`nginx

/etc/nginx/sites-available/your_domain

HTTP to HTTPS Redirect Server Block

server {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;

# Let's Encrypt ACME challenge handler (if using webroot)
# location /.well-known/acme-challenge/ {
#     allow all;
#     root /var/www/html; # Adjust to your webroot
# }

# Redirect all other HTTP traffic to HTTPS
location / {
    return 301 https://$host$request_uri;
}

}

HTTPS Server Block

server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your_domain.com www.your_domain.com;

root /var/www/your_domain/html;
index index.html index.htm;

# --- SSL Certificate Configuration ---
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/your_domain.com/chain.pem; # For OCSP Stapling

# --- Secure SSL/TLS Settings ---
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
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_session_timeout 1d; # 1 day
ssl_session_cache shared:SSL:10m; # 10 megabytes shared cache
ssl_session_tickets off; # Recommended to disable unless specific need

# --- OCSP Stapling ---
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s; # Use Google's DNS or your preferred DNS
resolver_timeout 5s;

# --- Diffie-Hellman Parameters ---
ssl_dhparam /etc/nginx/ssl/dhparam.pem; # Path to your dhparam file

# --- HSTS (HTTP Strict Transport Security) ---
# Add HSTS header. Start with a low max-age for testing (e.g., 300 seconds).
# Once confirmed working, increase max-age (e.g., 63072000 for 2 years)
# Consider adding 'includeSubDomains' and 'preload' after thorough testing.
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;

# --- Security Headers (Optional but Recommended) ---
# add_header X-Frame-Options "SAMEORIGIN" always;
# add_header X-Content-Type-Options "nosniff" always;
# add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; ..." always; # Requires careful tuning
# add_header Permissions-Policy "interest-cohort=()" always; # Disable FLoC

# --- Location Blocks & Application Logic ---
location / {
    try_files $uri $uri/ =404;
}

# Example PHP-FPM configuration (adjust as needed)
# location ~ \.php$ {
#     include snippets/fastcgi-php.conf;
#     fastcgi_pass unix:/run/php/php8.1-fpm.sock; # Adjust PHP version/socket path
#     fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#     include fastcgi_params;
# }

# Deny access to hidden files
location ~ /\.ht {
    deny all;
}

}
“`

验证步骤

  1. 检查 Nginx 配置语法:
    bash
    sudo nginx -t

    如果显示 syntax is oktest is successful,则配置无误。否则,根据错误提示修改配置文件。

  2. 重启或重新加载 Nginx:

    • 重新加载(推荐,不中断现有连接):sudo systemctl reload nginxsudo service nginx reload
    • 重启(如果 reload 失败或需要彻底应用更改):sudo systemctl restart nginxsudo service nginx restart
  3. 使用浏览器访问验证:
    打开浏览器,输入 https://your_domain.com。检查:

    • 地址栏是否显示 https:// 和一个挂锁图标。
    • 点击挂锁图标,查看证书信息是否正确(颁发给、颁发者、有效期)。
    • 尝试访问 http://your_domain.com,是否自动跳转到 HTTPS。
    • 浏览网站不同页面,确保没有“混合内容”警告(浏览器开发者工具 Console 面板会提示)。
  4. 使用在线 SSL 测试工具:
    访问 Qualys SSL Labs’ SSL Server Test,输入您的域名进行全面测试。理想情况下,您应该争取获得 A 或 A+ 评级。该工具会详细报告协议支持、密钥交换、加密套件强度、证书链、HSTS、OCSP Stapling 等配置情况,并给出改进建议。

6. 证书自动续期 (Let’s Encrypt)

Let’s Encrypt 证书有效期为 90 天,必须在到期前续期。Certbot 设计了自动续期功能。

  1. Certbot 自动续期机制:
    Certbot 安装时通常会自动设置一个计划任务 (Cron Job 或 Systemd Timer) 来定期运行 certbot renew 命令。该命令会检查所有通过 Certbot 获取的证书,如果证书将在 30 天内到期,它会自动尝试续期。

  2. 检查自动续期任务:

    • Systemd: sudo systemctl list-timers | grep certbot
    • Cron: sudo ls -l /etc/cron.d/certbotsudo crontab -l
  3. 手动测试自动续期:
    可以使用 --dry-run 选项模拟续期过程,而不会真正获取新证书或修改文件:
    bash
    sudo certbot renew --dry-run

    如果模拟成功,说明自动续期配置可能正常工作。

  4. 确保 Nginx 在续期后重新加载配置:
    certbot renew 命令通常包含一个 “deploy hook”,在成功续期后自动执行命令来使 Web 服务器加载新证书。对于 Nginx 插件 (--nginx),这通常是自动处理的。如果使用 certonly,您可能需要配置 hook:

    • 编辑 /etc/letsencrypt/renewal/your_domain.com.conf 文件,在 [renewalparams] 段添加或修改 renew_hook
      ini
      renew_hook = systemctl reload nginx
    • 或者,在运行 certbot renew 时通过 --deploy-hook 参数指定:
      bash
      sudo certbot renew --deploy-hook "systemctl reload nginx"
    • Certbot 的默认 Cron/Systemd 任务通常会包含合适的 hook。

7. 高级主题与最佳实践

  • 启用会话复用 (Session Resumption): TLS 握手过程比较耗费计算资源。会话复用允许客户端和服务器重用之前的协商结果,跳过完整的握手过程,加快后续连接速度。
    • ssl_session_cache shared:SSL:10m;: 定义一个 10MB 的共享内存区域来存储会话参数。大小根据并发连接数调整。
    • ssl_session_timeout 1d;: 设置会话参数在缓存中的有效时间(例如 1 天)。
    • ssl_session_tickets on/off;: 会话票证 (Session Tickets) 是另一种会话复用机制,但存在一些安全隐患(如无法有效撤销、削弱前向保密性)。除非有特定需求并了解其风险,否则建议关闭 (off)。
  • 多域名证书 (SAN) 与通配符证书:
    • SAN (Subject Alternative Name) 证书: 一个证书可以包含多个域名(如 your_domain.com, www.your_domain.com, blog.your_domain.com)。使用 Certbot 时,通过多个 -d 参数即可申请 SAN 证书。
    • 通配符证书: 一个证书可以保护一个域名及其所有下一级子域名(如 *.your_domain.com)。申请通配符证书通常需要 DNS 验证方式。certbot certonly --manual --preferred-challenges dns -d *.your_domain.com -d your_domain.com (需要手动添加 DNS TXT 记录)。
  • SNI (Server Name Indication): 允许多个 HTTPS 站点共享同一个 IP 地址和端口。客户端在 TLS 握手初期发送请求的域名,服务器根据此域名选择正确的证书。Nginx 默认支持 SNI,无需特殊配置,只需为每个域名配置相应的 server 块即可。
  • 性能优化考量:
    • 启用 HTTP/2 (http2)。
    • 启用 OCSP Stapling。
    • 启用会话复用 (主要是 ssl_session_cache)。
    • 选择高效的加密套件(ECDHE 优于 DHE,AES-GCM 优于 AES-CBC)。
    • 硬件加速(如果服务器 CPU 支持 AES-NI 指令集,Nginx 通常会自动利用)。
  • 安全相关的 HTTP 头部: 除了 HSTS,还可以配置其他安全头部来增强防护:
    • X-Frame-Options "SAMEORIGIN";"DENY";: 防止点击劫持。
    • X-Content-Type-Options "nosniff";: 防止浏览器 MIME 类型嗅探。
    • Content-Security-Policy: 定义允许加载的资源来源,非常强大但配置复杂,可有效防止 XSS。
    • Referrer-Policy: 控制 Referer 头部的发送策略。
    • Permissions-Policy: 控制浏览器特性的使用权限。

8. 常见问题与故障排除

  • Nginx 无法启动/加载配置失败: 运行 nginx -t 查看具体错误信息和行号。常见原因:配置文件语法错误、证书/私钥文件路径错误、私钥文件权限不正确 (应为 root 或 Nginx 用户可读,通常 600)、端口已被占用。
  • 浏览器显示证书错误:
    • 无效/过期: 证书已过有效期,需要续期或更换。
    • 名称不匹配 (NET::ERR_CERT_COMMON_NAME_INVALID): 访问的域名不在证书的 CN 或 SAN 列表中。确保 server_name 指令中的域名与证书包含的域名一致。
    • 颁发机构不可信 (NET::ERR_CERT_AUTHORITY_INVALID): 证书链不完整或 CA 不受信任。确保 ssl_certificate 文件包含了完整的证书链(服务器证书 + 中间证书)。对于自签名证书,此错误是正常的。
  • 混合内容 (Mixed Content) 警告: HTTPS 页面加载了通过 HTTP 加载的资源(如图片、脚本、样式表)。需要修改网站代码,将所有资源链接改为 HTTPS 或使用相对协议链接 (//example.com/resource.jpg)。
  • SSL 握手失败 (SSL Handshake Failed): 原因多样。可能是客户端/服务器协议或加密套件不兼容(检查 ssl_protocolsssl_ciphers 配置)、证书或私钥问题、防火墙阻止了 443 端口通信。查看 Nginx 错误日志 (/var/log/nginx/error.log) 获取更多线索。
  • OCSP Stapling 无法工作: 检查 ssl_stapling, ssl_stapling_verify, ssl_trusted_certificate, resolver 配置是否正确。确保 Nginx 服务器可以访问外部网络以查询 OCSP 服务器。使用 SSL Labs 测试可以验证 OCSP Stapling 状态。
  • HSTS 配置问题: 首次配置 HSTS 时使用了过长的 max-agepreload,导致网站出现问题后难以恢复。务必从小 max-age 开始测试。如果误加 preload,需要从预加载列表中移除(过程可能较长)。

9. 总结

为 Nginx 配置 HTTPS 是构建安全、可信赖网站的关键一步。本教程详细介绍了从理解 HTTPS 和 SSL/TLS 证书基础,到获取证书(特别是使用免费的 Let’s Encrypt),再到 Nginx 的核心配置指令 (listen, ssl_certificate, ssl_certificate_key, ssl_protocols, ssl_ciphers 等),以及 HSTS、OCSP Stapling、DH 参数等安全增强措施,最后还涵盖了自动续期、性能优化和故障排除等方面。

配置 HTTPS 可能初看起来有些复杂,但遵循本教程的步骤,并结合 Nginx 官方文档和在线工具 (如 SSL Labs) 进行验证和调整,您完全可以为您的网站成功部署强大而安全的 HTTPS。记住,网络安全是一个持续的过程,定期检查配置、更新软件、关注新的安全建议至关重要。希望本教程能为您在 Nginx 上实现 HTTPS 提供坚实的基础和全面的指导。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部