通过主机名代理 TCP

通过主机名代理 TCP

我的单台主机上有多个游戏服务器 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

是否有类似 hdr(host) 的检查可用于 TCP 连接?还是我操作正确,但游戏玩起来不太顺畅?

谢谢!

答案1

作为代理的替代方法(取决于应用程序协议,是否可以根据主机名执行),您可能需要检查客户端软件是否SRV注意,在这种情况下您应该能够仅在 DNS 中设置它。

记录SRV具有以下格式:

_Service._Proto.Name TTL Class SRV Priority Weight Port Target

在您提到 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.

答案2

在 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 协议开始时以明文发送的少数信息也会在协议的后面进行身份验证,因此如果您弄错了其中的任何部分,通信就会中断。更难以处理的是,在服务器将横幅发回客户端之前,客户端不会发送哪怕一个字节的有效负载。因此,代理几乎没有任何信息可以使用。

我不知道还有什么其他带主机名的协议可用于此类目的。所以我猜想上面未列出的大多数协议都无法通过主机名进行代理。

相关内容