Nginx 配置 HTTPS 全指南:每个参数逐一详解

1. 引言

随着网络安全意识的提升,HTTPS 已成为网站部署的标配。HTTPS 不仅能够加密客户端与服务器之间的数据传输,防止中间人攻击,还能提升搜索引擎排名和用户信任度。Nginx 作为高性能的 Web 服务器和反向代理服务器,配置 HTTPS 是其核心功能之一。

本文将带你从零开始,在 Nginx 中配置 HTTPS,并对配置文件中的每一个参数进行详细解读,帮助你不仅会配置,更理解每一行配置背后的含义。

2. 准备工作

在开始配置之前,需要做好以下准备:

  • 一台已安装 Nginx 的服务器(本文以 Ubuntu/Debian 系统为例,其他系统命令略有差异)。
  • 一个已解析到该服务器的域名。
  • 一份 SSL 证书及私钥文件。你可以从证书颁发机构(CA)购买,也可以使用 Let's Encrypt 免费获取。

2.1 检查 Nginx 是否安装

bash 复制代码
nginx -v

如果未安装,可使用以下命令安装:

bash 复制代码
sudo apt update
sudo apt install nginx -y

2.2 获取 SSL 证书

以 Let's Encrypt 为例,使用 Certbot 工具可以快速获取免费证书:

bash 复制代码
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com

Certbot 会自动修改 Nginx 配置并启用 HTTPS。但为了深入理解配置,本文将手动编写配置。

3. 基础 HTTPS 配置

首先,我们来看一个最基础的 HTTPS 配置示例:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

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

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

3.1 listen 443 ssl

nginx 复制代码
listen 443 ssl;

参数解读:

  • listen:指定 Nginx 监听的端口和协议。
  • 443:HTTPS 的默认端口。
  • ssl:告诉 Nginx 在该端口上启用 SSL/TLS 加密。这是启用 HTTPS 的关键参数。

注意 :在较新版本的 Nginx 中,ssl 参数可以省略,因为 listen 443 默认会启用 SSL。但为了兼容性和明确性,建议保留。

3.2 server_name

nginx 复制代码
server_name example.com www.example.com;

参数解读:

  • server_name:指定该虚拟主机匹配的域名。
  • 可以配置多个域名,用空格分隔。
  • 当客户端请求的 Host 头与这里的域名匹配时,Nginx 会使用该 server 块处理请求。

3.3 ssl_certificate

nginx 复制代码
ssl_certificate /etc/nginx/ssl/example.com.crt;

参数解读:

  • ssl_certificate:指定 SSL 证书文件的路径。
  • 证书文件通常以 .crt、.pem 或 .cer 为扩展名。
  • 该文件包含服务器的公钥证书,由 CA 签发。
  • 如果证书链中包含中间证书,需要将服务器证书和中间证书合并到同一个文件中。

3.4 ssl_certificate_key

3.5 多域名与通配符证书

在实际部署中,一个站点往往需要同时服务多个域名,或者为某个主域名下的所有子域名提供 HTTPS。这时就需要用到多域名证书或通配符证书。

3.5.1 同一 server 块配置多个域名共用一张证书

如果一张证书的 SAN(Subject Alternative Name,主题备用名称)字段中包含了多个域名,那么可以在同一个 server 块中配置这些域名,共用这一张证书:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com www.example.com blog.example.com;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

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

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

参数解读:

  • server_name:这里列出了三个域名,用空格分隔。只要请求的 Host 头匹配其中任意一个,Nginx 就会使用该 server 块处理请求。
  • ssl_certificate / ssl_certificate_key:指向同一张证书和对应的私钥。这张证书必须同时覆盖上面列出的所有域名,否则浏览器会提示证书不匹配。

适用场景 :当几个域名指向同一个站点、且证书已包含这些域名时使用。例如公司官网同时使用 example.com 和 www.example.com,或主站与博客共用一张多域名证书。

3.5.2 使用通配符证书(*.example.com)

