OpenVPN mit Pre-Shared Key

Wie führt man mit OpenVPN am einfachsten zwei lokale bzw. private Netzwerke zusammen, die allerdings nur über das Internet, also ein öffentliches Netz, miteinander verbunden werden können? Kann man dafür bei OpenVPN einen Pre-Shared Key einsetzen oder muss ein Zertifikat verwendet werden?

Netzwerk mit zwei Standorten, die lediglich über das Internet miteinander verbunden sind, aber ein gemeinsames Netzwerk bilden sollenIn vielen Fällen bzw. Situationen geht es einfach nur darum, zwei oder mehrere private Netzwerke zu einem größeren Netz zusammenzuführen, ohne dabei komplizierte Konfigurationen vornehmen zu müssen. Trifft das auf der linken Seite zu sehende Schema auf Ihre Situation zu, dann ist diese Anleitung genau richtig für Sie. Der hierbei relevante Sicherheitsaspekt wird durch die Verschlüsselung abgedeckt, die von OpenVPN bereitgestellt wird bzw. durch OpenVPN genutzt werden kann. Da es sich bei diesem VPN um eine einzige Punkt-zu-Punkt-Verbindung handelt, eignet sich ein Pre-Shared Key, welcher die Einrichtung erleichtert und die Handhabung von Zertifikaten vermeidet.

Für diese Anleitung gehe ich davon aus, dass die im Netzwerk-Diagramm dargestellte Situation gegeben ist und das Netzwerk des Standorts B (10.0.0.0/24) über dessen Router (10.0.0.1) mit dem Router A (192.168.0.1) verbunden werden soll, um auf das Netzwerk des Standorts A (192.168.0.0/24) - und umgekehrt - zugreifen zu können. Erforderlich ist, dass beide Router bereits eine Internet-Verbindung haben und zudem das Standard-Gateway des jeweiligen Netzwerkes sind, soll das ganze später ohne manuell konfigurierte IP-Routen funktionieren. Für das leichtere Verständnis beim Lesen wurden absichtlich zwei sehr unterschiedliche Netzbereiche aus den privaten IP-Adressbereichen gewählt.

Als erstes muss die VPN-Software OpenVPN auf beiden Routern installiert werden. Bei einer aktuellen Version der Linux-Distribution Fedora bzw. bei Red Hat Enterprise Linux 4 und 5 bzw. CentOS 4 und 5 oder einer anderen auf Fedora basierenden Distribution funktioniert dies mittels yum sehr einfach. Allerdings muss bei RHEL bzw. CentOS das Repository EPEL in yum eingebunden und aktiviert sein:

tux:~ # yum install -y openvpn

Sofern Sie sich entscheiden sollten, OpenVPN selbst zu kompilieren, verwenden Sie bitte niemals die Version 1.x der Bibliothek lzo, sondern immer die Version 2.x, da in der älteren Version diverse Fehler enthalten sind, die zu Speicherzugriffsfehlern und Abstürzen des OpenVPNs führen - ich spreche hier leider aus praktischer Erfahrung.

Die nachfolgende Beispielkonfiguration basiert, wie bereits oben angedeutet, auf einem symmetrischen Verschlüsselungsverfahren. Hierbei wird ein gemeinsamer Schlüssel erzeugt, den beide Router erhalten müssen. Der gesamte Netzwerkverkehr, der über den Tunnel fließt, wird dann mit genau diesem Schlüssel verschlüsselt bzw. geschützt. Das ganze bedeutet dann aber auch, dass jeder, der den Schlüssel zusätzlich (vielleicht sogar ungewollt) besitzt, den gesamten Traffic ebenfalls entschlüsseln kann. Und diesen Schlüssel können Sie mit nachfolgendem Befehl erzeugen; allerdings müssen beide Router den gleichen Schlüssel besitzen, damit später eine VPN-Verbindung aufgebaut werden kann:

tux:~ # openvpn --genkey --secret /etc/openvpn/static.key

Da OpenVPN bzw. VPN allgemein auf das Client-Server-Prinzip setzt, muss einer der beiden Router als VPN-Server agieren, während der andere als VPN-Client arbeitet. In meinem oben dargestellten Fall soll der Router A als Server fungieren und Router B wird der VPN-Client dazu sein. Es gibt grundsätzlich keine Regel, welcher der beiden Router welche Position einnehmen sollte, jedoch würde ich empfehlen, den Router des "Hauptnetzwerkes" als Server zu verwenden. Da die Konfigurationsdateien für VPN-Server und -Client bei OpenVPN sehr ähnlich aussehen, sollte man besonders aufpassen, dass man diese nicht versehentlich verwechselt. Die Konfigurationsdatei "/etc/openvpn/gemeinsam.conf" auf dem Router A sollte nachfolgendes enthalten.

# Netzwerk-Interface, das lokal für die Verbindung des VPNs genutzt wird
dev tun0

# Port, der eingehend für die VPN-Verbindung von Router B aus genutzt wird
port 1194

# Tunnel-IP-Adresse lokal und IP-Adresse des Endpunkts (Router B)
ifconfig 172.16.0.1 172.16.0.2

