问题描述
在现代 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