nginx https流量分发需区分四层(sni透传)与七层(tls终止):四层基于stream模块和ssl_preread,不解密、不验证书,仅按sni域名转发至后端https服务;七层在http块中配置server监听443 ssl,统一终止tls、解析http头/路径/cookie,支持重写、灰度、waf等高级功能。

要在分布式架构中用 Nginx 做 HTTPS 流量分发,关键不是“把 HTTPS 解开再转发”,而是分清两个层级:HTTP 层(七层)做内容感知路由,TCP 层(四层)靠 SNI 做无解密分流。选哪种,取决于你是否需要 inspect HTTP 头、路径、Cookie 等信息。
基于 SNI 的四层 HTTPS 分流(不终止 TLS)
适用于多个 HTTPS 服务共用 443 端口、后端各自持有证书、无需 Nginx 解密的场景,比如多个独立 SaaS 应用或微服务网关前的统一入口。
- 确认 Nginx ≥ 1.19.4,OpenSSL ≥ 1.1.1,并启用
stream_ssl_preread_module(运行nginx -V | grep stream-ssl-preread验证) - 所有配置写在顶层
stream { ... }块内,不能放在http里 - 用
map $ssl_preread_server_name $upstream_backend匹配域名,例如:app1.example.com app1_backend;app2.example.com app2_backend; -
server块监听443 ssl preread,开启ssl_preread on,并设置proxy_ssl on透传加密连接 - 后端服务器必须支持 TLS,并自行处理证书;Nginx 不参与证书验证与加解密
基于 server_name 的七层 HTTPS 反向代理(终止 TLS)
适用于需统一管理证书、做路径重写、请求头注入、灰度发布或 WAF 防护的场景,比如企业中台或 API 网关。
- 每个
server块监听443 ssl,绑定独立域名:server_name api.example.com;ssl_certificate /path/to/api.crt;ssl_certificate_key /path/to/api.key; - 后端可走 HTTP 或 HTTPS:
proxy_pass https://backend_app1;(推荐 HTTPS 后段)proxy_set_header X-Forwarded-Proto $scheme;保留协议信息 - 建议启用 TLS 1.3、OCSP Stapling 和会话缓存:
ssl_protocols TLSv1.3;ssl_stapling on; ssl_trusted_certificate /path/to/fullchain.pem;ssl_session_cache shared:SSL:10m; - 若多域名共用同一证书(如通配符),可复用同一份证书文件,减少磁盘与加载开销
结合负载均衡提升分布式弹性
无论四层还是七层,后端通常不止一台机器,需配合 upstream 实现高可用分发。
- 定义带健康检查的上游组:
upstream app1_cluster {<br> server 10.0.2.10:443 max_fails=2 fail_timeout=15s;<br> server 10.0.2.11:443 max_fails=2 fail_timeout=15s;<br> keepalive 32;<br>} - 选择合适算法:
轮询(默认)、加权轮询(适配异构节点)、least_conn(适合长连接)、ip_hash(需会话保持) - 对 HTTPS 后端,加上
proxy_ssl_*参数确保 TLS 连接安全透传:proxy_ssl_verify off;(若后端证书为自签或内网 CA)proxy_ssl_trusted_certificate /etc/nginx/ssl/internal-ca.pem; - 避免 SSL 握手成为瓶颈:启用
ssl_session_reuse和合理设置ssl_buffer_size
自动化与运维友好实践
在动态扩缩容的分布式环境中,静态配置易失效,需增强可维护性。
- 用 Certbot + Nginx 插件实现 Let’s Encrypt 证书自动申请与续期,配合
location /.well-known/acme-challenge透传验证请求 - 将各域名配置拆分为独立文件,放入
/etc/nginx/conf.d/sites-enabled/并include,便于 CI/CD 管理 - 对灰度流量,用
split_clients或map+ 请求头/参数做条件路由,例如:map $arg_version $backend { "" default; "v2" v2_backend; } - 添加基础防护:用
limit_req控制突发流量,配合geo模块限制高风险区域请求频次











