nginx可通过sni在四层实现https流量分流,无需解密tls,依赖≥1.19.4版本、openssl≥1.1.1及启用stream_ssl_preread模块,在stream块中用map匹配$ssl_preread_server_name路由。

确认环境支持 SNI 预读能力
这是前提,缺一不可:
- Nginx 版本 ≥ 1.19.4(官方主线版默认内置
ngx_stream_ssl_preread_module) - OpenSSL 版本 ≥ 1.1.1(SNI 和 ALPN 解析依赖其扩展支持)
- 配置中未禁用 stream 模块及相关 SSL 预读模块
运行以下命令验证模块是否可用:
nginx -V 2>&1 | grep -o with-stream-ssl-preread-module
若无输出,需升级 Nginx 或重编译时添加 --with-stream-ssl-preread-module 参数。
在 stream 块中定义上游与 SNI 映射规则
注意:所有配置必须写在 http 块之外的顶层 stream 块内,不能嵌套在 http 中。
典型结构如下:
stream {
upstream app1_backend {
server 10.0.1.10:443;
}
upstream app2_backend {
server 10.0.1.20:443;
}
map $ssl_preread_server_name $upstream_backend {
hostnames;
app1.example.com app1_backend;
app2.example.com app2_backend;
default app1_backend;
}
server {
listen 443 ssl preread;
ssl_preread on;
proxy_pass $upstream_backend;
proxy_ssl on;
proxy_ssl_protocols TLSv1.2 TLSv1.3;
proxy_ssl_verify off;
proxy_ssl_server_name on;
}
}
说明:
-
listen 443 ssl preread表示监听 443 端口并启用 SSL 预读模式 -
proxy_ssl on启用代理到上游的 TLS 连接(即后端也走 HTTPS) -
proxy_ssl_server_name on把原始 SNI 透传给后端,便于后端识别虚拟主机 -
proxy_ssl_verify off仅用于测试;生产环境应配proxy_ssl_trusted_certificate并开启校验
区分 TLS 终止与 TLS 透传两种模式
根据实际需求选择:
-
TLS 透传(推荐多数场景):Nginx 不提供证书,只读 SNI 并转发加密流。配置中不写
ssl_certificate,ssl_preread on即可 - TLS 终止 + 明文转发:Nginx 自己处理 TLS 握手(需配置证书),再以明文(如 HTTP)发给后端。这属于七层行为,不在 stream 块内实现
-
TLS 终止 + 重加密(mTLS 场景):Nginx 终止客户端 TLS,再用另一套证书向上游发起 TLS 连接,需启用
ngx_stream_ssl_module并配置proxy_ssl_certificate
常见问题与调优建议
遇到转发失败或连接拒绝,优先检查这几项:
- 防火墙是否放行 443 端口入向流量(尤其是云服务器安全组)
- 后端服务是否真实监听对应 IP:PORT 且允许来自 Nginx 的连接
- 客户端是否真正在 ClientHello 中发送了 SNI(老旧客户端或某些扫描工具可能不带)
- resolver 配置缺失导致域名无法解析(如 upstream 使用域名而非 IP,需加
resolver 8.8.8.8 valid=30s;) - 超时参数过短引发中断,可适当加大:
proxy_timeout 3600s、proxy_connect_timeout 15s
这种基于 SNI 的四层分流不复杂但容易忽略细节,关键是把模块、协议版本、配置层级三者对齐。











