OpenVPN

Schon vor der NSA-Affäre und den Enthüllungen durch Edward Snwoden hatte ich mir vorgenommen, im Jahre 2013 mehr Fokus auf die Sicherheit (und auch Privacy) im Netz zu legen. Daher habe ich meine persönliche Sicherheitsinitiative 2013 ausgerufen.

Eines der Ziele meiner Initiative ist eine weitgehende Befreiung von Google und eine Abkehr von Facebook. Google Kalender, Google Suche, Google Reader und Google Mail sind bereits in Arbeit, werden aber in einem späteren Blogeintrag behandelt.

Als erstes wollte ich das Problem lösen, dass man sich in öffentlichen WLANs (Hotel, Starbucks etc.) weitgehend ungeschützt bewegt und immer darauf angewiesen ist, dass die Dienste, die man nutzt, sicher sind. Ein kleiner Fehler (z.B. HTTP statt HTTPS) und schon können andere mitlauschen. Tools wie Firesheep haben gezeigt, wie einfach man Nutzerdaten im WLAN stehlen kann. Hinzu kommt noch die Frage, welche Verbindungsdaten der benutzte Provider speichert.

Eine Lösung für das Problem besteht im Einsatz eines VPNs. Hierdurch kann man eine verschlüsselte Verbindung zu einem vertrauenswürdigen Netz aufbauen und sich so den Lauschern im WLAN entziehen. Ein weiterer Vorteil besteht darin, dass man zukünftigen Zensurphantasien der Provider vorbeugt, da der VPN-Traffic nicht erkennen lässt, welches Ziel die Verbindung hat.

Bezüglich der Privacy wäre ein VPN auch noch ein Vorteil, so man einen VPN-Server betreibt (oder nutzt), der nicht zum Nutzer zurückverfolgt werden kann. Diese Option habe ich aber vorläufig nicht verfolgt und einen vServer bei einem deutschen Provider angemietet. Die Privacy ist hier sogar deutlich schlechter als bei einem direkten Internetzugriff, da der Server über den DNS und denic-Eintrag zu mir zurückverfolgt werden kann, ohne eine Mithilfe des Providers.

Als Software für den VPN-Server habe ich mich für OpenVPN entschieden, weil es MacOS und Windows unterstützt und auch einen Android Client hat.

Eigener vServer

Der erste Schritt besteht also in der Beschaffung eines Servers mit direkter Internetanbindung bei einem Provider. Da für meine Pläne eine virtuelle Maschine vollkommen ausreicht, habe ich das billigste Angebot gewählt, das es für unter 10 EUR im Monat gibt. Auf der Maschine hat man vollen Root-Zugriff und kann somit alle administrativen Aufgaben ausführen.

Die Maschine läuft unter CentOS 6, einem freien Clone von Red Hat Enterprise Linux. Daran musste ich mich, als Ubuntu und SuSE-Nutzer, zwar erst etwas gewöhnen aber die Unterschiede sind nicht zu gross.

Installation der Binares

Für OpenVPN gibt es zwar fertige Pakete für CentOS aber der Paketmanager auf meiner Maschine kannte sie standardmäßig nicht, da sie zu den Extra Packages gehören. Also muss man zuerst die entsprechenden Pakete dem Paketmanager bekannt machen.

$ wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm
$ rpm -Uvh epel-release-6-8.noarch.rpm

Danach kann man die Pakete ganz normal über den Paketmanager yum installieren. Neben dem Paket für openvpn benötigt man noch openssl. Damit das generieren der Keys und Zertifikate einfacher geht, habe ich auch noch easy-rsa installiert.

$ yum install openvpn.x86_64 -y
$ yum install openssl.x86_64 -y
$ yum install easy-rsa.noarch -y

Konfiguration von OpenVPN

OpenVPN liefert bereits eine Beispielkonfiguration mit, die man nach den eigenen Bedürfnissen anpassen muss.

$ mkdir /etc/openvpn
$ cp /usr/share/doc/openvpn-2.3.1/sample/sample-config-files/server.conf /etc/openvpn/

Die Anpassungen an der Datei server.conf beschränken sich auf einige wenige Zeilen. Zum einen habe ich die Schlüssellänge auf 2048 Bit heraufgesetzt und zum anderen die DNS-Server eingetragen. Als DNS-Server habe ich die Google-Server verwendet ;-). Zusätzlich sollte der OpenVPN-Server noch seine Privilegien abgeben.

dh dh2048.pem
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
user nobody
group nobody

Die ganze Datei sieht dann wie folgt aus:

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DNS 8.8.4.4"
keepalive 10 120
comp-lzo
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3

Schlüssel erzeugen

easy-rsa konfigurieren

Als nächstes müssen die Schlüssel für VPN-Verbindung erzeugt werden. Hierzu verwende ich easy-rsa, einen Satz von Skripten, der die komplizierten OpenSSL-Optionen benutzerfreundlich verpackt.

$ mkdir -p /etc/openvpn/easy-rsa/key
$ cp -r /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
$ cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf

Damit easy-rsa funktionierten kann, muss man einige Umgebungsvariable in der Datei easy-rsa/vars setzen:

export KEY_SIZE=2048
export KEY_COUNTRY="DE"
export KEY_PROVINCE="BW"
export KEY_CITY="STADT"
export KEY_ORG="ORGANISATION"
export KEY_EMAIL="root@mail"
export KEY_CN=domain.de
export KEY_NAME=vpn_server
export KEY_OU=vpn_server

