本文介绍了基于主机名的 Nginx TCP 转发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

随着 Nginx 社区版 TCP 负载均衡的发布,我想混合 OpenVPN 和 SSL 直通数据.Nginx 知道如何路由流量的唯一方法是通过他们的域名.

With the release of TCP load balancing for the Nginx community version, I would like to mix OpenVPN and SSL pass-through data. The only way for Nginx to know how to route the traffic is via their domain name.

 vpn1.app.com ─┬─► nginx at 10.0.0.1 ─┬─► vpn1  at 10.0.0.3
 vpn2.app.com ─┤                      ├─► vpn2  at 10.0.0.4
https.app.com ─┘                      └─► https at 10.0.0.5

我查看了 TCP 指南模块文档,但似乎没有很好的参考.如果有人能指出我正确的方向,我将不胜感激.

I have taken a look at the TCP guides and the module documentation, but it doesn't seem well referenced. If anyone can point me to the right direction, i'd be grateful.

ServerFault 的相关问题:Can a Reverse Proxy将 SNI 与 SSL 传递一起使用?

Related question on ServerFault: Can a Reverse Proxy use SNI with SSL pass through?

推荐答案

假设

如果我理解正确,您实际上希望 nginx 侦听单个 IP 地址和 TCP 端口组合(例如,listen 10.0.0.1:443),然后,取决于传入的 TCP 流流量,将其路由到 3 个不同的 IP 地址之一.

Assumptions

If I understand you correctly, you effectively want nginx to listen at a single IP address and TCP port combination (e.g., listen 10.0.0.1:443), and then, depending on the characteristic of the incoming TCP stream traffic, route it to one of the 3 different IP addresses.

您没有明确提到您希望它如何区分 3 个不同的涉险域,但我的假设是您认为这只是 TLS,并且必须要使用某种 TLS SNI(服务器名称指示)) 基于领域的差异化机制.

You don't explicitly mention how you expect it to differentiate between the 3 different domains at stake, but my assumption is that you assume it's all just TLS, and must want to employ some sort of a TLS SNI (Server Name Indication) mechanism for domain-based differentiation.

我相信 http://nginx.org/docs/ 提供的流相关文档非常权威和详尽对于相关模块(我在这里列出了所有这些,因为显然还没有交叉引用的中心位置,例如,还没有从流核心"模块到子模块的引用(和 docs/stream/ 只是重定向回 docs/),这确实很令人困惑,因为像 http://nginx.org/r/upstream 仅记录为适用于 http,没有提及适用于 stream,即使指令大致相同最后):

I would believe that the stream-related documentation provided at http://nginx.org/docs/ is quite authoritative and exhaustive for the modules at stake (I'm listing all of it here, since apparently there's no central place for cross-referencing this yet, e.g., no references from the "stream core" module to the submodules yet (and docs/stream/ just redirects back docs/), which is indeed quite confusing, since stuff like http://nginx.org/r/upstream is only documented to apply to http, without any mention of applicability to stream, even if the directives are about the same in the end):

请注意,来自每个模块的每个 nginx 指令都有有限数量的适用 Context.

Note that each nginx directive, from each module, has a limited number of applicable Context's.

因此,不幸的是,这里根本没有窥探 SNI 的指令!

As such, unfortunately, there is simply no directive to snoop into SNI here!

相反,它实际上记录在 stream_core 中,引用,不同的服务器必须侦听不同的地址:端口对.",正如您可能注意到的,这也与 listen 指令在更常见的 http_core 中工作,并且是对以下事实的相当明确的引用目前没有为 stream 中的 listen 实现 SNI 支持.

To the contrary, it's actually documented in stream_core that, to quote, "Different servers must listen on different address:port pairs.", which, as you may note, is also contrary to how the listen directive works within the more-common http_core, and is a rather unambiguous reference to the fact that no kind of SNI support is presently implemented for the listen within stream.

作为讨论点和解决建议,OpenVPN 流量只是具有可监听 SNI 的 TLS 的假设也不一定正确(但我对 OpenSSL 或 SNI 不太熟悉):

As a discussion point and a resolution suggestion, the assumption that OpenVPN traffic is just TLS with the snoopable SNI is also not necessarily correct (but I'm not too familiar with OpenSSL or SNI):

  • 考虑到即使 SNI 在今天是被动监听的,这显然与 TLS 保证连接安全的承诺背道而驰,因此,在未来的 TLS 版本中可能会发生变化.

  • Consider that even if SNI is passively snoopable today, that's clearly contrary to the promise of TLS of keeping the connection secure, and, as such, may change in a future version of TLS.

为了讨论起见,如果 OpenVPN 仅使用 TLS 连接,并且如果它使用 TLS 来验证具有用户证书的用户(哪个会使对流进行 MitM 变得更加困难,但仍然始终携带身份验证数据),那么,理论上,如果 nginx 确实在 listen 中支持 SNI 支持listen代码>流,那么您可能已经能够使用 nginx 主动地对它进行 MitM(因为 stream_proxy 中已经支持 >proxy_ssl.

For the sake of discussion, if OpenVPN is just using a TLS connection, and if it is NOT using TLS for authenticating users with user certificates (which would make it much more difficult to MitM the stream, yet still carry the authentication data all along), then, theoretically, if nginx did have SNI support around the listen within stream, then you'd possibly have been able to actively MitM it with nginx (since proxy_ssl is already supported in stream_proxy).

最重要的是,我相信 OpenVPN 最好通过它自己的基于 UDP 的协议运行,在这种情况下,您可以为一个基于 TCP 的 https 实例和另一个基于 UDP 的实例使用相同的 IP 地址和端口号-基于OpenVPN,没有冲突.

Most importantly, I believe OpenVPN may best be run over its own UDP-based protocol, in which case, you can use the same IP address and port number for one instance of the TCP-based https and another one of the UDP-based OpenVPN without a conflict.

最后,你可能会问,那么流模块有什么用呢?我相信它的目标受众是,(0),基于 IP 的 hash 与多个 upstream 服务器负载平衡 HTTP/2- 客户端的地址,例如,和/或 (1) 一种更直接且与协议无关的替换 stunnel.

In the end, you may ask, what would the stream module be useful for anyways, then? I believe its target audience would be, (0), load balancing HTTP/2 with multiple upstream servers, based on the hash of the IP-address of the client, for example, and/or, (1), a more straightforward and protocol-agnostic replacement for stunnel.

这篇关于基于主机名的 Nginx TCP 转发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 09:45