opnsense / plugins

OPNsense plugin collection
https://opnsense.org/
BSD 2-Clause "Simplified" License
832 stars 619 forks source link

www/caddy: Add "layer4.matchers.wireguard" matcher #4201

Open hrvojesolc opened 2 weeks ago

hrvojesolc commented 2 weeks ago

Important notices Before you add a new report, we ask you kindly to acknowledge the following:

Is your feature request related to a problem? Please describe. Before os-caddy, I could bind wireguard to 443 (udp). Even though wireguard has it's own protocol (not HTTPS), serving it on 443/udp allows to bypass many corporate firewalls that do not do packet inspection (most fast food chains in Ontario, Canada offering free WiFi). Caddy binds on 443/udp, presuming for QUIC HTTP/3.

Describe the solution you'd like It would be nice to use layer4 matching Wireguard protocol for reverse proxy to its native 51820/udp. I'm not sure if this is native caddy layer4 functionality or anything added specifically by os-caddy maintainers. Searches on internet such as https://github.com/mholt/caddy-l4 make it seem that there is concentrated effort on this. I know Wireguard portocol isn't listed anywhere as supported by caddy, but something like "layer4.matchers.regexp" maching first packet could potentially be used to match Wireguard traffic.

Describe alternatives you've considered

Additional context I used to run OpenVPN on 443/tcp which was great and worked wonderfully. Testing showed that Wireguard on 443/udp worked well for my scenarios so I switched to it for performance related reasons (browsing SMB, remote display, etc). Ideally I would like to have Wireguard appear as TLS (HTTPS) traffic from internet coming into the firewall so that it cannot be filtered out by corporate firewalls, but this is likely not happening in near future. Right now I put Wireguard back to 51820/udp and will possibly install OpenVPN and try reverse proxy to it as backup for when Wiregaurd is filtered by public/corporate networks.

Thanks for this great plugin!

Monviech commented 2 weeks ago

I don't quite understand what you need from me here.

If you need a certain traffic matcher supported, going upstream first and asking for it would be the best choice.

https://github.com/mholt/caddy-l4

The regex matcher is not supported in the GUI but you can certainly mess with it by using custom files.

https://docs.opnsense.org/manual/how-tos/caddy.html#custom-configuration-files

You can also change the default ports in the advanced general settings and then use Port Forwarding.

hrvojesolc commented 2 weeks ago

Thank you for your response. I'm new to caddy.

TLDR - It would be nice to add all the matchers that caddy-l4 supports in the GUI here: image

I'm not specifically looking for Wireguard protocol to be implemented in caddy here, just caddy's options. I wasn't sure if mholt/caddy-l4 is what is currently implemented in 2.8.4. I tried going through https://github.com/caddyserver/caddy to find out info on layer 4, but it doesn't seem to exists on any of the release notes. When I saw it used in os-caddy I started looking for info.

I'm now guessing that caddy in os-caddy plugin is using a non-vanilla version of caddy with custom features/modules baked in. If so, it would be nice to put the version number of caddy as well as caddy features in the base of release notes here (not the changelog): image

That is, can version number (2.8.4) be put into the wording into above notes as well as names of any extra features such as mholt/caddy-l4 in https://caddyserver.com/download: image

Doing this will make it easier to figure out how to go about testing some functionality that is not in the GUI.

Thank you again for your help and the great addition to OPNsense. I really appreciate it. I'll go on and try messing with the config files to test.

hrvojesolc commented 2 weeks ago

I've changed to title to remove Wireguard references. I know now that this is not something upstream has and I'll try to bring it up there and fiddle with custom config files manually. Thanks again.

Monviech commented 2 weeks ago

https://caddyserver.com/docs/command-line

caddy list-modules

That would have shown you the complete build. Since the build gets updated a lot I dont want to change the pkg description every time.

The GUI only offers matchers that I have tested. Im afraid of the support overhead of the regex matcher, unsure if adding it in the GUI is a wise choice.

Other matchers will be downstreamed over time when theyre added, the framework makes it easy to add new ones that don't need new custom fields.

Monviech commented 1 week ago

I implemented your feedback so the dependencies are more visible:

https://github.com/opnsense/plugins/blob/fc0bf2d9f82fe34ad511132e047fd477ba106e55/www/caddy/pkg-descr#L5-L8

vnxme commented 1 day ago

Hi! There is a wireguard matcher in caddy-l4 now. See https://github.com/mholt/caddy-l4/pull/245 for details.

Monviech commented 23 hours ago

Awesome @vnxme I will compile and add it in the next version. Thank you!

Monviech commented 22 hours ago

@vnxme I have one question regarding the matcher:

Can it also work like this (without specifying UDP)? Will it still match UDP traffic and proxy it as UDP traffic implicitly?

{
    layer4 {
        :443 {
            @test wireguard
            route @test {
                proxy server.local:51820
            }
        }
}
vnxme commented 19 hours ago

@Monviech Your question is out of scope of the matcher. It is related to how server listener and proxy upstream parse specified protocol-address-port combinations. I think you have to specify UDP for both server listener and proxy upstream, otherwise TCP is implicitly used, while WireGuard is pure UDP.

Monviech commented 19 hours ago

@vnxme Thank you for clarifying.

Monviech commented 13 hours ago

I have tested the wireguard matcher and it works. But it will not work inside the listener_wrapper which the layer4 implementation inside this caddy plugin currently builds on.

To allow caddy to proxy wireguard on udp/443, the following has to be added to the Caddyfile server directive to free the port from QUIC:

protocols h1 h2

This means the most straight forward way to solve the issue here would be an option to allow disabling QUIC with a checkbox so wireguard can bind directly to udp/443.

The actual wireguard matcher can then be added at a later time when the layer4 implementation inside this plugin gets another expansion to allow config generation outside the listener_wrapper scope.

vnxme commented 13 hours ago

@Monviech Please post your full config where the listener wrapper is used.

Monviech commented 13 hours ago

@vnxme

Normal Layer4 directive: (Does work for me. Yay) Note: Here I explicitely have to prevent h3 so udp/:443 is free for layer4 matcher.

{
        layer4 {
                udp/:443 {
                        @wg0 wireguard
                        route @wg0 {
                                proxy udp/172.16.0.254:51820 {
                                }
                        }
                }
        }
        servers {
                protocols h1 h2
                listener_wrappers {
                        layer4 {
                                # Other matchers in here that proxy TCP protocols
                                route
                        }
                        tls
                }
        }
}

:80 {
}

:443 {
}

Listener Wrapper: (Does not work for me) Note: Here I assume since sockstat shows the h3 port listening on udp:/443, that this UDP traffic would hit the listener_wrappers too, and then be wireguard protocol matched and proxied to udp/172.16.0.254:51820.

{
    servers {
        listener_wrappers {
            layer4 {
                @wg0 wireguard
                route @wg0 {
                    proxy udp/172.16.0.254:51820 {
                    }
                }
                route
            }
            tls
        }
    }
}

:80 {
}

:443 {
}
sockstat -l | grep -i -e :443 -e :80
caddy caddy        390 8   udp46  *:443                 *:*
caddy caddy        390 16  tcp46  *:443                 *:*
caddy caddy        390 19  tcp46  *:80                  *:*