Caddy L4 as TLS relay

I’m trying to setup my Caddy server with a Signal TLS proxy. I know there are some topics that discuss this implementation, like TLS proxy or relay in Caddy and How to convert the stream_ssl_preread_module in nginx to caddyfile, however, I’m having quite some trouble understanding the L4 extension syntax.

I want to use the Caddyfile format, as the rest of my configuration is using this format. I tried playing around with caddy adapt and I got the following code snippet to generate a similar result as to the original PR for the Signal TLS proxy:

{
    layer4 {
        localhost:4443 {
            @secure tls sni chat.signal.org ud-chat.signal.org storage.signal.org cdn.signal.org cdn2.signal.org cdn3.signal.org cdsi.signal.org contentproxy.signal.org sfu.voip.signal.org svr2.signal.org updates.signal.org updates2.signal.org
            route @secure {
                proxy {l4.tls.server_name}:443
            }
        }
    }
}

The Caddyfile above generates the following JSON config

{
  "apps": {
    "layer4": {
      "servers": {
        "srv0": {
          "listen": [
            "localhost:4443"
          ],
          "routes": [
            {
              "match": [
                {
                  "tls": {
                    "sni": [
                      "chat.signal.org",
                      "ud-chat.signal.org",
                      "storage.signal.org",
                      "cdn.signal.org",
                      "cdn2.signal.org",
                      "cdn3.signal.org",
                      "cdsi.signal.org",
                      "contentproxy.signal.org",
                      "sfu.voip.signal.org",
                      "svr2.signal.org",
                      "updates.signal.org",
                      "updates2.signal.org"
                    ]
                  }
                }
              ],
              "handle": [
                {
                  "handler": "proxy",
                  "upstreams": [
                    {
                      "dial": [
                        "{l4.tls.server_name}:443"
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        }
      }
    }
  }
}

However, as I noticed from both implementations, this enables the L4 proxy on the apex domain. I want the proxy to run on a subdomain, but I can’t understand how to enable it.

I also tried to use the following Caddyfile (which produces a JSON config similar to one of the threads linked):

{
    layer4 {
        :443 {
            @secure {
                tls sni chat.signal.org ud-chat.signal.org storage.signal.org cdn.signal.org cdn2.signal.org cdn3.signal.org cdsi.signal.org contentproxy.signal.org sfu.voip.signal.org svr2.signal.org updates.signal.org updates2.signal.org
                http host proxy.example.com
            }
            route @secure {
                proxy {l4.tls.server_name}:443
            }
        }
    }
}

but Signal still cannot connect to the TLS relay proxy. So, my question is, how to setup a relay proxy on a subdomain, using Caddyfile format and not JSON? And how can I setup automatic SSL certificate handling for this subdomain - do I need to include an empty domain block on the Caddyfile?

Okay, after some messing around I managed to get Signal to connect to the proxy.

This is the Caddyfile config:

{
    layer4 {
        :443 {
            @secure {
                tls sni chat.signal.org ud-chat.signal.org storage.signal.org cdn.signal.org cdn2.signal.org cdn3.signal.org cdsi.signal.org contentproxy.signal.org sfu.voip.signal.org svr2.signal.org updates.signal.org updates2.signal.org
            }
            @sub http host proxy.example.com
            route {
                tls
            }
            route @secure @sub {
                proxy {l4.tls.server_name}:443
            }
        }
    }
}

I would still like to know a bit what is going on here.

The http matcher matches any requests to proxy.example.com - I tried removing this block and realized I could use any subdomain that has a valid certificate, but also, if I include it in the same block as the Signal domains, it doesn’t work.

As for the rest

route {
  tls
}
route @secure @subdomain {
  proxy {l4.tls.server_name:443}
}

what does this mean? Is it telling Caddy to terminate the SSL connection? And then it goes to the next route block and just forwards the request to the upstream SSL server?

(also, is there a way to simplify this code?)