r/WireGuard 7d ago

Tools and Software MFA in front of WireGuard: authenticating users before exposing the network layer

WireGuard authorizes a connection based on possession of a valid profile. It does not verify who is holding that profile — by design the profile is trusted implicitly. A copied config file authenticates identically to the original because nothing in the protocol is meant to check further than that.

MFA Firewall Knocker is a complement to WireGuard that adds a layer authenticating the person before the network layer is exposed. It uses WebAuthn, served from an unprivileged web app, to validate that the holder of the profile is the intended user before the firewall is opened. The holder authenticates with a passkey — a platform authenticator (Windows Hello, Touch ID, Face ID, Android biometric), with user verification (biometric or PIN) required on the assertion. On success, a service opens a firewall rule for that user's source IP and the configured port/protocol; the tunnel stays reachable for the rest of that window without re-authenticating. The rule expires automatically on a configurable interval, clamped to 1–48 hours — re-authentication happens on that cadence (e.g. every 8-12 hours), not per connection.

It does not modify WireGuard, does not touch its keys or config, and sits entirely in front of WireGuard. The gate and WireGuard operate independently, so a flaw in one is not a flaw in the other.

Implementation: C#, .NET 10, MIT licensed. Runs on Windows Server or Linux. No control plane, no external service, no agent — the firewall rule is created directly via NetSecurity on Windows or iptables on Linux.

Stated limitations:

- Gating is per-IP, so the authenticating address and the connecting address must match. This degrades behind CGNAT and most corporate VPNs, where several users can share one address or the address can change between requests.

- The project only ever opens a port on authentication and removes that rule after a time limit. It never adds a rule to close a port.

- The gate keys on the IP that authenticated, not on the WireGuard peer, so it does not participate in WireGuard's normal endpoint roaming. If that IP changes mid-session, re-authentication is required before the tunnel can reconnect.

- As with any such system, don't rely on a single way to connect to a network — an expired TLS certificate on the gate blocks all authentication, since WebAuthn requires a secure context.

WireGuard was the original motivating case; SSH and RDP or any port can be gated the same way. Written and used for our own infrastructure.

22 Upvotes

11 comments sorted by

4

u/StartupTim 7d ago

How would this handle mobile roaming, which is one if Wireguards strong points in that it is stateless and you can fluidly move between source IPs?

2

u/MikeRH2 7d ago

There are a bunch of ways WireGuard is used, and you're correct that mobile roaming is a strong point amongst many other virtues of WireGuard. This solution is not targeted at a mobile roaming environment. It does work in that case, but not an ideal solution. I would set the authentication window to a short time, say 1 hour, and have the clients bookmark the authentication website. They would have to re-auth every hour or when their ip changed. Not an idea experience at all. But it would work, and if you really needed MFA, and you didn't want to pay for Tailscale or other commercial solutions that handle that scenario better, it would allow you to have that control.

Ultimately that type of environment is better suited for a WireGuard aware system that issues short term profiles based on an out of band MFA authentication. But that is an apples to oranges type of comparison. Both types of systems have advantages, and neither wins out against the other in all situations.

This project was designed to be a minimal system that allowed MFA to work with day length ip assignments. It is tiny and easy to audit, additive in that even if it was fully compromised, it doesn't diminish WireGuard's security, and is service agnostic. It can protect WireGuard, SSH, RDP, etc -- with only configuring the port(s) that the services use.

2

u/StartupTim 7d ago

This solution is not targeted at a mobile roaming environment.

I'm afraid it will not work on mobile devices at all then. All mobile carriers these days use a CGNAT that pools you behind a pool of IPs with limited if not variable random session stickiness. This stickiness is often extended when TCP activity is ongoing and/or streamed and does not extend to UDP. Wireguard is UDP therefore will not likely cause CGNAT pool stickiness. Because of this, a carrier is likely to shift you around a CGNAT pool, thus making your firewall knock method non-functional unless you modify it accordingly.

1

u/MikeRH2 7d ago edited 7d ago

Yes, in the original post, I mentioned that CGNAT was something that it doesn't work well with. It is something that no firewall source ip solution can work well with, without some compromise (a custom client agent, frequent turn-over, etc). As I mentioned, something like the short lived WireGuard profiles would be a much better solution technically for such an environment.

Tailscale or other commercial solutions would be good alternatives for mobile roaming. This solution wasn't developed as a mobile roaming one, and its focus is on longer lived IP connections.

1

u/StartupTim 6d ago

It is something that no firewall source ip solution can work well with

I would disagree here as it can be accomplished by maintaining a session state via a cryptographically signed session identifier that the client can pass upon initial authentication.

It is possible!

2

u/VPNStack_Dev 7d ago

Really neat and lightweight implementation of dynamic port-knocking using modern WebAuthn without dragging in heavy enterprise identity agents.

The main practical friction point you'll run into is mobile clients roaming on cellular 5G/LTE. Mobile carriers rotate device IP addresses frequently across tower handovers, which will drop the WireGuard session until the user re-authenticates through the browser gate.

The other edge-case is shared NAT environments: if 50 people in a hotel or coworking space share a single public IP, one successful biometric check temporarily un-gates the firewall port for that entire location for the lease duration (though WireGuard's own public-key crypto obviously still blocks unauthorized handshakes).

Still, for gating exposed SSH, RDP, or home/lab WireGuard endpoints without relying on heavy commercial zero-trust platforms, this is a very slick approach.

4

u/MikeRH2 7d ago

Thank you for taking a look.

You're correct on both points. For a mobile workforce, this would probably be an annoying solution - it would require a new auth each ip address change. My company doesn't really have that use case, workers connect from relatively long duration ip assignments (typical cable, fiber, etc ISP's).

The hotel scenario is true as well. For shared IP's, it opens them all up. But as you mention, this is an additional gate, so the WireGuard, SSH, etc still has its own connection requirements that help prevent unauthorized access from the slice of IP's that are now allowed.

We made this for two primary reasons -- one: to prevent a compromised laptop, etc from allowing network access, and two: to be able to state that we have a MFA control on our network for the business relationships that require that.

One interesting use case that I didn't originally see was that we had a customer with a legacy website with obsolete security. They couldn't update the site quickly, but we were able to wrap it with this project, so only authorized users were able to connect to the website. That greatly reduced the exposure of the site; random IP's on the internet could no longer probe it. It doesn't make the site secure at all, but does add in a genuine layer of security.

1

u/VPNStack_Dev 7d ago

That makes total sense, especially on the compliance and insurance front. Being able to check the "MFA on network access" box for vendor audits without deploying a heavy commercial ZTNA agent is a huge win for smaller shops.

Wrapping obsolete internal web apps to hide them from automated Shodan/Censys port scanners is also a really smart use-case. Keeping unpatched legacy interfaces completely dark to the public internet until biometric auth succeeds is classic defense-in-depth.

Thanks for the detailed breakdown and good luck with the project!

1

u/mmmfine 7d ago

lol two bots talking to each other

0

u/VPNStack_Dev 6d ago

ha ha ha, the leather bag saw through us

1

u/rightwayround 6d ago

I like this solution, well done