使用 HAProxy 根据域路由 SSH 流量

使用 HAProxy 根据域路由 SSH 流量

我目前正在家中构建自己的小型集群,并尝试让 SSH 路由(负载平衡)与 HAProxy 配合使用。我已经弄清楚了如何路由 HTTP 流量,但我在 SSH 方面遇到了困难。我对 TCP 协议了解不够多,无法立即知道我必须寻找什么,以便我可以确定如何查询连接,例如主机(不确定它是否在连接的某个地方)或任何可以识别我想要 SSH 进入哪个服务器的东西。

文档反复提到 SSH 流量,所以我可能遗漏了一些东西。我不想使用不同的端口,也不想使用不同的端口来回路由,因为它们可能不是标准的,因此在公共网络上会被屏蔽,或者其他会限制我的东西。

我当前的设置如下:

在我的域(或 IP)上发出请求 -> 路由器 -> 根据端口进行 NAT 转发 -> HAProxy 监听该端口 -> 现在应该识别专用于某个服务器的流量并代理流向它的流量。

编辑:正如Cha0s所澄清的那样,使用SSH(或类似方式)这是不可能的。

如果你对不同的方法感兴趣,Sven 的答案可以很好地帮助你做类似的事情,但让不同的子域名解析到不同的公共静态 IP

答案1

我相信您混淆了术语。

负载平衡通常意味着您连接到一台主机 ( example.com),然后让负载平衡器将所有连接分发到一台或多台后端主机,通常用户无法控制最终连接到哪个实际主机。这可以通过多种方式轻松为 SSH 实现。

某些协议(例如带有Host标头的 HTTP)可以为负载均衡器提供更多信息,以决定应将连接路由到哪些后端服务器(例如,example.com路由到ab,而example.org路由到cd)。

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等等),而从您的本地网络内部您只需使用nasraspi(因此连接是直接的,而不是通过网关)。

另一种方法是,假设您使用 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 的有效负载来查找它?

相关内容