- python3
- pip packages python_freeipa and pyotp
- openvpn-plugin-auth-script.so
- correct time on server with script
- a pre-created user in freeipa, added to the
freeipa_group_required
group, as well as an added token, via OTP Tokens -> add -> TOTP token from the user - user with admin rights or read user secrets
Add to you server openvpn.conf:
client-cert-not-required
username-as-common-name
plugin /location/to/you/openvpn-plugin-auth-script.so /location/to/you/ovpn_2fa_auth_sript.py
setenv freeipa_group_required vpn_it;
setenv freeipa_replica freeipa-replica.you_domain.com;
setenv freeipa_admin ovpn-2fa-service;
setenv freeipa_admin_password SUPERPASSWORD;
Add to you client openvpn.conf:
static-challenge "Enter 2fa PIN" 1
- Openvpn transmits
username
,password
,auth_control_file
through environment variables, wherepassword
is a string likeSCRV1:base64password:base64pin
,auth_control_file
is a tmp file monitored by the ovpn daemon, we must write 1 to it in case of successful authorization, 0 in case of failure. It is also necessary that our script completes without errors - Script decodes payload from ENV
password
- The script binds the user with the transferred credentials
- The script checks if a user is in a specific group
- The script checks the OTP pin code of the user under the service account
- If all conditions are successful, writes 1 to
auth_control_file
, otherwise writes 0 - The script exits with code 0 if there were no errors
The script writes logs to /var/log/ovpn_2fa_auth_script.log
This script was also tested with pfsense 2.7.2
Setenv via openvpn is used so that one script can be used by many openvpn servers at the same time, for example, checking different freepa groups for a user