diff --git a/Dockerfile b/Dockerfile index a85cb24b..5f8d0ea8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ LABEL maintainer="Kyle Manna " # Testing: pamtester RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories && \ - apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester && \ + apk add --update openvpn iptables bash easy-rsa openvpn-auth-pam google-authenticator pamtester libqrencode && \ ln -s /usr/share/easy-rsa/easyrsa /usr/local/bin && \ rm -rf /tmp/* /var/tmp/* /var/cache/apk/* /var/cache/distfiles/* diff --git a/docs/otp.md b/docs/otp.md index edbd1565..4d559ff3 100644 --- a/docs/otp.md +++ b/docs/otp.md @@ -7,56 +7,76 @@ The most common app that provides OTP generation is Google Authenticator ([iOS]( [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 +## Tutorial for New Installs 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 +1. Generate server configuration with the `-2` option. It's no longer necessary to supply the cipher option because OpenVPN 2.4 [uses AES-256-GCM by default](https://community.openvpn.net/openvpn/wiki/SWEET32). + ```bash + docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -2 + ``` -* Generate server configuration with `-2` and `-C $CIPHER` options +1. Init the EasyRSA PKI. + ```bash + docker run -v $PWD/data:/etc/openvpn --rm -it kylemanna/openvpn ovpn_initpki + ``` - docker run -v $OVPN_DATA:/etc/openvpn --rm kylemanna/openvpn ovpn_genconfig -u udp://vpn.example.com -2 -C $CIPHER +1. Generate your client certificate (possibly without a password since you're using OTP) + ```bash + docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full nopass + ``` -* Generate your client certificate (possibly without a password since you're using OTP) +1. Generate authentication configuration for your client. `-t` is needed to display the QR code, `-i` is also needed as `google_authenticator` prompts you to enter an OTP token to test. The QR code can be scanned with the Google Authenticator application. It also provides a link to a Google chart url that will display a QR code for the authentication. + ```bash + docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn ovpn_otp_user + ``` - docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full nopass +**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** -* Generate authentication configuration for your client. -t is needed to show QR code, -i is optional for interactive usage +Here's an example QR code generated for an hypotetical user@example.com user. - docker run -v $OVPN_DATA:/etc/openvpn --rm -t kylemanna/openvpn ovpn_otp_user +![Example QR Code](https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@example.com%3Fsecret%3DKEYZ66YEXMXDHPH5) -The last step will generate OTP configuration for the provided user with the following options +Generate client configuration for `` 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. -``` -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 -``` +## Tutorial for Existing Installs -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. +If you have an existing installation with customised config, follow this tutorial instead. -**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** +1. In `openvpn.conf`, add the config to enable 2FA. + ```bash + # Enable OTP+PAM for user authentication, add: + plugin /usr/lib/openvpn/plugins/openvpn-plugin-auth-pam.so openvpn + reneg-sec 0 + ``` -Here's an example QR code generated for an hypotetical user@example.com user. +1. In `ovpn_env.sh`, add the environment variable to enable 2FA + ```bash + declare -x OVPN_OTP_AUTH=1 + ``` -![Example QR Code](https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/user@example.com%3Fsecret%3DKEYZ66YEXMXDHPH5) +1. Restart the container for the new config to take effect. This step depends on your setup (ie. if it's docker or docker-compose). -Generate client configuration for `` 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. +1. In the client configuration file `.ovpn`, add the config to the end of the file. + ```bash + auth-user-pass + auth-nocache + reneg-sec 0 + ``` + +1. Alternatively, you could regenerate the client config if yours doesn't have custom fields added. + ```bash + docker run -v $OVPN_DATA:/etc/openvpn --log-driver=none --rm kylemanna/openvpn ovpn_getclient CLIENTNAME > CLIENTNAME.ovpn + ``` ## 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. +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/.google_authentication`. In this - way when you take a backup OTP users are included as well. +`ovpn_otp_user` script will store OTP credentials under `/etc/openvpn/otp/.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. +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 @@ -65,8 +85,10 @@ 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 authenticate ```