通配符证书可以覆盖某个主域名下的所有一级子域名,例如 *.example.com 可以匹配 www.example.com、blog.example.com、api.example.com 等,但不匹配 example.com 本身。

nginx 复制代码
server {
    listen 443 ssl;
    server_name *.example.com;

    ssl_certificate /etc/nginx/ssl/wildcard.example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/wildcard.example.com.key;

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

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

参数解读:

  • server_name *.example.com:使用通配符匹配所有一级子域名。
  • ssl_certificate / ssl_certificate_key:指向通配符证书及其私钥。通配符证书的 CN 或 SAN 字段为 *.example.com。

注意 :通配符证书只匹配一级子域名,a.b.example.com 这类多级子域名无法被 *.example.com 覆盖,需要单独配置或使用多域名证书。
适用场景 :当子域名数量较多、且未来可能动态新增子域名时使用。例如 SaaS 平台为每个客户分配独立的 customer.example.com,使用通配符证书可以避免频繁申请新证书。

nginx 复制代码
ssl_certificate_key /etc/nginx/ssl/example.com.key;

参数解读:

  • ssl_certificate_key:指定 SSL 私钥文件的路径。
  • 私钥文件通常以 .key 为扩展名。
  • 私钥必须保密,不能泄露给任何人。
  • 私钥与证书必须匹配,否则 Nginx 启动时会报错。

安全提示 :私钥文件的权限应设置为仅 root 可读,例如 chmod 600 example.com.key。

4. 增强 HTTPS 安全性的配置

基础配置已经可以启用 HTTPS,但为了提升安全性,还需要进行以下优化。

4.1 HTTP 自动跳转 HTTPS

为了让用户访问 HTTP 时自动跳转到 HTTPS,可以添加一个额外的 server 块:

nginx 复制代码
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

参数解读:

  • listen 80:监听 HTTP 默认端口。
  • return 301:返回 301 永久重定向状态码。
  • https://$host$request_uri:重定向目标地址。$host 是请求的域名,$request_uri 是请求的 URI。

说明:使用 301 永久重定向有利于 SEO,搜索引擎会将权重转移到 HTTPS 页面。

4.2 配置 HTTP/2

HTTP/2 可以显著提升页面加载速度,Nginx 1.9.5 及以上版本支持:

nginx 复制代码
listen 443 ssl http2;

参数解读:

  • http2:启用 HTTP/2 协议。
  • HTTP/2 支持多路复用、头部压缩等特性,能减少延迟、提升性能。
  • 注意:HTTP/2 需要 SSL/TLS 支持,因此必须与 ssl 同时使用。

4.3 配置 TLS 协议版本

nginx 复制代码
ssl_protocols TLSv1.2 TLSv1.3;

参数解读:

  • ssl_protocols:指定允许使用的 TLS 协议版本。
  • TLSv1.2:目前广泛支持的版本,安全性较高。
  • TLSv1.3:最新版本,安全性最高,性能更好。
  • 建议禁用 SSLv3、TLSv1.0 和 TLSv1.1,这些旧版本存在已知安全漏洞。

4.4 配置加密套件

nginx 复制代码
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_ciphers:指定允许的加密套件列表,用冒号分隔。
  • 加密套件决定了密钥交换、认证、加密和消息认证的方式。
  • 上述配置优先使用 ECDHE 密钥交换(支持前向保密)和 AES-GCM 加密算法(高效且安全)。
  • 建议使用 Mozilla 推荐的加密套件配置。

4.5 配置 SSL 会话缓存

nginx 复制代码
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

参数解读:

  • ssl_session_cache:配置 SSL 会话缓存。shared:SSL:10m 表示在共享内存中分配 10MB 缓存,大约可以存储 40000 个会话。
  • ssl_session_timeout:会话超时时间,超过该时间后会话失效,需要重新握手。
  • 启用会话缓存可以减少重复握手的开销,提升性能。

4.6 配置 OCSP Stapling

nginx 复制代码
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

参数解读:

  • ssl_stapling on:启用 OCSP Stapling。服务器主动向 CA 查询证书状态并缓存,在 TLS 握手时直接返回给客户端,无需客户端再向 CA 查询,提升握手速度。
  • ssl_stapling_verify on:验证 OCSP 响应。
  • resolver:指定 DNS 解析器,用于解析 OCSP 响应服务器的域名。
  • resolver_timeout:DNS 解析超时时间。

4.7 配置 HSTS

nginx 复制代码
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

参数解读:

  • add_header:添加 HTTP 响应头。
  • Strict-Transport-Security:HSTS 头,告诉浏览器只能通过 HTTPS 访问该站点。
  • max-age=31536000:有效期 1 年(单位秒)。
  • includeSubDomains:对子域名同样生效。
  • always:无论响应状态码是什么都添加该头。

注意:启用 HSTS 后,浏览器会强制使用 HTTPS,如果证书配置有误,用户将无法访问站点。建议先在测试环境验证。

4.8 配置 TLS 会话票据

4.9 HTTPS 反向代理配置

Nginx 最常见的用途之一就是作为反向代理:对外提供 HTTPS 加密访问,对内将请求转发给后端的 HTTP 服务(如 Tomcat、Node.js、Gunicorn 等)。这样既能让后端服务专注于业务逻辑,又能在入口统一处理 TLS 加密、负载均衡和安全策略。

nginx 复制代码
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # 证书配置
    ssl_certificate /etc/nginx/ssl/example.com.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: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_prefer_server_ciphers on;

    # 反向代理配置
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

参数解读:

  • proxy_pass:指定后端服务的地址。这里将请求转发到本机的 8080 端口,即后端 HTTP 服务监听的端口。
  • proxy_set_header Host $host:将客户端请求的 Host 头原样传递给后端,保证后端能正确识别域名。
  • proxy_set_header X-Real-IP $remote_addr:传递客户端的真实 IP 地址。由于 Nginx 转发后,后端看到的连接来源是 Nginx 本身,需要该头才能获取真实客户端 IP。
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for:追加客户端 IP 到转发链中,常用于日志记录和访问控制。
  • proxy_set_header X-Forwarded-Proto $scheme:告诉后端原始请求使用的协议(http 或 https)。$scheme 变量在 HTTPS 请求中取值为 https。

说明 :X-Forwarded-Proto 是解决后端重定向协议丢失问题的关键。如果缺少该头,后端在生成重定向 URL 时(例如登录成功后跳转)会误以为原始请求是 HTTP,从而生成 http:// 开头的地址,导致用户被重定向到非加密页面,甚至出现「重定向次数过多」的错误。

4.9.1 后端重定向协议丢失的解决方案

当后端服务需要根据请求协议生成绝对 URL 时(如 Spring Boot 的 RedirectView、Django 的 HttpResponseRedirect),必须让后端感知到原始请求是 HTTPS。除了设置 X-Forwarded-Proto 头,部分框架还需要额外配置:

nginx 复制代码
# 对于需要识别 X-Forwarded-Proto 的框架(如 Django、Spring Boot)
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;

参数解读:

  • X-Forwarded-Proto $scheme:声明原始请求协议为 HTTPS,后端据此生成 https:// 开头的重定向地址。
  • X-Forwarded-Port $server_port:传递 Nginx 监听的端口(443),供后端生成包含正确端口的 URL。

注意 :部分框架默认不信任代理设置的 X-Forwarded-* 头,需要显式开启。例如 Django 需在 settings.py 中配置 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https'),Spring Boot 需设置 server.forward-headers-strategy=framework。否则后端仍会忽略该头,重定向协议问题依旧存在。

nginx 复制代码
ssl_session_tickets on;

参数解读:

  • ssl_session_tickets:启用 TLS 会话票据(Session Tickets)。
  • 与会话缓存不同,会话票据由服务器加密后发给客户端,客户端在后续连接中携带票据即可恢复会话,无需服务器存储会话状态。
  • 适用于多台服务器负载均衡的场景。

5. 完整的安全配置示例

将以上配置整合,得到一个完整的 HTTPS 配置示例:

nginx 复制代码
# HTTP 跳转 HTTPS
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

# HTTPS 主配置
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # 证书配置
    ssl_certificate /etc/nginx/ssl/example.com.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: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_prefer_server_ciphers on;

    # 会话缓存与票据
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets on;

    # 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;

    # 站点根目录
    root /var/www/html;
    index index.html;

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

5.1 ssl_prefer_server_ciphers

nginx 复制代码
ssl_prefer_server_ciphers on;

参数解读:

  • ssl_prefer_server_ciphers:当客户端支持多种加密套件时,是否优先使用服务器端配置的加密套件顺序。
  • 设置为 on 可以确保优先使用服务器端更安全的加密套件。

6. 验证配置并重启 Nginx

配置完成后,需要验证配置文件的正确性并重启 Nginx:

bash 复制代码
# 验证配置
sudo nginx -t

# 重启 Nginx
sudo systemctl restart nginx

如果配置正确,nginx -t 会输出:

复制代码
nginx: configuration file /etc/nginx/nginx.conf test is successful

7. 常见问题排查

7.1 证书不匹配

如果证书与私钥不匹配,Nginx 启动时会报错。可以使用以下命令验证:

bash 复制代码
# 查看证书信息
openssl x509 -in /etc/nginx/ssl/example.com.crt -noout -modulus | openssl md5

# 查看私钥信息
openssl rsa -in /etc/nginx/ssl/example.com.key -noout -modulus | openssl md5

两个命令输出的 MD5 值应一致。

7.2 证书链不完整

如果浏览器提示证书链不完整,需要将服务器证书和中间证书合并:

bash 复制代码
cat example.com.crt intermediate.crt > combined.crt

然后将 ssl_certificate 指向合并后的文件。

7.3 端口被占用

如果 443 端口被其他程序占用,可以使用以下命令查看:

bash 复制代码
sudo netstat -tlnp | grep 443

8. 总结

本文详细介绍了 Nginx 配置 HTTPS 的完整流程,并对每个参数进行了深入解读。从基础的 listen 443 ssl、ssl_certificate、ssl_certificate_key,到安全增强的 ssl_protocols、ssl_ciphers、HSTS、OCSP Stapling 等,每一个参数都有其特定的作用。

配置 HTTPS 不仅仅是启用加密,更重要的是通过合理的参数配置,在安全性、性能和兼容性之间找到最佳平衡。希望本文能帮助你深入理解 Nginx HTTPS 配置的每一个细节,在实际部署中游刃有余。

相关推荐
螺蛳粉 螺蛳粉8 小时前
第一篇:Keepalived 高可用实战:VIP 漂移与 Nginx 主备切换完整指南
运维·nginx·负载均衡·keepalived·高可用
荣合技术服务8 小时前
VMware ESXi 虚拟化平台服务器虚拟机数据恢复服务
linux·运维·服务器
爱吃香菜的初学者8 小时前
十三.Linux——信号量
linux·运维·服务器·开发语言
吴声子夜歌9 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(三)
运维·nginx·kubernetes
小小龙学IT9 小时前
ROS2 安装完全指南(Ubuntu 版):从零开始到跑通第一个节点本文
linux·运维·ubuntu
Ruiery9 小时前
Linux 6.6内核 CPU 深度解析(十二):SMT 进阶 — core scheduling 与共享算力的负载平衡
linux·运维·服务器
2401_872418789 小时前
Windows服务器:错误 403 - 禁止访问:本地 FTP 上传文件到网站服务器后提示无访问权限
运维·服务器·windows
吴声子夜歌10 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(二)
运维·nginx·kubernetes
Ruiery18 小时前
Linux 6.6内核 CPU 深度解析(七):调度器启动 — 从单核到多核,调度器分阶段点亮
linux·运维·服务器
50万马克的面包18 小时前
CSDN-栈队列数组-知识点整理
linux·运维·服务器