如何让 SSL 更好地处理 non-ssl 协议数据

How to get SSL to play nice with non-ssl protocol data

简短背景:如果我们回到 2006 年左右:我们(即:我的公司)使用 java 客户端应用 嵌入在浏览器中 通过端口 443 连接到 in-house 服务器上端口 8068 上的 C 程序后端 运行。在首次开发 java 应用程序时,端口 443 是我们知道不会被使用该软件的客户阻止的唯一端口(易于安装,可能客户 in-house 工作人员没有'有能力或知识来控制他们的内部防火墙)。

Fast-forward 到 2016 年,我受雇帮助开发 Java 应用程序的 NodeJS/Javascript 版本。 Java 应用程序在其替代开发过程中继续使用,但是糟糕 - 我们了解到浏览器将在不久的将来放弃对嵌入式 Java 的支持。所以我们切换到 Java Web Start,这样客户就可以继续下载应用程序,它仍然通过端口 443->8068 路由连接到内部服务器。

2017 年过去了,你不知道吗,我们不能同时使用 up-coming JS web-app 和 HTTPS/SSL 以及 Java 应用程序, 因为他们使用相同的端口。 "Ok let's use NGINX to solve the problem." 但由于内部政治、客户需求和 turn-over 的 web-developer 员工,我们从来没有抽出时间真正做到这一点。

所以我们到了 2020 年,准备部署新的 Web 版本的客户端软件,整个 443 烂摊子再次出现。

基本上我希望允许(暂时)Java 应用程序继续使用 443,但现在也需要让网络应用程序也使用 HTTPS。早在 2017/2018 年,我们就在谷歌上搜索了让它们通过 NGINX 共存的方法,但我们从未真正让它们正常工作,或者示例和教程不完整或令人困惑。似乎我们需要按照 https://www.nginx.com/blog/running-non-ssl-protocols-over-ssl-port-nginx-1-15-2/ 的方式使用流式传输,或者查看传入的 HTTPS header 并在 NGINX 配置文件中进行“if (https) { route to nodeJS server } else { assume it must be the java app and route to port 8068 }”排序。

过去的 Google 搜索链接似乎不再存在,所以如果有人知道允许 HTTPS 网站切换到仍然需要使用 443 的 non-SSL 应用程序的 NGINX 配置,我将不胜感激.任何为我们指明正确方向的文档 and/or 教程也会有所帮助。提前致谢!

您可以使用 ssl_preread 选项执行此操作。基本上,此选项将允许访问包含在 SSL 端口协商的协议的变量 $ssl_preread_protocol。如果未检测到有效协议,则变量将为空。

使用此参数,您可以对您的环境使用以下配置:

stream {
    upstream java {
        server __your_java_server_ip__:8068;
    }

    upstream nodejs {
        server __your_node_js_server_ip__:443;
    }

    map $ssl_preread_protocol $upstream {
        default java;
        "TLSv1.2" nodejs;
    }

    server {
        listen 443;

        proxy_pass $upstream;
        ssl_preread on;
    }
}

在您的情况下,此配置会将连接直接传递给您的 nodejs 和 java 后端服务器,因此,nodejs 将需要协商 SSL。您可以使用另一个服务器上下文将此工作传递给 NGiNX,例如:

stream {
    upstream java {
        server __your_java_server_ip__:8068;
    }

    upstream nodejs {
        server 127.0.0.1:444;
    }

    map $ssl_preread_protocol $upstream {
        default java;
        "TLSv1.2" nodejs;
    }

    server {
        listen 443;

        proxy_pass $upstream;
        ssl_preread on;
    }
}

http {
    server {
        listen 444 ssl;
        __your_ssl_cert_configurations_here__

        location / {
            proxy_pass http://__your_nodejs_server_ip__:80;
        }
    }
}

您至少需要 NGiNX 版本 1.15.2 才能使用此配置,并使用 ngx_stream_ssl_preread_module 模块编译(需要使用 --with-stream_ssl_preread_module 配置参数,因为这个模块默认没有构建).

来源:https://www.nginx.com/blog/running-non-ssl-protocols-over-ssl-port-nginx-1-15-2/