77 lines
4.0 KiB
Markdown
77 lines
4.0 KiB
Markdown
# Using two factor authentication for users
|
|
|
|
Instead of relying on complex passwords for client certificates (that usually get written somewhere) this image
|
|
provides support for two factor authentication with OTP devices.
|
|
|
|
The most common app that provides OTP generation is Google Authenticator ([iOS](https://itunes.apple.com/it/app/google-authenticator/id388497605?mt=8) and
|
|
[Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2&hl=it)) you can download it
|
|
and use this image to generate user configuration.
|
|
|
|
## Usage
|
|
|
|
In order to enable two factor authentication the following steps are required.
|
|
|
|
* Choose a more secure [cipher](https://community.openvpn.net/openvpn/wiki/SWEET32) to use because since [OpenVPN 2.3.13](https://community.openvpn.net/openvpn/wiki/ChangesInOpenvpn23#OpenVPN2.3.13) the default openvpn cipher BF-CBC will cause a renegotiated connection every 64 MB of data
|
|
|
|
* Generate server configuration with `-2` and `-C $CIPHER` options
|
|
|
|
docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -2 -C $CIPHER
|
|
|
|
* Generate your client certificate (possibly without a password since you're using OTP)
|
|
|
|
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full <user> nopass
|
|
|
|
* Generate authentication configuration for your client. -t is needed to show QR code, -i is optional for interactive usage
|
|
|
|
docker run -v $OVPN_DATA:/etc/openvpn --rm -t kylemanna/openvpn ovpn_otp_user <user>
|
|
|
|
The last step will generate OTP configuration for the provided user with the following options
|
|
|
|
```
|
|
google-authenticator --time-based --disallow-reuse --force --rate-limit=3 --rate-time=30 --window-size=3 \
|
|
-l "${1}@${OVPN_CN}" -s /etc/openvpn/otp/${1}.google_authenticator
|
|
```
|
|
|
|
It will also show a shell QR code in terminal you can scan with the Google Authenticator application. It also provides
|
|
a link to a google chart url that will display a QR code for the authentication.
|
|
|
|
**Do not share QR code (or generated url) with anyone but final user, that is your second factor for authentication
|
|
that is used to generate OTP codes**
|
|
|
|
Here's an example QR code generated for an hypotetical user@example.com user.
|
|
|
|
![Example QR Code](https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@example.com%3Fsecret%3DKEYZ66YEXMXDHPH5)
|
|
|
|
Generate client configuration for `<user>` and import it in OpenVPN client. On connection it will prompt for user and password.
|
|
Enter your username and a 6 digit code generated by Authenticator app and you're logged in.
|
|
|
|
## TL;DR
|
|
|
|
Under the hood this configuration will setup an `openvpn` PAM service configuration (`/etc/pam.d/openvpn`)
|
|
that relies on the awesome [Google Authenticator PAM module](https://github.com/google/google-authenticator).
|
|
In this configuration the `auth` part of PAM flow is managed by OTP codes and the `account` part is not enforced
|
|
because you're likely dealing with virtual users and you do not want to create a system account for every VPN user.
|
|
|
|
`ovpn_otp_user` script will store OTP credentials under `/etc/openvpn/otp/<user>.google_authentication`. In this
|
|
way when you take a backup OTP users are included as well.
|
|
|
|
Finally it will enable the openvpn plugin `openvpn-plugin-auth-pam.so` in server configuration and append the
|
|
`auth-user-pass` directive in client configuration.
|
|
|
|
## Debug
|
|
|
|
If something is not working you can verify your PAM setup with these commands
|
|
|
|
```
|
|
# Start a shell in container
|
|
docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn bash
|
|
# Then in container you have pamtester utility already installed
|
|
which pamtester
|
|
# To check authentication use this command that will prompt for a valid code from Authenticator APP
|
|
pamtester -v openvpn <user> authenticate
|
|
```
|
|
|
|
In the last command `<user>` should be replaced by the exact string you used in the ovpn_otp_user command.
|
|
|
|
If you configured everything correctly you should get authenticated by entering a OTP code from the app.
|