Connect OpenVPN to the GitLab User DB

This blog post will discuss how OpenVPN can be connected to the GitLab user database. Data in a Git repository often require a lot of work, meaning a lot of energy, time and money. If you don’t want to rely on the GitLab login alone but instead want additional protection before it, one way to go about it is with OpenVPN. The idea is that access to GitLab will only be possible within the VPN.

In order for user administration to remain simple, the OpenVPN server is connected to the user database of GitLab.

Impact

One drawback that we’ll mention is that users must first have a password-protected account before they can connect to GitLab. If the users are managed by an administrator, the administrator only creates the accounts, not the passwords, since GitLab sends a password-reset link. But, this way, the user cannot log on to the system to change their password. This means there first has to be a separate step in which either the administrator sets the password (by using their own email address and then changing it later on) or the user can initially set their password via an existing VPN connection (e.g. using the credentials of an existing account).

Implementation

This involves working with a Debian 8, but any other current Linux distribution should behave very similarly.
First, GitLab is installed. This is already documented on the GitLab website (see GitLab-CE Install).
After that, an OpenVPN server is installed using apt-get install openvpn.

Create certificates

We create keys and certificates for a CA and for the VPN server. This should preferably be done in the directory in which the OpenVPN configuration (normally /etc/openvpn) is located.
First, we generate the private key and the certificate of the CA.

$ openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout ca.key -days 3650 -out ca.pem

After that, we create a private key and a certification signing request for the server and sign it with the CA.

$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout server.key -out server.csr  
$ openssl x509 -req -sha256 -CA ca.pem -CAkey ca.key -days 730 -CAcreateserial -CAserial ca.srl -in server.csr -out server.pem  

Make sure that the two private keys (.key-Files) can only be read by the required user (in this example, git).

OpenVPN server configuration

The OpenVPN server is created with the following configuration:

port 1194
proto udp
dev tun
ca ca.pem
cert server.pem
key server.key
dh dh4096.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user git
group git
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn-debug.log
verb 3
auth-user-pass-verify /etc/openvpn/auth-user.rb via-env
script-security 3
client-cert-not-required

The OpenVPN server will not expect any certificates from the client in the configuration described above, since the users are only supposed to log on with a password. The OpenVPN client verifies the server based on its certificate, which should be known to every client.
The verification of the username-password combination is taken care of using an external script. This script must reply 0 when a username-password combination is valid and 1 if not. Due to the gitlab rail runner, the script must be indicated in the OpenVPN configuration with an absolute path, since, otherwise, the runner will not be able to find the script.
The script looks like this:

#!/usr/bin/gitlab-rails runner

begin
    if ((User.find_by_username! ENV['username']).valid_password? ENV['password'])
        exit 0
    end
rescue
    exit 1
end

exit 1

DNS

In order for this configuration to work, there should be two DNS entries present. The first entry is needed so that the VPN client can connect to the server, and the second is used to connect to GitLab.
The DNS entry for the VPN server has the public IP address of the server stored in it. The DNS entry for GitLab indicates the IP address in the VPN tunnel. In the example above, this is the first IP address from the IP pool 10.8.0.1.

vpn.example.com.    IN    A    <Server Public IP>
git.example.com.    IN    A    10.8.0.1

OpenVPN user configuration (CLI-based)

The user can connect to the VPN server with the following configuration. To do so, in addition to the configuration, they also need to have the certificate of the CA ca.pem so that it can verify the server.

dev tun
remote vpn.example.com 1194
nobind
ca ca.pem
tls-client
persist-key
persist-tun
comp-lzo
cipher AES-256-CBC
pull
auth-user-pass
verb 3

OpenVPN user configuration (NetworkManager)

A new OpenVPN setup is created in the Network Manager.
The “identity” configuration should look as follows (Gateway, user name and password must be adapted and the certificate of the CA needs to be loaded as the CA certificate):

After that, press the “Advanced…” button to open the window for advanced options.
There, the “General” tab is set as follows (Use LZO data compression is important`):

and the “Security” tab is set as follows (adjust “Cipher”):

After that, press “OK” to close the Advanced Options window.

The IPv4 configuration should look as follows (“DNS” is switched off here; the most important thing is that IPv4 is switched on with “DHCP” and the routes are configured automatically):

And finally switch off the IPv6 configuration, as well:

This concludes all the configurations for VPN. After saving, a connection can be established to the OpenVPN server and then it is possible to surf the GitLab server within the VPN channel.