通过主机名代理 TCP

sha*_*n m 9 tcp access-control-list haproxy gameserver

我的单个主机上有多个游戏服务器 TCP 端口。目标是让用户能够连接到 server1.domain.net 并根据该子域进行定向。我的第一直觉写了以下内容,但后来我意识到 TCP 流量不会有任何要读取的标头。使用 HAProxy 1.5.8。我尝试使用多个后端、use_backend 和完整的 ACL 行做同样的事情,但得到了相同的结果(可以理解)。

listen game-listener
  bind x.x.x.x:22222
  mode  tcp
  use-server  server1 if { hdr(host) -i server1.domain.net }
  use-server  server2 if { hdr(host) -i server2.domain.net }
  server server1 localhost:22201 check
  server server2 localhost:22202 check
Run Code Online (Sandbox Code Playgroud)

是否有像 hdr(host) 这样的检查可以用于 TCP 连接?还是我做得对,而游戏玩得不好?

谢谢!

kas*_*erd 5

根据客户端连接的主机名将连接分派到不同的后端在 TCP 层上是不可能的。

您必须为每个主机名使用单独的 IP 地址,或者使用协议特定代码在应用程序层实现代理以检测主机名。

这种代理对于某些协议是可能的,但对于其他协议则不是。从容易到不可能,我足够了解的协议是:

  • HTTP 易于支持。所有 HTTP/1.1 客户端和大多数 HTTP/1.0 客户端都将在期待来自服务器的任何回答之前发送主机标头。没有主机头的客户端可能早已不复存在,因为现在许多网站没有它就无法工作。
  • 所有支持 SNI 的客户端都可以支持 HTTPS。SNI 比 HTTP/1.1 更近标准化,仍然有一些客户端没有 SNI 支持。
  • DNS 是可以支持的,但有点棘手。在大多数情况下,您只需直接在公共 IP 地址上操作您的权威 DNS 服务器,而不是代理。
  • SMTP 可以支持,但也很棘手。SMTP 代理可能最终看起来更像是 SMTP 中继,而不是代理。
  • SSH 无法支持。协议中根本不存在主机名的概念。客户端可以使用 DNS 来解析服务器的 IP 地址,并且可以将存储的主机密钥与其主机名相关联,但这完全是客户端的实现细节。这对代理是不可见的,因此它不能用于分派连接。此外,没有任何有用的信息以明文形式发送,即使是在 SSH 协议开始时以明文形式发送的几条信息也会在协议后期进行身份验证,因此如果您弄错了任何部分,通信就会中断。使这更不可能处理的是这样一个事实,即在服务器将横幅发送回客户端之前,客户端甚至不会发送一个字节的有效负载。

我不知道任何其他带有主机名的协议,可用于此类目的。所以我猜大多数不在上面列表中的协议是不可能通过主机名代理的。


Håk*_*ist 5

作为代理的替代方案(如果可以基于主机名,则取决于应用程序协议)您可能需要检查客户端软件是否SRV知道,在这种情况下,您应该能够单独在 DNS 中进行设置。

一个SRV记录的格式如下:

_Service._Proto.Name TTL Class SRV Priority Weight Port Target
Run Code Online (Sandbox Code Playgroud)


在您提到多个 Minecraft 实例的具体示例中,应该可以根据SRV记录执行此操作,并且记录可能如下所示:

_minecraft._tcp.foo.example.com. 86400 IN SRV 0 5 25565 server1.example.com.
_minecraft._tcp.bar.example.com. 86400 IN SRV 0 5 25566 server1.example.com.
Run Code Online (Sandbox Code Playgroud)