Jam*_*ica 45 tcp load-balancing virtualhost nginx stream
随着Nginx社区版本的TCP负载平衡的发布,我想混合使用OpenVPN和SSL传递数据.Nginx知道如何路由流量的唯一方法是通过他们的域名.
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
Run Code Online (Sandbox Code Playgroud)
我已经看过TCP指南和模块文档,但它似乎没有被很好地引用.如果有人能指出我正确的方向,我将不胜感激.
关于ServerFault的相关问题:反向代理可以使用带SSL的SNI通过吗?
小智 62
这是现在可以用另外的ngx_stream_ssl_preread模块在Nginx的1.11.5添加和ngx_stream_map模块中添加1.11.2.
这允许Nginx读取TLS客户端Hello并根据要使用的后端的SNI扩展来决定.
stream {
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;
}
upstream vpn1_backend {
server 10.0.0.3:443;
}
upstream vpn2_backend {
server 10.0.0.4:443;
}
upstream https_backend {
server 10.0.0.5:443;
}
upstream https_default_backend {
server 127.0.0.1:443;
}
server {
listen 10.0.0.1:443;
proxy_pass $name;
ssl_preread on;
}
}
Run Code Online (Sandbox Code Playgroud)
cns*_*nst 21
如果我理解正确,你实际上希望nginx监听单个IP地址和TCP端口组合(例如listen 10.0.0.1:443
),然后根据传入TCP流流量的特性将其路由到3个不同的IP地址之一.
您没有明确提到您希望它如何区分3个不同的域,但我的假设是您认为它只是TLS,并且必须要使用某种TLS SNI(服务器名称指示)机制基于域的区分.
我相信http://nginx.org/docs/上提供的与流相关的文档对于所涉及的模块是非常权威和详尽的(我在这里列出了所有这些,因为显然没有交叉的中心位置 -引用这个,例如,没有从"流核心"模块到子模块的引用(并且docs/stream/
只是重定向回docs/
),这确实很令人困惑,因为像http://nginx.org/r/upstream这样的东西只记录到适用于http
,而不适用于任何提及stream
,即使指令是关于到底是相同的):
请注意,每个模块中的每个nginx指令都具有有限数量的适用指令Context
.
因此,遗憾的是,这里根本没有指示窥探SNI!
相反,它实际上记录在stream_core
引用中," Different servers must listen on different address:port pairs.
",正如您可能注意到的那样,这也违背了该listen
指令在更常见的情况下的工作方式http_core
,并且是一个相当明确的参考指出这一事实. SNI支持目前正在为listen
内部实施stream
.
作为讨论点和解决方案的建议,OpenVPN流量只是具有可窥探SNI的TLS的假设也不一定正确(但我不太熟悉OpenSSL或SNI):
考虑到即使SNI今天被动地窥探,这显然违背了TLS保证连接安全的承诺,因此,可能会在未来版本的TLS中发生变化.
为了讨论的缘故,如果OpenVPN的是只使用一个TLS连接,如果它不使用TLS验证用户的身份用户证书(这将使它更难以MITM流,但仍然承载认证数据都一起)那么,理论上,如果nginx确实在listen
内部有SNI支持stream
,那么你可能已经能够使用nginx主动MitM它(因为proxy_ssl
已经支持stream_proxy
).
最重要的是,我认为OpenVPN可能最好通过自己的基于UDP的协议运行,在这种情况下,您可以使用相同的IP地址和端口号作为基于TCP的https的一个实例和另一个基于UDP的OpenVPN没有冲突.
最后,您可能会问,流模块对于什么有用呢?我相信它的目标受众是,(0),基于客户端的IP地址,负载均衡HTTP/2
多个upstream
服务器hash
,和/或,(1),更直接和协议无关的替代stunnel
.
如@Lochnair所述,您可以使用ngx_stream_map模块和$ server_addr变量来解决此问题。这是我的例子。
我的主机IP是192.168.168.22
,我使用keepalived绑定2虚拟IP来eth0
。
$sudo ip a
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 5c:f3:fc:b9:f0:84 brd ff:ff:ff:ff:ff:ff
inet 192.168.168.22/24 brd 192.168.168.255 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.168.238/32 scope global eth0
valid_lft forever preferred_lft forever
inet 192.168.168.239/32 scope global eth0
valid_lft forever preferred_lft forever
$nginx -v
nginx version: nginx/1.13.2
$cat /etc/nginx/nginx.conf
...
stream {
upstream pod53{
server 10.1.5.3:3306;
}
upstream pod54{
server 10.1.5.4:3306;
}
map $server_addr $x {
192.168.168.238 pod53;
192.168.168.239 pod54;
}
server {
listen 3306;
proxy_pass $x;
}
}
Run Code Online (Sandbox Code Playgroud)
因此,我可以通过不同的VIP使用相同的端口3306访问不同的MySQL服务。就像通过diffrent使用同一端口访问不同的HTTP服务一样server_name
。
192.168.168.238 -> 10.1.5.3
192.168.168.239 -> 10.1.5.4
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
39871 次 |
最近记录: |