caddy-l4 icon indicating copy to clipboard operation
caddy-l4 copied to clipboard

Feature Request: dynamic proxying based on SNI

Open ktmart opened this issue 3 years ago • 2 comments

Hi,

In regular caddy I can do what i call "dynamic proxying", where the queried hostname defines dynamically the backend to use. Here is an example as a caddyfile:

*.example.com {
  tls {
    on_demand
    client_auth {
      mode require_and_verify
      trusted_ca_cert_file /path/to/ca.pem
    }
  }
  
  @proxied {
    vars_regexp backend {host} ^(?P<host>[a-z0-9]+)\.example.com$
  }
  
  route @proxied {
    reverse_proxy {
      to {re.backend.host}.example.local
      transport http
    }
  }
}

I didn't find out how to reproduce this kind of behavior with layer4, it would be really nice to have this feature!

Thanks!

ktmart avatar Jul 22 '22 09:07 ktmart

Use a TLS matcher that matches on SNI, for a route that proxies to the backend you want. I'm mobile right now but hopefully that gives you a quick starting point.

mholt avatar Jul 22 '22 15:07 mholt

@ktmart Ok, so yeah, the last example in our README: https://github.com/mholt/caddy-l4#config-examples

Shows how to match routes based on HTTP Host and TLS ServerName. In your case you'd just have multiple that use TLS ServerName.

We could probably simplify that config if l4 had a map handler like the http app does: https://caddyserver.com/docs/modules/http.handlers.map

That would allow you to map TLS ServerName to a variable which you could then use in a single proxy handler.

mholt avatar Jul 22 '22 19:07 mholt

What else do you need to have this work for you? Does the README example not do what you need?

mholt avatar Aug 04 '22 18:08 mholt

@ktmart Oh, I see, so you want to use a placeholder in the proxy address, right? The TLS matcher sets a placeholder: https://github.com/mholt/caddy-l4/blob/master/modules/l4tls/matcher.go#L102

So you can use {l4.tls.server_name} after matching. (I don't think you need to enumerate any strings or use a regular expression.)

mholt avatar Aug 17 '22 15:08 mholt

@mholt my understanding is they want just the {labels.2} only (in Caddy HTTP-app language), not the whole domain, which is why they use a regexp there. Note that the input is *.example.com while the proxy is to *.example.local

francislavoie avatar Aug 17 '22 15:08 francislavoie

Ohh, I see. Ok yeah, this can be implemented pretty easily I think.

mholt avatar Aug 17 '22 15:08 mholt