Skip to content

Instantly share code, notes, and snippets.

@xandout
Last active March 18, 2021 08:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xandout/af501e1b4ba0443f97beb50f6e90fa4d to your computer and use it in GitHub Desktop.
Save xandout/af501e1b4ba0443f97beb50f6e90fa4d to your computer and use it in GitHub Desktop.
OpenVPN TOTP Auth

Script to use TOTP tokens as passwords for OpenVPN auth

The user will be prompted for a username and password.

The username is the client username and the password is generated by their MFA app such as Authy or Google Authenticator.

OpenVPN server config

Add the following flags to your OpenVPN server config

script-security 2
auth-user-pass-verify /etc/openvpn/auth-otp.py via-file
username-as-common-name
auth-user-pass-optional # This is not required but it allows users without `auth-user-pass` in their client config to just use cert based auth

OpenVPN client config

Add the following flag to your OpenVPN client configs.

If you supplied auth-user-pass-optional in the server config, omitting the following flag from your client config will skip username/password auth.

auth-user-pass

Auth script

You need python3 and pyotp installed

pip3 install pyotp

#!/usr/bin/python3
import pyotp
import json
import sys
args = []
with open(sys.argv[1]) as f:
    args = f.readlines()
if len(args) == 0:
    print("No auth passed")
    sys.exit(0)
username = args[0].rstrip()
password = args[1].rstrip()
if username == "":
    sys.exit(0)
username = args[0]
password = args[1]
users = {}
with open('/etc/openvpn/users.json') as f:
  users = json.load(f)
if username in users:
    seed = users[username]
    totp = pyotp.TOTP(seed)
    if totp.verify(password):
        sys.exit(0)
    else:
        sys.exit(1)
else:
    print(f'User {username} not found')
    sys.exit(1)

JSON file containing usernames and TOTP seeds

{
    "mom": "3TIDFSZGDUNK3U6R",
    "dad": "LYHTI3TSZSQZTRPZ",
    "sister": "NPMQEPQ77ZVTSWGM",
    "brother": "OT72ZH4VJGFBNU2P",
    "other": "Y42QY2XR32IHEOWN"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment