Nginx无法直接将HTTPS流量转发至不同协议后端,可行方式仅有TLS终止(解密后按HTTP路由)或TLS透传(仅按SNI四层转发),二者分别适用于需处理内容与仅需分发加密流的场景。

不能直接“将 HTTPS 流量转发至不同协议后端”,因为 HTTPS 是加密的 HTTP 协议,Nginx 无法在不解密的前提下识别内容并做协议级路由。真正可行的方式只有两种:TLS 终止(解密后按 HTTP 路由)或 TLS 透传(不解密、仅按 SNI 做四层转发)。选择哪种方式,取决于你是否需要读取/修改请求内容,以及后端支持什么协议。
HTTPS 终止 + 多协议后端转发
这是最常用也最灵活的方式:Nginx 解密客户端 HTTPS 请求,得到明文 HTTP 请求,再根据路径、Host、Header 等条件,将请求以 HTTP 或其他协议(如 WebSocket、gRPC)转发给不同后端。
- 必须配置 ssl_certificate 和 ssl_certificate_key,启用 HTTPS 监听
- 用 location 块区分路径,例如
/api/→ HTTP 后端,/ws/→ WebSocket 后端,/grpc/→ gRPC 后端(需启用http_v2和grpc_pass) - 转发 HTTP 后端时,推荐开启
keepalive连接池,减少后端建连开销 - 转发 WebSocket 时,务必设置:
proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade"
TLS 透传(SNI 路由)+ 原协议后端
适用于后端自己处理 TLS,且你只负责四层分发。此时 Nginx 不解密、不干预应用层,只是根据 Client Hello 中的 SNI 字段,把整个加密 TCP 流原样转发到对应后端——后端可以是 HTTPS、MQTT over TLS、自定义 TLS 协议服务等。
- 必须启用 stream 模块(编译需含
--with-stream --with-stream_ssl_preread_module) - 配置中不能出现
http、server_name、location等七层指令 - 依赖
$ssl_preread_server_name变量做域名匹配,例如example.com → 10.0.1.10:443(HTTPS 后端),mqtt.example.com → 10.0.1.20:8883(MQTT over TLS 后端) - 老旧客户端若不发 SNI,会走 default 分支,需提前评估兼容性
混合场景:部分终止、部分透传
一个 Nginx 实例可同时运行 http 和 stream 上下文,实现“HTTPS 终止”与“TLS 透传”共存。例如:443 端口上,Web 流量走 HTTP 层终止并路由,IoT 设备的 TLS 连接走 stream 层透传。
- http 块处理常规 Web 请求(带 SSL 配置、proxy_pass 到 HTTP/HTTPS/gRPC 后端)
- stream 块单独监听 443(或另开端口如 4443),专用于 SNI 分流
- 注意端口冲突:两个 server 块不能同时
listen 443 ssl和listen 443;建议透传走独立端口,或用ssl_preread on+ 条件判断(高级用法需结合 map 与 if,但 stream 中 if 支持有限)
常见误区提醒
所谓“把 HTTPS 流量直接转成 HTTP 或 WebSocket”是误解——HTTPS 流量本质是加密 TCP 流,不是“带协议标识的数据包”。Nginx 要么解密(变成 HTTP),要么透传(仍是加密流),不存在中间态。
- proxy_pass https://... 是 Nginx 主动作为 HTTPS 客户端连接后端,与“转发客户端 HTTPS”无关
- 试图用 rewrite 或 header 修改来切换协议,对加密流量无效——HTTP 层都不可见
- 后端若为非 HTTP 协议(如 SMTPS、FTPS),必须用 stream 模块 + TLS 透传,http 模块完全不适用


















