OpenVPN an GitLab User DB anhängen

In diesem Blog Post soll es darum gehen, wie ein GitLab hinter einem OpenVPN aufgebaut werden kann. Oft steckt in Daten, welche in einem Git-Repository sind, viel Arbeit und somit auch viel Energie, Zeit und Geld. Wer sich nicht nur auf das Login von GitLab verlassen sondern einen weiteren Schutz davor haben will, kann dies z.B. mit OpenVPN lösen. Die Idee ist, dass der Zugriff auf das GitLab nur noch innerhalb des VPN möglich ist.
Damit die User Administration weiterhin simpel bleibt, wird dabei der OpenVPN Server an die User Datenbank von GitLab angebunden.

Impact

Als negativer Punkt sei hier erwähnt, dass User zuerst einen Account mit Passwort haben müssen, bevor sie auf das GitLab verbinden können. Werden die User von einem Administrator verwaltet, erstellt dieser nur die Accounts, jedoch nicht die Passwörter, da GitLab einen Passwort-Reset-Link versendet. Dadurch kann sich der User aber nicht am System anmelden um sein Passwort zu setzen. Dies bedeutet, es muss in einem ersten Schritt zuerst entweder das Passwort durch den Administrator gesetzt werden (indem er die eigene E-Mail Adresse verwendet und später wechselt) oder der User kann über eine schon bestehende VPN Verbindung (z.B. mit Hilfe der Credentials eines schon vorhandenen Accounts) sein Passwort initial setzen.

Realisierung

Hier wird mit einem Debian 8 gearbeitet, jede andere aktuelle Linux Distribution sollte sich aber sehr ähnlich verhalten.
Zuerst wird ein GitLab installiert, dies ist auf der Webseite von GitLab schon dokumentiert (siehe GitLab-CE Install).
Danach wird ein OpenVPN Server mittels apt-get install openvpn installiert.

Zertifikate erstellen

Wir erstellen Keys und Zertifikate für eine CA und für den VPN Server. Dies geschieht vorzugsweise direkt im Verzeichnis, in welchem die OpenVPN Konfiguration (standardmässig /etc/openvpn) liegt.
Zuerst generieren wir den privaten Key und das Zertifikat der CA.

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

Danach erstellen wir einen privaten Key und ein Certificate Signing Request für den Server und signieren diesen mit der 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  

Es sollte darauf geachtet werden, dass die beiden privaten Keys (.key-Files) nur durch den benötigten User (in diesem Beispiel git) gelesen werden können.

OpenVPN Server Konfiguration

Der OpenVPN Server wird mit folgender Konfiugration erstellt:

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

Der OpenVPN Server wird in der oben beschriebenen Konfiguration vom Client keine Zertifikate erwarten, da die User sich nur per Passwort anmelden sollen.
Der OpenVPN Client verifiziert den Server anhand dessen Zertifikat, welches jedem Client bekannt sein sollte.
Die Verifizierung der Usernamen-Passwort-Kombination wird mithilfe eines externen Scripts gelöst. Dieses Script muss bei gültiger Username-Passwort-Kombination 0, und ansonsten 1, zurückgeben. Aufgrund des gitlab-rails Runner muss das Script in der OpenVPN Konfiguration zwingend mit absolutem Pfad angegeben werden, da der Runner ansonsten das Script nicht findet.
Das Script sieht wie folgt aus:

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

Damit diese Konfiguration funktioniert, sollten zwei DNS Einträge vorhanden sein. Der erste Eintrag wird gebraucht, damit der VPN Client zum Server verbinden kann und der Zweite wird genutzt, um auf das GitLab zu verbinden.
Der DNS Eintrag für den VPN Server hat die Public IP Adresse des Servers hinterlegt. Der DNS Eintrag für GitLab zeigt auf die IP Adresse im VPN Tunnel, im obigen Beispiel ist dies die erste IP Adresse aus dem IP Pool 10.8.0.1.

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

OpenVPN Benutzer Konfiguration (CLI basiert)

Der User kann mit folgender Konfiguration zum VPN Server verbinden. Er muss dafür nebst der Konfiguration auch das Zertifikat der CA ca.pem besitzen, damit er den Server verifizieren kann.

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 Benutzer Konfiguration (NetworkManager)

Es wird ein neues OpenVPN Setup im Network Manager angelegt.
Die „Identity“ Konfiguration sollte dabei wie folgt aussehen (Gateway, Username und Password müssen dabei angepasst und als CA Certificate muss das Zertifikat der CA geladen werden):

Danach wird mit dem Button „Advanced…“ das Fenster für die erweiterten Optionen geöffnet.
Dort wird der Reiter „General“ wie folgt eingestellt (wichtig ist Use LZO data compression):

und der Reiter „Security“ folgendermassen („Cipher“ anpassen):

Danach wird das Advanced Options Fenster mit „OK“ wieder geschlossen.

Die IPv4 Konfiguration sollte wie folgt aussehen („DNS“ wird hier ausgeschalten, wichtig ist vor allem, dass IPv4 mit „DHCP“ eingeschalten ist und die Routes automatisch konfiguriert werden):

Und schliesslich auch noch die IPv6 Konfiguration ausschalten:

Damit sind alle Konfigurationen für VPN gemacht, nach dem Speichern, kann eine Verbindung zum OpenVPN Server aufgebaut und danach innerhalb vom VPN Kanal der GitLab Server angesurft werden.