NHAS / wag

Simple Wireguard 2FA
BSD 3-Clause "New" or "Revised" License
499 stars 27 forks source link

XDP eBPF firewall blocks register_mfa? #44

Closed uplight-dev closed 1 year ago

uplight-dev commented 1 year ago

Hi

I'm trying to setup WAG on my local intranet but the eBPF firewall blocks the connection by returning XDP_DROP. This seems to be due to the Device having sessionExpiry = 0, as pasted below as output from kernel ring buffer.

Steps:

  1. Add debug logs

    • adapted the internal/router/xdp.c to print the checks done that result in XDP_DROP and also the values of each test branch.
    • rebuilt the WAG executable
  2. Test registration

    • enable port-forward in router to VM that hosts the WAG server, for
    • start WAG server
    • from WAG Host, open Webadmin and add a Registration_Token
    • from the Client device, open register_device url at http://:/register_device?key=. A WireGuard .conf file gets downloaded.
    • configure the file in Client's WireGuard
    • start Client's Wireguard and activate the config
    • handshake works and Transfer begins for both received/sent which is OK
    • register a WAG_DOMAIN.TLD with LetsEncrypt SSL
    • open the https://:/
    • the browser hangs and there's below errors in kernel tracing:
> sudo cat  /sys/kernel/debug/tracing/trace_pipe

kworker/3:0-4612    [003] d.s1  8233.786962: bpf_trace_printk: conntrack(): *isAccountLocked || isTimedOut || current_device->
kworker/3:0-4612    [003] d.s1  8233.787763: bpf_trace_printk: current_device->sessionExpiry == 0
kworker/3:0-4612    [003] d.s1  8233.787770: bpf_trace_printk: currentTime > current_device->sessionExpiry
kworker/3:0-4612    [003] d.s1  8233.787771: bpf_trace_printk: xdp_wag_firewall() = XDP_DROP

Is there something I didn't understand from the Usage guides or is this actually a bug in WAG? Thank you!

NHAS commented 1 year ago

Hi there.

Could I have your wag config file (minus private key)

It's a bit hard to tell what's going on here as the session expiry should only be checked when the route is marked as an Mfa route.

(and I definitely haven't had the issue you're describing)

However by default the vpn server should be default ly enabled. There is another bug about how Mfa always takes precedence over public routes which I am looking to change.

uplight-dev commented 1 year ago

Thank you!

Here's the config.json file:

{
    "Socket": "/tmp/wag.sock",
    "Proxied": false,
    "ExposePorts": [
        "443/tcp",
        "7080/tcp"
     ],
    "NAT": true,
    "Lockout": 5,
    "ExternalAddress": "[REDACTED]",
    "MaxSessionLifetimeMinutes": -1,
    "SessionInactivityTimeoutMinutes": -1,
    "ManagementUI": {
        "ListenAddress": ":4433",
        "Enabled": true
    },
    "Webserver": {
        "Public": {
            "ListenAddress": "0.0.0.0:7080",
            "CertPath": "/wag/cert.pem",
            "KeyPath": "/wag/cert.key"
        },
        "Tunnel": {
            "CertPath": "/wag/cert.pem",
            "KeyPath": "/wag/cert.key",
            "Port": "443"
        }
    },
    "Authenticators": {
        "DefaultMethod": "webauthn",
        "Issuer": "[REDACTED]",
        "Methods": [
            "webauthn"
        ],
        "DomainURL": "https://[REDACTED]",
        "OIDC": {
            "IssuerURL": "",
            "ClientSecret": "",
            "ClientID": ""
        }
    },
    "Wireguard": {
        "DevName": "wg0",
        "ListenPort": 8009,
        "PrivateKey": "[REDACTED]",
        "Address": "10.1.2.1/24",
        "MTU": 1412,
        "PersistentKeepAlive": 25
    },
    "DatabaseLocation": "devices.db",
    "Acls": {
        "Policies": {
            "*": {
                "Mfa": [
                    "10.1.2.0/24",
                    "10.1.1.0/24"
                ],
                "Allow": [
                    "10.1.2.0/24",
                    "10.1.1.0/24"
                ]
            }
        }
    }
}
NHAS commented 1 year ago

