caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
57.47k stars 4.01k forks source link

Use layer4 as a listener wrapper OR pipe layer4 connection to http FOR ocserv multiplexing #6439

Closed vnxme closed 1 month ago

vnxme commented 3 months ago

Hi,

My intention is to multiplex ocserv (OpenConnect VPN server, it could be treated as a TLS-capable non-HTTP application) and caddy on a single port. What I would like to achieve is the following logic: caddy listens on :443, if it receives a TLS connection with SNI ocserv.example.com, it passes it through without terminating TLS to another host where ocserv runs, otherwise it terminates TLS on its own and serves example.com and its subdomains other than ocserv.example.com. An additional point is I would like to use caddyfile adapter to configure caddy for both layer4 and http/tls, but I understand that's another issue.

It's possible (as of caddy@v2.8.4 and caddy-l4@ca3e2f3) to make the layer4 app listen on :443 and the http app listen on another port (e.g. :444), and proxy non-ocserv.example.com from :443 to :444. For reference, see below the relevant part of autosave.json. However, given both layer4 and http apps are inside caddy, I would like to find a way to do the same more efficiently without proxying.

autosave.json, layer4 proxy, working ``` "layer4": { "servers": { "example": { "listen": [":443"], "routes": [ { "match": [ { "tls": {"sni": ["ocserv.example.com"]} } ], "handle": [ { "handler": "proxy", "upstreams": [ {"dial": ["ocserv.address.local:443"]} ] } ] }, { "match": [ { "not": [ { "tls": {"sni": ["ocserv.example.com"]} } ] } ], "handle": [ { "handler": "proxy", "upstreams": [ {"dial": ["localhost:444"]} ] } ] } ] } } }, ```

As far as I understand, this is a topic which has been discussed a few times so far, and there are a number of relevant issues/PRs:

Thus, my question is whether there is any way to make ocserv multiplexing work without proxying other subdomains (any mistake in layer4 listener wrapper config above?) or implement such a functionality in caddy and/or caddy-l4?

Regards,

vnxme commented 3 months ago

Seems like there is a related PR battle between https://github.com/mholt/caddy-l4/pull/208 and https://github.com/mholt/caddy-l4/pull/210. Hope they will soon find a mutually acceptable solution to restore the old behaviour (fallback next handler), and the layer4 listener wrapper config above will probably work.

Nevertheless, it would be great if https://github.com/caddyserver/caddy/pull/5040 could be finalised and some documentation/examples provided. Generally it might be an even better solution than listen wrappers.

mholt commented 3 months ago

Yeah, layer4 plugin is currently undergoing some revisions.

To serve TLS without terminating it, you'll need the layer4 module. Caddy's HTTP server can only terminate TLS. Generally speaking, any and all protocol multiplexing will need the layer4 module.

vnxme commented 3 months ago

Following @ydylla's config samples, namely the one named "listener-wrapper-matcher-with-no-handler.json" (see https://github.com/mholt/caddy-l4/issues/209), I've managed to make my layer4 listener wrapper config work using the suggested workaround.

autosave.json, layer4 listener wrapper, working ``` "listener_wrappers": [ { "wrapper": "layer4", "routes": [ { "match": [ { "tls": {"sni": ["ocserv.example.com"]} } ], "handle": [ { "handler": "proxy", "upstreams": [ {"dial": ["ocserv.address.local:443"]} ] } ] }, { "match": [ { "not": [ { "tls": {"sni": ["ocserv.example.com"]} } ] } ] } ] }, { "wrapper": "tls" } ], ```
vnxme commented 3 months ago

@mholt Thank you for responding. The layer4 module is absolutely amazing! Really appreciate your time and effort spent on it.

Do you have any plans to merge it into caddy core? Or at least make it configurable the way caddy works? I mean the caddyfile adapter.

And what do you actually think about https://github.com/caddyserver/caddy/pull/5040?

mholt commented 3 months ago

Do you have any plans to merge it into caddy core? Or at least make it configurable the way caddy works? I mean the caddyfile adapter.

We've talked about it. We need to resolve some of the glaring issues with it first, obviously. But it's a good candidate as it seems to be getting quite popular / in higher demand as time goes on. It'll be a lot of work, especially that Caddyfile support.

And what do you actually think about https://github.com/caddyserver/caddy/pull/5040?

I like that change still, but I have yet to find time to test it end-to-end. If someone who is savvy with Go wants to try wiring up the Layer4 module to support the exported Pipe() method, then we can probably make some progress on it sooner. I've just been very behind :sweat_smile: