Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Dockerfile and otp.md #514

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ LABEL maintainer="Kyle Manna <[email protected]>"

# 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/*

Expand Down
80 changes: 51 additions & 29 deletions docs/otp.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <user> 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 <user>
```

docker run -v $OVPN_DATA:/etc/openvpn --rm -it kylemanna/openvpn easyrsa build-client-full <user> 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 [email protected] user.

docker run -v $OVPN_DATA:/etc/openvpn --rm -t kylemanna/openvpn ovpn_otp_user <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 `<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.

```
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 [email protected] 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/[email protected]%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 `<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.
1. In the client configuration file `<user>.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/<user>.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/<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.
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

Expand All @@ -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 <user> authenticate
```
Expand Down