「Nginx」- 转发 SSL 流量、SSL 直通、根据域名进行 SSL 转发

  CREATED BY JENKINSBOT

问题描述

在现代 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