Reverse TCP (SSH) proxy with host.match

1. The problem I’m having:

Thank you guys so much for Caddy! A real gem!

I am trying to configure Caddy as a reverse raw tcp proxy and use it with a match.host.
My idea is to redirect an SSH request to a specific port on the localhost depending on the hostname.

I got a similar functionality but only for HTTPS requests.
Using the APIs I generate a new route at runtime where I create a randomdomain that I use for the match.host to select the reverse proxy, e.g.:

          "routes": [
            {
              "match": [
                {
                  "host": [
                    "randomdomain.example.com"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "reverse_proxy",
                  "upstreams": [
                    {
                      "dial": ":5000"
                    }
                  ]
                }
              ]
            }
          ]

It works without any problems.
I would like to achieve the same result using caddy-l4, in a scenario like this:

But I can’t figure out how to find an alternative to match.host in layer4.

I understood that layer4 does not support match.host, can you advise me how I could achieve the same result as the HTTPS case but with TCP (or better SSH) requests?

Thank you very much for the help.

3. Caddy version:

v2.7.5 h1:HoysvZkLcN2xJExEepaFHK92Qgs7xAiCFydN5x5Hs6Q=

4. How I installed and ran Caddy:

a. System environment:

  • Ubuntu
  • ec2 instance.

b. Command:

./caddy run --config caddy_config.json

d. My complete Caddy config:

{
  "apps": {
    "http": {
      "servers": {
        "example": {
          "listen": [
            ":443"
          ],
          "routes": []
        }
      }
    }
  }
}

There’s no such thing as “host” in raw TCP or SSH.

In HTTP, there’s the Host header, which is how routing by host is done.

In HTTPS (i.e. HTTP + TLS) there’s TLS-SNI (i.e. Server Name Indication) which is passed in cleartext during the TLS handshake. That’s necessary because the HTTP bytes are encrypted, so that aspect needs to be hoisted to the TLS layer for routing to still happen.

1 Like

Thank you for your clear answer!
I have seen a few examples online based on ProxyCommand to achieve SSH routing based on SNI, but I would like to avoid it.

I am then wondering if there is a way/configuration with Caddy to do a mapping between subdomains with a specific internal port for raw TCP connections.

Currently, is there this functionality in Caddy or external plugins?

Thank you

Like I said, the problem is raw TCP connections don’t carry subdomains in their payload unless the underlying protocol actually does that itself. So that’s not a thing.

I think you mean things like this Route SSH Connections with HAProxy (In-Depth Configuration) ?

You can do that with caddy-l4 I think. In theory. You could terminate TLS and use the SNI matcher to do routing. That might work. But I’ve never played around with it.

I think you mean things like this Route SSH Connections with HAProxy (In-Depth Configuration) ?

You can do that with caddy-l4 I think. In theory. You could terminate TLS and use the SNI matcher to do routing. That might work. But I’ve never played around with it.

Yes, exactly.
Maybe I will give it a try.

Thank you for your support.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.