Certificate Authority

Auf dem Weg zu einem Satz von Schlüsseln benötigt man als erstes eine Certificate Authority (CA), damit die Schlüssel signiert werden können. Diese erzeugt man einfach selbst. Dass es sich hier nicht um eine echte, vertrauenswürdige Stelle handelt ist für den VPN-Zweck egal, da sowohl Client als auch Server von mir betrieben werden und auf dem Client das Zertifikat der CA manuell installiert wird. Ein Man-in-the-middle-Angriff würde voraussetzen, dass der Angreifer das Zertifikat auf meinem Client austauscht oder den privaten Schlüssel meiner CA stiehlt. Beides ist hinreichend unwahrscheinlich.

$ cd /etc/openvpn/easy-rsa
$ source ./vars
$ ./clean-all
$ ./build-ca

Server-Schlüssel

Jetzt können die Schlüssel für den Server erstellt werden und von der CA beglaubigt. easy-rsa macht das in einem einzigen Schritt:

$ cd /etc/openvpn/easy-rsa
$ ./build-key-server server

Für die Erzeugung der Sitzungsschlüssel verwendet OpenVPN einen Diffie-Hellman-Schlüsselaustausch (DH), sodass die entsprechenden Parameter berechnet werden müssen. Die Begründung für die Verwendung von DH ist die deutlich höhere Performance verglichen mit RSA. Dafür dauert das Erzeugen der DH-Parameter extrem lange, man muss also für den folgenden Schritt einiges an Geduld mitbringen, da er einige Minuten dauert.

$ cd /etc/openvpn/easy-rsa
$ ./build-dh

Die Schlüssel werden zwar von easy-rsa erzeugt, nicht aber in die entsprechenden Verzeichnisse kopiert. Daher muss man sie noch von Hand umkopieren:

$ cp /etc/openvpn/easy-rsa/keys/dh2048.pem /etc/openvpn/
$ cp /etc/openvpn/easy-rsa/keys/ca.crt /etc/openvpn/
$ cp /etc/openvpn/easy-rsa/keys/server.crt /etc/openvpn/server.crt
$ cp /etc/openvpn/easy-rsa/keys/server.key /etc/openvpn/server.key

Client-Schlüssel

Damit sich der Client später gegenüber dem Server authentifizieren kann, benötigt er ebenfalls einen Schlüssel.

$ cd /etc/openvpn/easy-rsa
$ ./build-key client

Die Client-Schlüssel werden später in die Client-Konfigurationsdateien aufgenommen.

Client-Konfiguration erzeugen

Auf dem Client muss eine Datei installiert werden, die die Verbindungsinformationen des Servers enthält. Man kann diese Datei im Texteditor erstellen und die Schlüssel hineinkopieren. Einfacher geht es aber mit einem kleinen Skript, das diese Aufgabe erledigt.

#!/bin/sh

FILE=server.ovpn
IP=1.1.1.1   # IP des Servers

echo "client"      	      	>> $FILE
echo "dev tun"				>> $FILE
echo "proto udp"			>> $FILE
echo "remote $IP 1194"		>> $FILE
echo "resolv-retry infinite">> $FILE
echo "nobind"				>> $FILE
echo "persist-key"			>> $FILE
echo "persist-tun"			>> $FILE
echo "comp-lzo"				>> $FILE
echo "verb 3"				>> $FILE
echo "<ca>"					>> $FILE
cat /etc/openvpn/ca.crt     >> $FILE
echo "</ca>"				>> $FILE
echo "<cert>"				>> $FILE
cat /etc/openvpn/easy-rsa/keys/client.crt >> $FILE
echo "</cert>"				>> $FILE
echo "<key>"				>> $FILE
cat /etc/openvpn/easy-rsa/keys/client.key >> $FILE
echo "</key>"				>> $FILE

Die Konfigurationsdatei muss man auf den Clients installieren.

Clients

Für Windows gibt es einen GUI-Client direkt bei OpenVPN, für MacOS setze ich den Kommandozeilen-Client und die zusätzliche grafische Oberfläche Tunnelblick ein.

Bei Windows muss die oben erstellte Konfigurationsdatei in den config-Ordner im Programmverzeichnis kopiert werden. Tunnelblick führt einen schrittweise durch die Konfiguration.

Routing

Mit dem bisher beschriebenen Setup kann man eine VPN-Verbindung zum Server aufbauen. Allerdings enden die Pakete auf dem Server, weil er sie nicht weiterleitet. Daher muss man auf dem Server noch NAT aktivieren.

Als erstes muss man das IP-Forwarding im Kernel über die Datei /etc/sysctl.conf einschalten. Hierzu fügt man die folgende Zeile ein bzw. ändert sie:

net.ipv4.ip_forward = 1

Danach muss die Konfiguration dem Kernel bekannt gemacht werden:

$ sysctl -p

Als letztes sind noch das Routing der Pakete eingeschaltet werden (1.1.1.1 ist durch die IP-Adresse des Servers zu ersetzen):

$ iptables -t nat -A POSTROUTING -o venet0 -s 10.8.0.0/24 -j SNAT --to 1.1.1.1
$ service iptables save

Server starten

Der OpenVPN-Server kann jetzt gestartet werden:

$ service openvpn start

Damit er bei jedem Systemstart wieder erneut gestartet wird, registriert man ihn als Systemdienst.

$ chkconfig --level 35 openvpn on

Fertig. Der VPN-Server läuft.