我目前正在家中构建自己的小型集群,并尝试让 SSH 路由(负载平衡)与 HAProxy 配合使用。我已经弄清楚了如何路由 HTTP 流量,但我在 SSH 方面遇到了困难。我对 TCP 协议了解不够多,无法立即知道我必须寻找什么,以便我可以确定如何查询连接,例如主机(不确定它是否在连接的某个地方)或任何可以识别我想要 SSH 进入哪个服务器的东西。
文档反复提到 SSH 流量,所以我可能遗漏了一些东西。我不想使用不同的端口,也不想使用不同的端口来回路由,因为它们可能不是标准的,因此在公共网络上会被屏蔽,或者其他会限制我的东西。
我当前的设置如下:
在我的域(或 IP)上发出请求 -> 路由器 -> 根据端口进行 NAT 转发 -> HAProxy 监听该端口 -> 现在应该识别专用于某个服务器的流量并代理流向它的流量。
编辑:正如Cha0s所澄清的那样,使用SSH(或类似方式)这是不可能的。
如果你对不同的方法感兴趣,Sven 的答案可以很好地帮助你做类似的事情,但让不同的子域名解析到不同的公共静态 IP
答案1
我相信您混淆了术语。
负载平衡通常意味着您连接到一台主机 ( example.com
),然后让负载平衡器将所有连接分发到一台或多台后端主机,通常用户无法控制最终连接到哪个实际主机。这可以通过多种方式轻松为 SSH 实现。
某些协议(例如带有Host
标头的 HTTP)可以为负载均衡器提供更多信息,以决定应将连接路由到哪些后端服务器(例如,example.com
路由到a
和b
,而example.org
路由到c
和d
)。
SSH 没有这样的字段,因此无法使用负载均衡器和仅一个 IP 地址来完成此任务。这使得 LB 不适合此任务。
通常,这个问题可以通过使用主机作为 SSH 代理/网关/跳转主机来解决,并指示您的 SSH 客户端使用它。如果您使用 OpenSSH,请将以下内容输入到您的客户端中~/.ssh/config
Host *.internal.lan
ProxyCommand ssh -q -A -x proxy.example.com -W %h:%p
现在,如果您连接到行中列出的名称Host
,您的 SSH 客户端将首先连接到proxy.example.com
(必须指向您的公共 IP 地址)并将其用作网关以转发到实际机器(如果适用,使用 NAT 端口转发到实际代理机器的端口 22)。请注意,proxy.example.com
必须能够解析*.internal.lan
。设置 DNS 服务器或使用路由器提供的内部服务器来实现此目的。
之后,您可以从外部网络连接到nas.internal.lan
您的 NAS(或raspi.internal.lan
等等),而从您的本地网络内部您只需使用nas
或raspi
(因此连接是直接的,而不是通过网关)。
另一种方法是,假设您使用 NAT:
在 NAT 路由器中创建端口转发,例如
Port 2210 -> internal host1, port 22
Port 2211 -> internal host2, port 22
然后将以下内容放入您的客户端~/.ssh/config
:
Host host1.example.com
Port 2210
Host host2.example.com
Port 2211
并确保host1/2.example.com
两者都指向您的外部 IP 地址。
然后您可以通过 SSH 连接host1.example.com
,OpenSSH 将连接到端口 2210,该端口通过 NAT 网关转发到您的内部主机 1。
这两种方法都适用于您的场景。
答案2
据我所知,您无法基于域执行此操作。HTTP 可以这样工作,因为它有一个特殊的Host
标头,浏览器(在本例中为反向代理)可以理解并基于它做出决策。
在其他 TCP 协议上,我没发现任何类似的东西。SSH 上肯定没有。
答案3
因此,一般来说,是的,只有 HTTP 才能确定 HAProxy 中的目标主机名...但是,如果连接到 HAProxy 的 TCP 客户端发送目标地址(IP 或 FQDN),它是可以废弃该信息并将其用于路由目的。
我介绍一下我的 Minecraft 共享端口扑克庄家:
#starting from top of file, for completeness.
global
user haproxy
group haproxy
#setting tcp mode here is required, won't work if in frontend area!
defaults
mode tcp
#setting up the HAProxy listener:
frontend frontend-name
bind :25565
tcp-request inspect-delay 3s
#ACLs for 1.9 and newer clients:
acl mojang req.payload(5,16) -m sub sub1.domain.tld1
acl bungee req.payload(5,16) -m sub sub2.domain.tld1
acl bungee req.payload(5,16) -m sub sub1.domain.tld2
acl nukkit req.payload(5,16) -m sub sub3.domain.tld1
#ACLs for 1.8 and older clients, keeping pinger working:
acl mojang req.payload(4,16) -m sub sub1.domain.tld1
acl bungee req.payload(4,16) -m sub sub2.domain.tld1
acl bungee req.payload(4,16) -m sub sub1.domain.tld2
acl nukkit req.payload(4,16) -m sub sub3.domain.tld1
#Accept connections if matching an ACL above:
tcp-request content accept if bungee
tcp-request content accept if mojang
tcp-request content accept if nukkit
#Route connection to appropriate backend server:
use_backend minecraft.bungee if bungee
use_backend minecraft.mojang if mojang
use_backend minecraft.nukkit if nukkit
#backend servers - one bungee network, one notchian server, one nukkit server:
backend minecraft.bungee
#here we're directing the connection to bungee on 127.0.0.1:25566
#We're also sending the proxy-protocol(v2) to bungee (check conf!)
server bungee-server 127.0.0.1:25566 send-proxy-v2
backend minecraft.mojang
#Mojang servers can't use the proxy-procotol, so not sending it
server mojang-server 127.0.0.2:25567
backend mincraft.nukkit
#nukkit will never work here, as Bedrock is based on UDP, not TCP!
server sponge-server 127.0.0.3:25568
#EoF
这是一个基本的设置并运行。我的生产设置有很大不同,使用我的设置所需的选项。
现在,问题只剩下——您能在数据包中找到目标主机吗,以便使用 HAProxy 的有效负载来查找它?