Yep I see the problem.

In your config you've marked your vpn network range 10.1.2.0/24 as Mfa, this includes the server address.

So when the server adds the public allow rule for itself, the Mfa rule you add later to allow clients to hit other vpn clients when mfa'd takes precedence.

This is an active bug/feature that's been requested. I am planning on making the rules take the most specific declaration instead of straight preference.

uplight-dev commented 1 year ago

Ok, sorry for my misunderstanding but then Mfa should be on a different host than the server which hosts WAG? Or what else can I put as Mfa in ACLs?

NHAS commented 1 year ago

Oh don't worry this seems to have caught more than just you.

Unfortunately for wag as it stands there isn't a nice way to do Mfa for vpn clients to hit each other without also restricting the server endpoint.

I'm planning on fixing this. But I just haven't had the time recently.

So the work around would be:

I am working on this and I have a fix in mind. Just haven't done it :p

uplight-dev commented 1 year ago

I've changed the Mfa rule to 10.1.2.3/32 and the registration page appears just fine :) It now makes sense and I thought the otherwise. The Mfa rule is indeed to allow VPN clients to see eachother and not to specify the endpoint of MFA itself. I didn't read this correctly from the User guides.

So thanks a lot, and no worries about the fix, it's good you have it planned as I'm looking to use this project to eventually setup security on a VPS using a Yubikey. A bit unrelated, but I'm planning to support a case when the Client device is compromised and an attacker would have full control over it. So I'm thinking to only open a single VNC port behind the VPN and only allow a single connection on that VNC port. When I'm done working, I'd close the VPN connection. Like this, only way to hack the server would be to take control of the VNC while I'm using it (less possible than usual attacks).

Do you know, in case the attacker could eavesdrop all traffic, if he could launch a replay attack and successfully login to WAG without using the Authenticator token? Also, when I disconnect from WireGuard client app, could I force that a reconnect would require the Authenticator token?

NHAS commented 1 year ago

Really depends on what you mean by a compromised end device.

If an attacker is on your machine wag will only help if the user doesn't enter in their Mfa credentials.

If you mean an attacker had stolen the wireguard config, then wga effectively stops one config from being used in two places and would cause Mfa to have to be constantly reentered.

I need a bit more information about the scenario you're envisioning

uplight-dev commented 1 year ago

The scenario is that I'm working from home network and there's some devices that are insecure due to people going to various sites, downloading possible malware. These have lots of data so I cannot factory reset them easily. So I thought of moving my work in a VPS, make that secure instead(encrypt drives, etc.) and store there the sensitive files and slowly migrate everything from home network there. But all is useless if an attacker would manage to install a backdoor on that VPS. I've bought a Yubikey and hope it'd provide a way to prevent any access to that VPS by unauthorized parties.

uplight-dev commented 1 year ago

So based on your answer, after I logout from WAG, it's only possible to login if the Auth token is used again. This only leaves the case with the current session. But there I guess the only way is by either hacking the VNC port during the VPN session from the same device I'm using or by logging in to VNC before I get to (since VNC only allows 1 connection).

I just tested and there might be an issue: Steps:

Please note:

I read the User guide but it's not very clear that Mfa is for accessing other VPN clients during a Mfa'd session while Allow is to permit open access to VPN clients, no matter if they're logged in or not (i.e not getting blocked by the eBPF Firewall). And that Allow is rather useful for the initial registration of the Auth token, where you're not logged-in yet. Just a suggestion, perhaps updating it might help others stumbling on same issue.

NHAS commented 1 year ago

Sorry I think there is a misunderstanding here. The Mfa section allows you to mark any arbitrary ranges as requiring Mfa.

What you have shown me is that you've marked your vpn client network range as needing Mfa, which means wag will allow traffic to your vpn clients once Mfa is correctly entered.

