Proxying TCP by hostname

15,078

Solution 1

As an alternative to proxying (where it depends on the application protocol if it's possible to do based on hostnames) you may want to check if the client software is SRV aware, in which case you should be able to set this up in DNS alone.

An SRV record has the following format:

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

In your specific example where you mentioned multiple instances of Minecraft it should be possible to do this based on SRV records and the records could look something like this:

_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.

Solution 2

Dispatching connections to different backends depending on the hostname which the client connected to is impossible to do on the TCP layer.

You will have to either use separate IP addresses for each hostname or implement the proxying at the application layer with protocol specific code to detect the hostname.

Such a proxy is possible for certain protocols but not for others. Ranging from easy to impossible, the protocols I know enough about are:

  • HTTP is easy to support. All HTTP/1.1 clients and most HTTP/1.0 clients will send a host header before expecting any answer answer from the server. Clients without host header are likely long gone, since many sites these days will not work without it.
  • HTTPS can be supported for all clients with SNI support. SNI was standardized much more recently than HTTP/1.1, there are still a few clients around without SNI support.
  • DNS is possible to support but slightly tricky. In most cases you'd just operate your authoritative DNS server directly on a public IP address instead of proxying.
  • SMTP is possible to support but also tricky. A proxy for SMTP would likely end up looking more like an SMTP relay than like a proxy.
  • SSH is impossible to support. The concept of hostnames simply doesn't exist in the protocol. The client may use DNS to resolve the IP address of the server, and it may associate stored host keys with their host names, but this is entirely an implementation detail on the client side. This would not be visible to the proxy, so it cannot be used to dispatch connections. Moreover no useful information is send in cleartext, and even the few pieces of information that are send in cleartext at the start of the SSH protocol are authenticated later in the protocol, so if you get any part of that wrong, the communication breaks. What makes this even more impossible to handle is the fact that the client does not send even one byte of payload until the server has send a banner back to the client. So the proxy would have literally no information to work with.

I am not aware of any other protocol with a hostname, which could be used for such purposes. So I am guessing that most protocols not on the above list are impossible to proxy by hostname.

Share:
15,078

Related videos on Youtube

shaun m
Author by

shaun m

DevOps at airG

Updated on September 18, 2022

Comments

  • shaun m
    shaun m almost 2 years

    I've got multiple game servers TCP ports on my single host machine. The goal is to have users be able to connect to server1.domain.net and have their directed based on that subdomain. My first instinct wrote the following but then I realised that TCP traffic isn't going to have any header to read. Using HAProxy 1.5.8. I tried doing this same thing using multiple backends, use_backend and full ACL lines but got the same result (understandably).

    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
    

    Is there a check like hdr(host) that I can use for TCP connections? Or am I doing it right and the game just isn't playing nice?

    Thanks!

    • Michael Hampton
      Michael Hampton over 9 years
      This isn't even possible unless the protocol being proxied supports it, and most do not.
    • Håkan Lindqvist
      Håkan Lindqvist over 9 years
      Are these games SRV aware? That would open a possibility of solving it in DNS, eliminating the need for proxying at all.
    • shaun m
      shaun m over 9 years
      That is not something I'd considered. These are Minecraft servers and some quick Googling turned up this post which seems like a good answer: serverfault.com/questions/474225/… Thanks! If you make your comment an answer, I'll accept it.
  • BradChesney79
    BradChesney79 almost 5 years
    ...a workaround for SSH is setting up a singular bastion server on a particular port for SSH. From there it is a simple TCP forward for that port. Once you are inside, then you have full access to the machines your bastion server can reach. SSH'ception'... "We have to go deeper!"