OpenVPN ist eine Software zur Erstellung von virtuellen privaten Netzwerken (VPN).
Mit OpenVPN ist es möglich sichere Netzwerkverbindungen über unsichere Netzwerke (z.B. das Internet oder öffentliche WLANs) aufzubauen. Verwendet wird hierfür das Verschlüsselungsprotokoll SSL/TLS.
Zur Authentifizierung der einzelnen Clients werden Zertifikate und Schlüssel verwendet, wobei jeder Client sein eigenes Zertifikat und seinen eigenen privaten Schlüssel bekommt. Zur einfachen Erstellung und der Verwaltung der Zertifikate und Schlüssel verwenden wir EasyRSA.
OpenVPN und EasyRSA installieren
Als erstes installieren wir OpenVPN und EasyRSA. Da die in den Paketquellen enthaltene Version von EasyRSA veraltet ist, laden wir die aktuelle Version von den EasyRSA Releases auf GitHub und entpacken diese.
sudo apt install openvpn
cd /etc/openvpn
sudo wget https://github.com/OpenVPN/easy-rsa/releases/download/3.0.1/EasyRSA-3.0.1.tgz
sudo tar -xf EasyRSA-3.0.1.tgz
sudo mv EasyRSA-3.0.1 easyrsa3
Zur Erhöhung der Sicherheit legen wir auf unserem zusätzlich einen neuen Benutzer und eine neue Gruppe für den OpenVPN-Server an. Diese werden dem Server später über die Config mitgeteilt.
sudo addgroup --system --no-create-home --disabled-login --group openvpn
sudo adduser --system --no-create-home --disabled-login --ingroup openvpn openvpn
Zertifizierungsstelle (CA) erstellen
Zur Verwaltung der Server- und Client-Zertifikate benötigen wir eine Zertifizierungsstelle, oder auch CA (certificate authority) genannt. Diese können wir dank EasyRSA sehr einfach erstellen und verwalten.
cd /etc/openvpn/easyrsa3
sudo ./easyrsa init-pki
sudo ./easyrsa build-ca
Dies erstellt für unseren OpenVPN-Server eine neue Public-Key-Infrastruktur (pki) und erzeugt in dieser eine neue CA. Dabei muss für die CA ein Passwort angegeben werden. Dieses Passwort sollte sicher irgendwo aufbewahrt werden, da es für jedes Signieren eines Server- oder Client-Zertifikates benötigt wird.
Jeder Client benötigt später zusätzlich zu seinen eigenen Zertifikaten das öffentliche Zertifikat der CA (/etc/openvpn/easyrsa/pki/ca.crt
).
Zusätzlich erstellen wir noch die CRL-Datei für den Server, welche für widerrufene Zertifikate benötigt wird.
sudo ./easyrsa gen-crl
Damit der Server, welcher später unter dem Nutzer und der Gruppe “openvpn” läuft, auch auf die CRL-Datei zugreifen kann, ändern wir den Eigentümer des Verzeichnisses /etc/openvpn/easyrsa3
auf root:openvpn
und passen die Rechte an, dass die Gruppe Lesezugriff auf die CRL-Datei hat.
sudo chown -R root:openvpn /etc/openvpn/easyrsa3
sudo chmod g+x /etc/openvpn/easyrsa3/pki
sudo chmod g+r /etc/openvpn/easyrsa3/pki/crl.pem
Server-Zertifikat erstellen
Der Server benötigt ein eigenes Zertifikat und zusätzlich die Diffie-Hellman-Parameter. Diese sind nötig, um kryptografische Schlüssel sicher über unsichere Kanäle auszuhandeln.
sudo ./easyrsa gen-dh
sudo ./easyrsa build-server-full server nopass
Dabei muss zum Signieren des Server-Zertifikates das Passwort des CA-Zertifikates eingegeben werden.
Zudem ist es ratsam TLS-Auth zu verwenden, was jedem Paket bei der Schlüsselaushandlung zwischen Server und Client eine spezielle Signatur hinzufügt. Hierfür erstellen wir einen TA-Schlüssel.
sudo openvpn --genkey --secret ./pki/ta.key
Dieser TA-Schlüssel muss später, genauso wie das CA-Zertifikat, jedem Client bekannt sein.
Server-Config
Im Folgenden eine Beispiel-Config für den OpenVPN-Server, welche unter /etc/openvpn/server.conf
gespeichert wird.
# Port auf dem der Server erreichbar sein soll
# Standard 1194
port 1194
# Protokoll für den Server
# udp oder tcp, Standard ist udp
proto udp
# Device das für den VPN-Tunnel genutzt wird.
# "tun" erzeugt einen gerouteten IP-Tunnel, "tap" erzeugt einen Ethernet-Tunnel.
dev tun
# Keepalive-Pakete senden
# Alle 10 Sekunden ein Paket senden und annehmen
# dass eine Verbindung abgebrochen ist wenn über 120 Sekunden
# kein Paket empfangen wurde
keepalive 10 120
# Aktuellen Status jede Minute in die angegebene Datei schreiben
status openvpn-status.log
# Log-Level festlegen
verb 3
# Die Persist-Optionen verhindern den erneuten Zugriff auf einige Ressourcen,
# die nach einem Neustart aufgrund des Abgebens von Berechtigungen nicht
# mehr verfügbar sein können.
persist-tun
persist-key
ifconfig-pool-persist /etc/openvpn/ipp.txt
# Verschlüsselungsalgorithmus AES mit 256 Bit verwenden
cipher AES-256-CBC
# Authentifizierungsalgorithmus SHA-512 verwenden
auth SHA512
# Zertifikate der Gegenstellen müssen Client-Zertifikate sein
# Verhindert MITM (Man In The Middle) Angriffe
remote-cert-tls client
# Nach dem Start des Server die Berechtigungen abgeben und zum angegebenen
# Benutzer/Gruppe wechseln
user openvpn
group openvpn
# Zertifikate für den Server
ca /etc/openvpn/easyrsa3/pki/ca.crt
key /etc/openvpn/easyrsa3/pki/private/server.key
cert /etc/openvpn/easyrsa3/pki/issued/server.crt
dh /etc/openvpn/easyrsa3/pki/dh.pem
# TLS-Auth verwenden
tls-auth /etc/openvpn/easyrsa3/pki/ta.key 0
# CRL-Datei für widerrufene Zertifikate
crl-verify /etc/openvpn/easyrsa3/pki/crl.pem
# Sever-Modus und virtuellen IP-Bereich festlegen
# Der IP-Bereich darf nicht mit einen vorhanden IP-Bereich kollidieren
server 10.8.0.0 255.255.255.0
# Topologie des virtuellen Netzwerks
# Siehe auch https://community.openvpn.net/openvpn/wiki/Topology
# Möglich sind subnet, p2p, net30
topology subnet
OpenVPN-Server manuell starten
Nachdem die Zertifikate und die Server-Config erstellt sind kann der OpenVPN-Server gestartet werden.
sudo openvpn /etc/openvpn/server.conf
Dies startet den Server im aktuellen Terminal und zeigt die Log-Meldungen direkt an. Für Testzwecke sicherlich hilfreich, für den Produktivbetrieb jedoch eher weniger.
OpenVPN-Server als SystemD-Service
Damit der OpenVPN-Server permanent läuft nutzen wir einen SystemD-Service.
Schaut man sich den standardmäßig aktivierten Service openvpn.service
an, so stellt man fest, dass dieser lediglich als “oneshot” /bin/true
aufruft. Das ist auf den ersten Blick nicht was wir wollen.
OpenVPN bringt ein besonderes Service-Template mit, welches unter /lib/systemd/system/openvpn@.service
zu finden ist. Auf dieses Template muss ein Symlink erstellt werden, welcher den Namen der Server-Config im Verzeichnis /etc/openvpn/
beinhaltet. Im folgenden Beispiel wird von einer Server-Config in der Datei server.conf
ausgegangen.
sudo ln -s /lib/systemd/system/openvpn@.service /etc/systemd/system/openvpn@server.service
Der Service erkennt dann automatisch, anhand des Namens hinter dem @
, welche Config für OpenVPN geladen werden soll.
Aktiviert werden braucht dieser Service nicht extra, da es ein Teil des openvpn.service
ist und über diesen gesteuert wird.
Zum Starten des OpenVPN-Servers als Service starten wir einfach den openvpn.service
neu und schauen uns anschließend den Status an.
sudo systemctl restart openvpn.service
sudo systemctl status openvpn@server.service
● openvpn@server.service - OpenVPN connection to server
Loaded: loaded (/lib/systemd/system/openvpn@.service; enabled; vendor preset: enabled)
Active: active (running) since So 2017-03-19 13:11:04 CET; 1s ago
It’s magic!
Client-Zertifikat erstellen
Für jeden Client muss ein eigenes Zertifikat erstellt werden.
cd /etc/openvpn/easyrsa3
sudo ./easyrsa build-client-full clientname
Dabei muss ein neues Passwort für das Client-Zertifikat und zum Signieren wieder das Passwort des CA-Zertifikates eingegeben werden.
Das Client-Zertifikat liegt nun unter /etc/openvpn/easyrsa3/pki/issued/clientname.crt
und der zugehörige private Schlüssel unter /etc/openvpn/easyrsa3/pki/private/clientname.key
.
Das Zertifikat und vor allem der private Schlüssel sollten NIEMALS über eine ungesicherte Verbindung vom Server zum Client übertragen werden! Jeder der über den privaten Schlüssel verfügt kann sich als der Client ausgeben.
Client-Config
Die Client-Config wird als .ovpn
-Datei bereitgestellt und kann dann von jedem aktuellen OpenVPN-Client verarbeitet werden.
In der folgenden Beispiel-Config müssen noch die entsprechenden Zertifikate, wie weiter unten beschrieben, eingefügt werden.
# OpenVPN Client
client
# Hostname/IP und Port des Servers
remote server.domain.tdl 1194
# Device das für den VPN-Tunnel genutzt wird.
dev tun
# Protokoll des Servers
# udp oder tcp, Standard ist udp
proto udp
# Bei Verbindungsfehler unendlich oft versuchen die Verbindung wiederherzustellen
resolv-retry infinite
# Nicht an eine lokale IP-Adresse binden
nobind
# Die Persist-Optionen verhindern den erneuten Zugriff auf einige Ressourcen,
# die nach einem Neustart aufgrund des Abgebens von Berechtigungen nicht
# mehr verfügbar sein können.
persist-key
persist-tun
# Verschlüsselungsalgorithmus AES mit 256 Bit verwenden
cipher AES-256-CBC
# Authentifizierungsalgorithmus SHA-512 verwenden
auth SHA512
# Zertifikate der Gegenstellen müssen Server-Zertifikate sein
# Verhindert MITM (Man In The Middle) Angriffe
remote-cert-tls server
# TLS-Auth als Client verwenden
key-direction 1
# Zertifikate und Schlüssel
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
[...]
-----END OpenVPN Static key V1-----
</tls-auth>
<ca>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
[...]
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN ENCRYPTED PRIVATE KEY-----
[...]
-----END ENCRYPTED PRIVATE KEY-----
</key>
Die benötigten Zertifikate und Schlüssel sind auf dem Server vorhanden und können zum Beispiel über eine SSH-Verbindung mittels cat
angezeigt und in die Client-Config kopiert werden. Auch hier nochmals der Hinweis, dass die Zertifikate und Schlüssel niemals über eine ungesicherte Verbindung übertragen werden sollten!
Die entscheidenden Zeilen, die in die Client-Config kopiert werden müssen, sind im folgenden Beispiel hervorgehoben.
cd /etc/openvpn/easyrsa3
# tls-auth
sudo cat pki/ta.key
#
# 2048 bit OpenVPN static key
#
-----BEGIN OpenVPN Static key V1-----
19963f30698663ad6b3600c220f750ad
[...]
8b826236190dc7dfb97f3abd56701a5a
-----END OpenVPN Static key V1-----
# ca
sudo cat pki/ca.crt
-----BEGIN CERTIFICATE-----
MIIFqjCCAyagAwIBAgIJAIeJvH+ho4QLMA0GCSqGSIb3xQEBCwUAMBkxFzAVBgNV
[...]
QYh4m167feMm6ICptfGrOSgE2QT76yANDJgUuXx9oGh4sdufhBXXtJolqMX7SzEI
3Hg=
-----END CERTIFICATE-----
# cert
sudo cat pki/issued/clientname.crt
Certificate:
[...]
-----BEGIN CERTIFICATE-----
MIIFQDXCAyigAwIBAgIBBD7NBgkqhkiG9w0BAQsFADAZMRcwFQYDVQ6DDA5jcnlI
[...]
OjYq8ILb08I/GpaEkCSPLO7PkaDtbiEc3ypSrLTRoWXQn0vNyByd1aKUr7RrA6cT
C0rXsA==
-----END CERTIFICATE-----
# key
sudo cat pki/private/clientname.key
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJQwIBA0ANBgkqhkiG5w0BAQEFAASCCS0wggkpAgEAaoICA7Cpd4eI9jYFYLK0
[...]
1G60lge7bHXvXcTrhqv+jhRfRPBTyV2qY6TKZ+WZ/KpcyNOyNl/ynJ5aChpbLy4C
LLYTuZu6ZauZteX8pKjRS7RUel3bQk4=
-----END ENCRYPTED PRIVATE KEY-----
Feste IP-Adresse für bestimmte Clients
Standardmäßig erhält jeder Client eine zufällige IP-Adresse aus dem virtuellen IP-Bereich des Servers. Möchte man einem bestimmtem Client eine feste IP-Adresse zuweisen, so kann man dies über eine eigene Config für diesen Client auf dem Server erledigen.
Sofern noch nicht vorhanden erstellen wir zuerst auf dem Server das Verzeichnis für die clientspezifischen Configs und fügen der Server-Config den entsprechenden Eintrag hinzu.
cd /etc/openvpn
sudo mkdir ccd
# Verzeichnis für die Client-Configs
client-config-dir ccd
Nun legen wir für den entsprechenden Client die Config-Datei im Verzeichnis /etc/openvpn/ccd/
an, wobei die Datei genauso heißen muss, wie der Client bei der Erstellung des Zertifikates genannt wurde. Im folgenden Beispiel soll der Client client50 die feste IP 10.8.0.50 erhalten.
# Feste IP für den Client (Client-IP Subnet)
ifconfig-push 10.8.0.50 255.255.255.0
Weiterleitung ins Internet
Standardmäßig haben OpenVPN-Clients vom VPN aus keinen Zugriff auf das Internet. Dies kann man recht einfach auf dem Server einrichten, indem man IP-Forwarding aktiviert und ein NAT einrichtet.
sudo sysctl -w net/ipv4/ip_forward=1
sudo iptables -t nat -F POSTROUTING
sudo iptables -t nat -A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
Hierbei muss natürlich ggf. eth0
und der IP-Bereich des VPN angepasst werden.
Möchte man dies bei einem Neustart des Systems automatisch aktivieren lassen, so fügt man zuerst einmal der sysctl-Konfiguration einen entsprechenden Eintrag in einer eigenen Konfigurationsdatei hinzu:
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.d/70-openvpn.conf
Für die iptables-Regeln nutzen wir iptables-persistent, welches wir zuerst installieren, falls noch nicht vorhanden.
sudo apt install iptables-persistent
Bei der Installation fragt iptables-persistent, ob man die aktuellen Regeln speichern möchte. Beantworten wir dies mit ja, so ist die Arbeit auch schon erledigt und die Regeln werden beim Systemstart automatisch geladen. Andernfalls muss in der Datei /etc/iptables/rules.v4
die Regel im Bereich *nat
hinzugefügt werden, sodass es dann wie folgt aussieht:
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A POSTROUTING -o eth0 -s 10.8.0.0/24 -j MASQUERADE
COMMIT
Nachträglich alle aktuellen iptables-Regeln speichern kann man zudem über den folgenden Befehl:
sudo iptables-save | sudo tee /etc/iptables/rules.v4
Zur Vollständigkeit halber: Regeln für IPv6 über ip6tables werden in der Datei /etc/iptables/rules.v6
gespeichert bzw. aus dieser geladen.
Allen Traffic über den VPN-Tunnel leiten
Normalerweise wird nur der Traffic über den VPN-Tunnel geleitet, der entweder für den VPN-IP-Bereich bestimmt ist, oder über spezielle Routen zu diesem geleitet wird.
Möchte man nun allen Traffic eines Clients durch den Tunnel leiten, so kann man in der Client-Config (clientname.ovpn
) den folgenden Eintrag hinzufügen:
# Erzwingen, dass jeglicher Traffic über das VPN läuft
redirect-gateway
Weiterhin ist es möglich vom Server aus diese Option an alle Clients zu übermitteln, sodass der Traffic von jedem Client vollständig durch den Tunnel geleitet wird. Hierzu fügt man der Server-Config den folgenden Eintrag hinzu:
# Erzwingen, dass jeglicher Traffic aller Clients durch den Tunnel geleitet wird
push "redirect-gateway"
Zertifikat widerrufen
Ein ausgestelltes und signiertes Zertifikat kann von der CA widerrufen werden. Dies ist beispielsweise notwendig, wenn das Zertifikat in die falschen Hände gelangt ist und man nicht mehr sicher sein kann, dass es nur den berechtigten Personen vorliegt.
Der Widerruf eines Zertifikates sperrt den entsprechenden Client am OpenVPN-Server.
Zuerst muss das entsprechende Zertifikat widerrufen und anschließend die CRL-Datei (neu) erstellt werden. Hierfür wird wieder das Passwort der CA benötigt. Damit die CRL-Datei vom Server gelesen werden kann müssen auch wieder die Dateirechte angepasst werden.
cd /etc/openvpn/easyrsa3
sudo ./easyrsa revoke clientname
sudo ./easyrsa gen-crl
sudo chown root:openvpn ./pki/crl.pem
sudo chmod g+r ./pki/crl.pem
Sofern noch nicht vorhanden muss zudem der folgende Eintrag in der Server-Config hinzugefügt beziehungsweise aktiviert werden:
# CRL-Datei für widerrufene Zertifikate
crl-verify /etc/openvpn/easyrsa3/pki/crl.pem
Private Key für die “OpenVPN Connect” Android-/iOS-App
Achtung: Die folgenden Infos sind Versionsabhängig und die gezeigte Konvertierung wird bei neueren Versionen der App nicht mehr benötigt beziehungsweise kann sogar zu Fehlern führen.
Im Zweifelsfall sollte immer zuerst der original Schlüssel getestet werden.
Unter Verwendung des “encrypted private key” meldet die Android-App OpenVPN Connect den Fehler OpenVPN core error : PolarSSL: error parsing config private key : PK - Bad input parameters to function.
Die iOS-App OpenVPN Connect meldet CORE_ERROR mbed TLS: error parsing config private key : PK - Bad input parameters to function
.
Dies kann behoben werden, indem man den Schlüssel in das DES3-Format konvertiert und anschließend den konvertierten Schlüssel in die Client-Config einfügt.
cd /etc/openvpn/easyrsa3
openssl rsa -in pki/private/clientname.key -des3 -out pki/private/clientname.des3.key
29. Nov. 2019 um 12:08
Hi, das erstellen des ta.key klappt nicht, das System kennt openvpn nicht. Ich bin unter /etc/openvpn
VG
30. Nov. 2019 um 20:17
Hallo Michael,
das kann passieren, wenn openvpn nicht unter den in der Variable `$PATH` angegebenen Pfaden zu finden ist. Bei einigen Debian-Systemen ist beispielsweise bei normalen Nutzern `/usr/sbin` nicht in `$PATH` enthalten.
Versuch mal anstelle von `openvpn` `/usr/sbin/openvpn` zu verwenden.
1. Dez. 2019 um 9:40
Hallo, ja, das wars. Super, Danke. Nur noch rausfinden, wie ich path dauerhaft speichere, aber das muss ich finden.
VG, Michael
26. Jan. 2020 um 22:01
Hallo Peter,
Super Beitrag! Bei dem Schritt mit dem “Client 50” hätte ich noch eine Frage, da ich erst seit ein paar Wochen mit mit dem Pi auseinandersetze. Ich habe ein Verzeichnis mit meinem Client Namen angelegt und den Befehl ifconfig-push… ausgeführt. Als Fehlermeldung erhalte ich “Kommando nicht gefunden”. Kannst du mir einen Hinweis geben, was ich falsch mache?
Danke & Gruss
Andreas
27. Jan. 2020 um 19:47
Hallo Andreas,
das ist kein Befehl der ausgeführt werden muss, sondern eine Config-Datei für den einen Client, der in dem Beispiel `client50` heißt. `/etc/openvpn/ccd` ist das Verzeichnis und `client50` der Dateiname. Durch diese Config wird dem Client dann die feste IP `10.8.0.50` zugewiesen.
22. Jul. 2021 um 9:26
Hallo Peter,
tolle Anleitung, Server ist aufgesetzt, ein Client zum testen läuft ebenfalls.
Verbindung wird ohne Murren hergestellt, einzig mein Problem ist noch das ich mit dem Verbundenen Client nicht auf das Netz hinter dem Server zugreifen kann. In der Config habe ich die Route mit ” Route 192.168.58.0 255.255.255.0″ ergänzt. Der Log der Verbindung zeigt auch das er die Route setzt: add -net 192.168.58.0 10.33.0.1 255.255.255.0. Wenn ich jetzt einen Trace ausführe zeigt er keine Wege an, ein Trace auf den Server 10.33.0.1 geht aber.
Du hast doch bestimmt den entscheidenenden Hinweis für mich.
Danke und Grus Mike
22. Jul. 2021 um 19:15
Hi, mit deinem erwähnten Config-Eintrag legst du auf dem Server eine Route zum entsprechenden Netzbereich an.
Wenn du von den Clients aus auf das lokale Netzwerk des Servers zugreifen möchtest, dann musst du den Clients eine Route zum Servernetz pushen.
Der Config-Eintrag dafür wäre dann `push “route 192.168.58.0 255.255.255.0″`.
Zudem muss am Server das IP-Forwarding aktiviert und ein NAT eingerichtet werden. Beispiele dazu findest du in meinem Beitrag OpenVPN – Zugriff auf Netzwerk hinter einem Client.
26. Aug. 2021 um 14:19
Hallo Peter,
danke für deine Anleitung. Sehr detailliert und gut strukturiert.
Leider hab ich Probleme mich mit meinem iPhone iOS 14.x mit dem Server zu verbinden. Die extra Anweisung, das Zertifikat zu konvertieren, habe ich natürlich ausgeführt.
Ich bekomme folgende Fehlermeldung beim verbinden mit der openvpn Connect App:
Error message: PKey::parse_pem: error in private key:: error06065065:digital envelope
routines:EVP_DecrypteFinal_ex:bad decrypte / error:23077074:PKCS12…
Eine Suche im Netz hat leider nicht ergeben. Hast du einen Rat?
26. Aug. 2021 um 19:14
Für alle die das hier lesen:
Das Problem wurde im Discord besprochen und gelöst. Neuere Versionen der OpenVPN Connect App brauchen scheinbar die Konvertierung nicht mehr.