In terms of the 8081 port being exposed. I mean you have added it to exposed ports, which exposes the port on the vpn server to the clients... So I'm. Not sure what the issue is there?

uplight-dev commented 1 year ago
  1. Yes indeed, I was just saying that by reading the User guide I understood exactly the opposite of this. I thought Mfa is for granting access while making the Mfa registration, where Mfa shouldn't be enforced. And that Allow is for which networks have access to VPN while using the Auth Token. Don't want to insist on it, but it's possible other users could do same mistake and spend some time on debugging.

  2. Also please disregard the steps in my previous comment. I realized I tried them with the 8081 server being configured as "Acls.Allow". Which means, no matter if I was using the token or not, it was visible. I'll correct the test case and let you know.

  3. About the exposed ports, do you know the difference than putting in Acls.Allow list, the same ports?

  4. And I tried another test with something like this, but the Allow list gets overriden. Could you please confirm if the bug you described is per IP address(i.e. Mfa/IP overrides Allow/IP even if the ports are different)?

    "Acls": {
        "Policies": {
            "*": {
                "Mfa": [
                    "10.1.2.1/32 8081/any"
                ],
                "Allow": [
                    "10.1.2.1/32 443/any"
                ]
            }
        }
    }
  5. Looking again at my use case, I realized I'd need VLAN isolation between the hosts in the VPN. Is that possible with WAG? Related https://www.reddit.com/r/WireGuard/comments/vtoeet/is_it_possible_to_create_two_wireguard_vpns_on/. Here someone created 12 WG instances on same server. Would that work fine with WAG?

Thanks a lot for everything!

NHAS commented 1 year ago
  1. I find it unlikely other people will make this mistake as the the declaration is literally "Mfa" vs "Allow", which I hoped would indicate that one would require Mfa.

  2. ExposedPorts is for exposing ports on the VPN server itself as such it also adds Iptables rules, putting things in the Allow section adds things to the eBPF firewall. (This question is a little unclear, so I think this is what you're asking)

  3. This isnt a bug. You've defining two rules for the same ip address, and as such the MFA route takes precedence. Even with the upcoming changes I've got planned this will be a configuration error and not allowed. (As it doesnt make sense to define a rule as MFA and Public/Allowed)

  4. This isnt possible with wireguard as a technology, wireguard is a layer 3 VPN only which means there is no such thing as VLANs for wireguard. You can run multiple instance of wag on one server, but you cant have one instance of wag managing multiple wireguard devices.

uplight-dev commented 1 year ago

Ok, I understand, just wanted to help improve things, no worries. If it doesn't break things, a suggestion perhaps is RequiresMfa and DMZ - although without further explanation as a side-comment it's still not 100% clear. This is my last attempt, sorry for insisting with this :)

About VLANs, do you know if launching multiple WAGs would severly impact performance/memory consumption? Or perhaps if there are limits on the max number of WAGs per server?

NHAS commented 1 year ago

Unfortunately since this is already part of peoples configurations its a bit hard to change on a whim (I typically only add to the configuration file, not change it too much).

On another note, I have the first version of wag that will fix your issue and also resolve #43

NHAS commented 1 year ago

I can definitely see how the user manual isnt quite as clear as it needs to be around this. So I'l add some documentation around it, rather than just relying on my implicit understanding of things

NHAS commented 1 year ago

Policies: A map of group or user names to policy objects which contain the wag firewall & route capture rules
Policies.<policy name>.Mfa: The routes and services that require Mfa to access
Policies.<policy name>.Public: Routes and services that do not require authorisation

This is what Im going to put ^

uplight-dev commented 1 year ago

That's great to know and especially that the fix is here and now :) I'll test it as next thing on my list. And I had the same with the implicit understanding, and it's not easy to see when it manifests. But that's the great part when writing open source, having a community around to build the product ;) You were kind and open, I respect that. Hope you'll have great success and as someone else said here, WireGuard is a great product but it lacks Mfa. And WAG looks like the answer to me for it.

NHAS commented 1 year ago

https://github.com/NHAS/wag/releases/tag/v6.0.1-pre-release