HTTPS终结应在接入层(最外层)完成,Nginx在此监听443端口、加载证书、解密TLS后以HTTP转发至中间层,并透传X-Forwarded-Proto等关键头,中间层及后端均走内部HTTP通信,避免重复加解密。

在多级代理架构中配置 Nginx 实现 HTTPS 终结,关键不是“在哪一层加证书”,而是明确哪一层承担 TLS 解密职责,并确保上下游协议与头信息正确传递。通常,HTTPS 终结应落在最外层(接入层),后续层级统一走 HTTP 或内部可信网络通信,既保障安全又避免重复加解密开销。
第一层:接入层必须终结 HTTPS
这是整个链路的安全边界。Nginx 在此层监听 443 端口,加载有效证书,完成 TLS 握手后将明文请求转发给中间层:
- 配置 listen 443 ssl http2,启用 HTTP/2 提升性能
- 指定证书路径:ssl_certificate 和 ssl_certificate_key
- 必须设置 proxy_set_header X-Forwarded-Proto $scheme,让下游知道原始是 HTTPS
- 转发目标用 proxy_pass http://middle-tier-cluster(注意是 http://,不是 https://)
- 建议开启 ssl_session_cache shared:SSL:10m 复用会话,降低 TLS 开销
中间层与后端层保持 HTTP 内部通信
中间层(如服务发现网关)和后端层(如应用网关)默认不处理 TLS,只信任来自接入层的流量:
- 所有 proxy_pass 指向都使用 http:// 协议,避免二次加密
- 保留并透传关键头:X-Forwarded-For、X-Real-IP、X-Forwarded-Proto
- 若中间层需根据协议做策略(如重定向 HTTP 请求),依赖 $http_x_forwarded_proto 而非 $scheme
- 后端应用通过解析 X-Forwarded-Proto 判断是否应生成 HTTPS 链接,避免混合内容问题
跨层一致性校验不可少
多级代理容易因头信息丢失或误配导致跳转错乱、资源加载失败:
- 接入层要显式设置 proxy_set_header Host $host,防止后端收到 IP 或默认 server_name
- 中间层若做灰度路由,应基于 X-Forwarded-For 或自定义 header(如 X-Client-Country),而非原始 remote_addr
- 所有层级统一记录 $http_x_forwarded_proto 到 access log,便于排查协议丢失问题
- 禁用中间层和后端层的 ssl_protocols 和 ssl_ciphers 配置——它们不该处理 TLS
特殊场景:仅部分路径强制 HTTPS
如果业务要求某些接口(如 /api/v1/pay)必须 HTTPS,而静态资源可走 HTTP,可在接入层用条件判断:
- 用 if ($request_uri ~ ^/api/) 匹配路径,配合 return 301 https://$host$request_uri
- 更推荐在 server 块中用多个 location 分离逻辑,避免 if + rewrite 的潜在陷阱
- 确保 location /api/ 下的 proxy_pass 仍指向中间层 HTTP 地址,终结动作只发生在 443 监听块内


















