问题描述
在现代 Web 环境中,Nginx 通过作为前端服务出现并监听 HTTPS 请求,而后端应用程序作为独立的服务并提供 HTTP 访问。我们通过 proxy_pass 完成流量转发。
但是,如果后端也监听 HTTPS 请求,虽然能够通过 proxy_pass 完成,但是却要管理两套证书。因此,我们希望能够将 HTTP 流量直传到后端服务,这样仅管理后端证书即可。
该笔记将记录:在 Nginx 中,如何直接转发 SSL 流量,以及相关问题的处理方法。
解决方案
stream { upstream vpn1_backend { server 10.0.0.3:443; } upstream vpn2_backend { server 10.0.0.4:443; } upstream https_default_backend { server 127.0.0.1:443; } map $ssl_preread_server_name $name { vpn1.app.com vpn1_backend; vpn2.app.com vpn2_backend; https.app.com https_backend; default https_default_backend; } server { listen 10.0.0.1:443; proxy_pass $name; ssl_preread on; } }
1)通过 upstream 指令,我们定义后端服务器;
2)通过 ssl_preread 模块,将提取 SSL ClientHello 信息。比如 SNI 字段,并注入 $ssl_preread_server_name 字段;
3)通过 map 指令,根据 $ssl_preread_server_name 的值定义 $name 变量的值;
4)最后,在 proxy_pass 中,使用动态的 $name 变量来选择不同的 upstream 服务器;
已知问题
该方案将遗失客户端的真实 IP 地址,需要进一步配置才能解决问题。
参考文献
Module ngx_stream_map_module
Nginx TCP forwarding based on hostname – Stack Overflow
SSL Pass-Through in Nginx Reverse proxy? – Stack Overflow
Module ngx_stream_ssl_preread_module