wheelybird / openvpn-server-ldap-otp

A dockerised OpenVPN server using LDAP for authentication, with optional 2FA via Google Authenticator
MIT License
168 stars 72 forks source link

OpenVPN container

This will create an OpenVPN server. You can either use LDAP for authentication (with optional 2FA provided by Google Auth) or create a client certificate.
The container will automatically generate the certificates on the first run (using a 2048 bit key) which means that the initial run could take several minutes whilst keys are generated. The client configuration will be output in the logs. A volume is created for data persistence.

A note about compression

Compression is no longer enabled by default for backwards-compatibility. However the backwards-compatible option compress migrate has been added to the server configuration. This simply allows the server to ignore the client's request for compression. More information on why compression is disabled can be found on the OpenVPN website.

Configuration

Configuration is via environmental variables. Here's a list, along with the default value in brackets:

Mandatory settings:

Mandatory when USE_CLIENT_CERTIFICATE is false (the default):


Tip: The LDAP authentication module authenticates the user by searching for their LDAP entry and if it can't return that record authentication fails. Many LDAP servers don't allow anonymous binds/searches, so set LDAP_BIND_USER_DN (and LDAP_BIND_USER_PASS) as a user that has permission to search the directory.


Optional settings:

Data persistence

Important configuration and data is kept in the container's /etc/openvpn directory, so this path should be mounted as a volume or a bind mount. See the Docker documentation for more information. In the example below, we mount it as a bind mount to a directory on the host.

Launching the OpenVPN daemon container:

docker run \
           --name openvpn \
           --volume /path/on/host:/etc/openvpn \
           --detach=true \
           -p 1194:1194/udp \
           -e "OVPN_SERVER_CN=myserver.mycompany.com" \
           -e "LDAP_URI=ldap://ldap.mycompany.com" \
           -e "LDAP_BASE_DN=dc=mycompany,dc=com" \
           -e "LDAP_BIND_USER_DN=cn=example,dc=mycompany,dc=com" \
           -e "LDAP_BIND_USER_PASS=examplepass" \
           --cap-add=NET_ADMIN \
           wheelybird/openvpn-ldap-otp:v1.8

Using OTP

If you set ENABLE_OTP=true then OpenVPN will be configured to use two-factor authentication: you'll need your LDAP password and a passcode in order to connect. The passcode is provided by the Google Authenticator app. You'll need to download that from your app store.
You need to set up each user with 2FA. To do this you need to log into the host that's running the OpenVPN container and run
docker exec -ti openvpn add-otp-user <username> where username matches the LDAP username.
Give the generated URL and emergency codes to the user. To log in the user must append the code generated by Google Authenticator to their password. So if their password is verysecurepassword and the Authenticator code is 934567 then they need to enter verysecurepassword934567 at the password prompt.
The server-side OTP configuration is stored under /etc/openvpn, so ensure that's mounted as a volume otherwise the configuration will be lost when the container is restarted.
Note: OTP will only work with LDAP and can't be enabled if you're using the client certificate.

Using a client certificate

Set USE_CLIENT_CERTIFICATE=true if you want to use a client certificate instead of LDAP authentication. This will create a single client key and certificate. The server will be configured to accept multiple clients using the same certificate.
This is useful for testing out your VPN server and isn't intended as an especially secure VPN setup. If you want to use this for purposes other than development then you should read up on the downsides of sharing a single certificate amongst multiple clients.

Git repository

The Dockerfile and associated assets are available at https://github.com/wheelybird/openvpn-server-ldap-otp

Fail2ban administration

You can ban or un-ban IP addresses using the fail2ban-client command within the running container. For example, running docker exec -ti openvpn fail2ban-client set openvpn <banip|unbanip> <IPV4 Address>. You can view the ban logs by running docker exec -ti openvpn tail -50 /var/log/fail2ban.log.

Keepalive settings

The OpenVPN server is configured to send a keepalive ping every ten seconds and to restart the client connection if no reply has been received after a minute. If you set OVPN_IDLE_TIMEOUT then the server will kill the client connection after that many seconds, and the client will be configured to exit instead of restart after a minute of failed pings. For this reason your client can take up to a minute longer than the configured OVPN_IDLE_TIMEOUT timeout value before it exits.

LDAP authentication filters

You can restrict who can log into the VPN via LDAP filters. This container uses the libpam-ldapd and nslcd packages to authenticate against LDAP. The value of LDAP_FILTER will be appended to the user lookup. So if LDAP_FILTER is memberOf=cn=staff,cn=groups,cn=accounts,dc=example,dc=org then the filter that nslcd will generate is (&(uid=username)(memberOf=cn=staff,cn=groups,cn=accounts,dc=example,dc=org)). nslcd defaults to (objectClass=posixAccount), which will therefore create a filter like (&(uid=username)(objectClass=posixAccount)) if LDAP_FILTER is undefined.