Nginx 实现 HTTPS→HTTPS 反向代理需对外终止 TLS、对内启用证书校验并透传 X-Forwarded-Proto 等头信息,确保端到端加密与协议一致性。

在 Nginx 中实现 HTTPS 到后端的反向代理(即 HTTPS → Nginx → HTTPS 后端),关键在于两层 TLS 的协同处理:对外终止 HTTPS,对内建立可信 HTTPS 连接。配置不当容易导致证书校验失败、协议识别错误或重定向降级等问题。
明确代理模式:HTTPS to HTTPS
这不是简单的“Nginx 解密再发 HTTP”,而是保持端到端加密:客户端用 HTTPS 访问 Nginx,Nginx 再以 HTTPS 协议主动连接后端服务(如 https://10.0.2.5:8443)。这种模式适用于安全合规场景,比如对接云原生 API、Spring Boot + HTTPS 的微服务、或跨机房加密调用。
- 必须确认后端服务已启用 HTTPS 并提供有效证书(自签名或私有 CA 签发均可)
- Nginx 不会自动信任后端证书——需显式开启校验并指定可信 CA 根证书
- 不能省略 X-Forwarded-Proto $scheme,否则后端可能误判为 HTTP 请求
核心配置项:证书校验与头信息传递
对内 HTTPS 代理不是加个 https:// 前缀就完事,必须补全安全链路参数:
-
开启上游证书验证:
proxy_ssl_verify on; -
指定可信 CA 文件:
proxy_ssl_trusted_certificate /etc/nginx/ssl/upstream-ca.crt;(该文件应包含后端服务所用 CA 的公钥) -
匹配后端证书主机名:
proxy_ssl_name "api.internal.com";(与后端证书的 CN 或 SAN 一致) -
强制传递协议标识:
proxy_set_header X-Forwarded-Proto $scheme; -
保留原始 Host 和客户端 IP:
proxy_set_header Host $host;和proxy_set_header X-Real-IP $remote_addr;
避免常见陷阱:路径与重定向问题
当后端返回 302 重定向时,若未正确设置头信息,可能生成 http:// 地址导致混合内容报错或跳转失败:
- 确保后端应用(如 Spring Boot、Tomcat)已配置信任
X-Forwarded-Proto头,并据此生成重定向 Location - Nginx 层可加
proxy_redirect http:// https://;强制改写响应头中的重定向地址(仅限简单场景,推荐优先由后端处理) - 不要遗漏
proxy_set_header X-Forwarded-Port $server_port;,尤其当 Nginx 使用非标准 HTTPS 端口时
完整可用示例(/etc/nginx/conf.d/secure-api.conf)
以下是最小可行配置,已整合证书、校验、头传递与超时优化:
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass https://10.0.2.5:8443/;
proxy_ssl_verify on;
proxy_ssl_trusted_certificate /etc/nginx/ssl/internal-ca.crt;
proxy_ssl_name "api.internal.com";
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_set_header X-Forwarded-Port $server_port;
proxy_connect_timeout 60s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
}
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}


















