WireGuard 2FA Guide
WireGuard is a kernel-space VPN protocol — it has no concept of passwords or interactive authentication, only static public keys. That means there's no "built-in" way to require a 6-digit TOTP code to connect. But you can add 2FA at a higher layer in several ways. Here are the three that actually work in production.
Reality check:Pure WireGuard with TOTP at the protocol level isn't possible. Anything that "adds 2FA to WireGuard" gates either key issuance or session establishment — not the WireGuard handshake itself.
Approach 1: Web portal with TOTP gate (recommended)
Use a frontend portal (e.g. wg-portal or a custom one) that requires login + TOTP before issuing/rotating a user's WireGuard key. The portal manages wg0.conf peer entries.
Flow:
- User signs in with password + TOTP at the portal.
- Portal issues a short-lived WireGuard config (e.g. 8-hour key).
- User imports the config into their WireGuard client and connects.
- Key expires — to reconnect, user must pass 2FA again at the portal.
Approach 2: SSH jump host with PAM + TOTP
Don't expose WireGuard publicly. Put it behind an SSH bastion that requires libpam-google-authenticator for TOTP. Users SSH-tunnel to the bastion, then bring up WireGuard from there.
# /etc/pam.d/sshd
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactiveTrade-off: every user needs to google-authenticator to generate their TOTP secret, then scan with their authenticator app (Google Authenticator, 2FAA, etc.).
Approach 3: Tailscale or Cloudflare WARP (managed identity)
If you don't need raw WireGuard, mesh-VPN products built on top of WireGuard already integrate with identity providers that enforce 2FA: Tailscale via Google/Microsoft/Okta SSO + their 2FA policy, Cloudflare WARP / Zero Trust the same way.
You keep WireGuard's performance and get 2FA "for free" through the identity layer.
TOTP-side: generate the codes with 2FAA
Whichever approach you pick, the user-facing TOTP code can come from any standard authenticator. 2FAA runs in the browser — useful when users don't want yet another phone app, or when you need to generate codes from a script for testing.
Common questions
Can I add 2FA to the WireGuard handshake itself?
No. WireGuard uses static Noise-protocol keys — there's no interactive challenge to layer TOTP onto. 2FA has to live at the authorization layer above (web portal, jump host, IdP).
What about rotating keys based on TOTP?
That's effectively what Approach 1 does — the WireGuard private key the user holds expires, and TOTP gates re-issuance. It's the most practical "WireGuard 2FA" deployment pattern.
Does OpenVPN have built-in 2FA but WireGuard doesn't?
Yes. OpenVPN supports username/password + PAM, so a TOTP module plugs in naturally. WireGuard explicitly skipped this complexity for speed and simplicity, so you add 2FA outside the protocol.