# Welche Netze sind auf der Gegenseite (Router B) verfügbar und sollen genutzt werden?
route 10.0.0.0 255.255.255.0

# Absoluter Pfad zum gemeinsamen Schlüssel
secret /etc/openvpn/static.key

# Komprimierung durch die Bibliothek lzo aktivieren (bei langsamen Leitungen interessant)
comp-lzo yes

# Ausführlichkeit der Logmeldungen auf ein normales, aber hilfreiches Niveau einstellen
verb 3

# Ändert die Fragmentierung der Pakete, um UDP-Pakete > 1200 Bytes zu verhindern;
# diese Option wird häufig zur Umgehung von Problemen mit der MTU-Erkennung eingesetzt
#fragment 1200
#mssfix 1200

# Sorgt jede 30 Sekunden für einen internen Ping zum Test der Verbindung
ping 30

# Neustart der OpenVPN-Verbindung, wenn der interne Ping für 60 Sekunden erfolglos bleibt
ping-restart 60

# Ausführung auf standardmäßig verfügbare Programme wie ifconfig, ip, route beschränken
script-security 1

Ist das geschehen, so muss auf dem Router B nachfolgender Inhalt in die Datei "/etc/openvpn/gemeinsam.conf" eingetragen werden. Und denken Sie bitte unbedingt daran, den Wert der Option "remote" auf die öffentliche IP-Adresse bzw. auf den Hostname von Router A abzuändern, sonst funktioniert der Verbindungsaufbau des VPN-Clients zum VPN-Server nicht:

# Netzwerk-Interface, das lokal für die Verbindung des VPNs genutzt wird
dev tun0

# Port, der bei der nachfolgenden Einstellung als Zielport auf Router A genutzt wird
port 1194

# Öffentliche IP-Adresse oder Name des Routers A, der als Ziel (VPN-Server) verwendet wird
remote vpn.standort-a.tld

# Tunnel-IP-Adresse lokal und IP-Adresse des Endpunkts (Router A)
ifconfig 172.16.0.2 172.16.0.1

# Welche Netze sind auf der Gegenseite (Router A) verfügbar und sollen genutzt werden?
route 192.168.0.0 255.255.255.0

# Absoluter Pfad zum gemeinsamen Schlüssel
secret /etc/openvpn/static.key

# Komprimierung durch die Bibliothek lzo aktivieren (bei langsamen Leitungen interessant)
comp-lzo yes

# Ausführlichkeit der Logmeldungen auf ein normales, aber hilfreiches Niveau einstellen
verb 3

# Ändert die Fragmentierung der Pakete, um UDP-Pakete > 1200 Bytes zu verhindern;
# diese Option wird häufig zur Umgehung von Problemen mit der MTU-Erkennung eingesetzt
#fragment 1200
#mssfix 1200

# Sorgt jede 30 Sekunden für einen internen Ping zum Test der Verbindung
ping 30

# Neustart der OpenVPN-Verbindung, wenn der interne Ping für 60 Sekunden erfolglos bleibt
ping-restart 60

# Ausführung auf standardmäßig verfügbare Programme wie ifconfig, ip, route beschränken
script-security 1

Sollte es sich um ein Betriebssystem mit aktiviertem SELinux und einem abweichenden Port bzw. Protokoll (also nicht den standardmäßigen Port 1194 per UDP) handeln, so muss noch die SELinux-Richtlinie entsprechend angepasst werden:

tux:~ # semanage port -a -t openvpn_port_t -p udp 1195
tux:~ # 

Anschließend muss man den Dienst auf beiden Routern aktivieren, damit dieser auch nach dem nächsten Neustart der Server wieder mitgestartet wird:

tux:~ # chkconfig openvpn on
tux:~ # 

Und um nicht bis zum nächsten Neustart warten zu müssen, aktiviert man OpenVPN am besten sofort auf beiden Servern:

tux:~ # service openvpn start
Starting openvpn:                                          [  OK  ]
tux:~ # 

Nun sollte es einige Sekunden dauern, bis die VPN-Verbindung aufgebaut ist. Dann existiert auf beiden Servern das tun0-Interface und im Systemlog in /var/log/messages sollten sich Nachrichten über den Verbindungsaufbau finden, die IP-Netze sollten gegenseitig erreichbar sein - sofern das Firewalling auf den Routern dies nicht verhindert. Da sich das Firewalling bei VPN mit Routing jedoch nicht anders als in "normalen" Netzwerken verhält, gehe ich hierauf nicht gesondert ein. Gibt es Probleme bei der Erreichbarkeit über IP, obwohl die VPN-Verbindung erfolgreich aufgebaut worden ist, so sollte die Firewall als allererste Ursache sicher ausgeschlossen werden können. Zudem finden sich im Systemlog in /var/log/messages auch bei einem Fehler diverse Informationen, welche, insbesondere bei einem Nichtzustandekommen des Verbindungsaufbaus, genau geprüft werden sollten und normalerweise auch den Grund finden lassen...