In diesem Blogpost zeige ich Schritt für Schritt, wie ich mein privates openVPN-Netzwerk aufgebaut habe. Zu dem Thema gibt es übrigens eine sehr empfehlenswerte Podcastfolge von Request for Comments, in welcher Clemens Schrimpe ausführlich über VPN spricht.
Mein VPN soll die IPs 10.5.5.0/24
verwenden und eigentlich “nur” dazu dienen, die Clients miteinander zu verbinden. Es kann aber auch easy der gesamte Internettraffic über dass VPN geleitet werden.
Hardware
Folgende Geräte kommen zum Einsatz:
Master-CA
- ist die Zertifikationsinstanz, welche die Zertifikate ausstellt und signiert. Dies übernimmt mein Desktoprechner zuhauseopenVPN-Server
- das übernimmit mein HomeserverClients
- mein Desktoprechner, mein Laptop sowie mein Büro-PC
Installieren
Zunächst installiere ich die benötigten Pakete:
sudo apt install openvpn easy-rasa
Ich nutze Arch, btw, daher nutze ich Pacman:
pacman -S openvpn easy-rsa
Zertifikate anlegen
Bevor es wirklich los gehen kann, müssen die grundlegenden Zertifikate erstellt werden.
Master CA
Wir sind unsere eigene Zertifikationsinstanz, die alle weiteren Zertifikate für Server und Clients signiert. Diese Zertifikationsinstanz sollte auf einer anderen Maschine laufen als dem openVPN Server. Daher nutze ich meinen Desktop-PC zu hause dafür.
Wir erstellen zunächst das passende Verzeichnis unter /etc/easy-rsa
sudo bash
mkdir /etc/easy-rsa
cd /etc/easy-rsa
… und erzeugen hier das Master-CA ca.crt
:
export EASYRSA=$(pwd)
easyrsa init-pki
easyrsa build-ca
Denke dir ein starkes Passwort für das Master-CA aus, und gib dir einen Common Name, ich habe da “Produnis” gewählt.
Die Datei ca.crt
liegt nun im Unterordner pki/
Serverzertifikat
Jetzt legen wir die Zertifikate für unseren openVPN-Server an und signieren sie mit unserem Master-CA:
easyrsa gen-req SERVERNAME nopass
easyrsa sign-req server SERVERNAME
Wir müssen die Aktion mit yes
bestätigen und das eben erzeugte Passwort des Master-CA eingeben.
Das erzeugte und signierte Zertifikat für den openVPN-Server liegt nun in pki/private/SERVERNAME.key
bereit. Ebenfalls liegt dort die Datei pki/private/ca.key
. Diese benötigen wir später noch, um weitere Zertifikate zu signieren.
Der openVPN-Server benötigt noch weitere Dateien für die Verschlüsslung des Netzwerks. Da diese Dateien auch von den Clients benötigt werden, erzeuge ich mir ein eigenes Verzeichnis hierfür, welches so heisst, wie das VPN-Netz, das ich erzeugen möchte. In meinem Fall soll das Netzwerk “produnis” heissen. Der Name ist egal, aber so verliert man nicht die Übersicht.
mkdir /etc/easy-rsa/produnis
# diffie hellman für Perfect Forward Secrecy (PFS)
openssl dhparam -out /etc/easy-rsa/produnis/dh.pem 2048
# HMAC key um Man-in-the-Middle-Angriffe zu unterbinden
openvpn --genkey secret /etc/easy-rsa/produnis/ta.key
Jetzt kopieren wir alles auf den openVPN-Server. Folgende Dateien werden dort benötigt:
/etc/easy-rsa/pki/private/SERVERNAME.key
/etc/easy-rsa/pki/issued/SERVERNAME.crt
/etc/easy-rsa/pki/ca.crt
/etc/easy-rsa/produnis/dh.pem
/etc/easy-rsa/produnis/ta.key
Ich kopiere die Dateien zunächst ins /tmp
-Verzeichnis des Servers.
scp /etc/easy-rsa/pki/private/SERVERNAME.key /etc/easy-rsa/pki/issued/SERVERNAME.crt /etc/easy-rsa/pki/ca.crt /etc/easy-rsa/produnis/dh.pem /etc/easy-rsa/produnis/ta.key user@server:/tmp
Server einrichten
Verbinde dich auf den Server und erstelle ein Unterverzeichnis in /etc/openvpn/server/
, das wie das VPN-Netz heisst. Ich hatte ja produnis als Netznamen gewählt.
ssh user@server
sudo bash
mkdir /etc/openvpn/server/NETZNAME
In diesen Ordner verschiebe ich die kopierten Dateien.
mv /tmp/SERVERNAME.key /tmp/SERVERNAME.crt /tmp/ca.crt /tmp/dh.pem /tmp/ta.key /etc/openvpn/server/NETZNAME/
Im “Hauptordner” /etc/openvpn/server/
erstelle ich die Datei produnis.conf
mit folgendem Inhalt:
port 1194
proto udp
dev tun
server 10.5.5.0 255.255.255.0
# ihr müsst "produnis" durch eure Namen ersetzen
ca /etc/openvpn/server/produnis/ca.crt
cert /etc/openvpn/server/produnis/produnis.crt
key /etc/openvpn/server/produnis/produnis.key # This file should be kept secret
dh /etc/openvpn/server/produnis/dh.pem
tls-crypt /etc/openvpn/server/produnis/ta.key
client-to-client # damit sich die clients untereinander sehen können
ifconfig-pool-persist /etc/openvpn/server/produnis/ipp.txt
keepalive 10 120
cipher AES-256-CBC
max-clients 5
persist-key
persist-tun
status /etc/openvpn/server/produnis/openvpn-status.log
verb 3
explicit-exit-notify 1
Stelle sicher, dass openVPN auf alle Dateien zugreifen kann:
chown openvpn:network -R /etc/openvpn/server
Starte den Server mittels
openvpn /etc/openvpn/server/produnis.conf
Systemd
Alle Konfigurationsdateien liegen in /etc/openvpn/server/
, z.B. /etc/openvpn/server/produnis.conf
. Die passende systemd-Service-Unit heisst nun genauso wie die .conf
-Datei (nur ohne .conf
) openvpn-server@servername.service
.
In meinem Fall also
systemctl start openvpn-server@produnis.service
systemctl status openvpn-server@produnis.service
Clients hinzufügen
Auf der Master-CA-Maschine erzeugen wir nun weitere Zertifikate für jeden Client.
sudo bash
cd /etc/easy-rsa
easyrsa gen-req CLIENTNAME nopass
easyrsa sign-req client CLIENTNAME
Wir müssen die Aktion mit yes
bestätigen und das oben erzeugte Passwort des Master-CA eingeben.
Jetzt können wieder alle Dateien auf den Client übertragen werden. Benötigt werden
/etc/easy-rsa/pki/private/CLIENTNAME.key
/etc/easy-rsa/pki/issued/CLIENTNAME.crt
/etc/easy-rsa/pki/ca.crt
/etc/easy-rsa/produnis/ta.key
Ich kopiere diese Dateien zunächst ins /tmp
-Verzeichnis auf dem Client:
scp /etc/easy-rsa/pki/issued/CLIENTNAME.crt /etc/easy-rsa/pki/private/CLIENTNAME.key /etc/easy-rsa/pki/ca.crt /etc/easy-rsa/produnis/ta.key user@client:/tmp
Konfiguration der Clients
Auf dem Client erstelle ich im Ordner /etc/openvpn/client/
einen Unterordner produnis
. In diesen lege ich alle Zertifikate.
ssh user@client
sudo bash
mkdir /etc/openvpn/client/produnis
mv /tmp/ca.crt /tmp/ta.key /tmp/CLIENTNAME.key /tmp/CLIENTNAME.crt /etc/openvpn/client/produnis/
Im “Hauptordner” /etc/openvpn/client/
erstelle ich die Datei produnis.conf
mit folgendem Inhalt:
client
dev tun
proto udp
remote mein.server.de 1194 # ersetze mit Adresse des openVPN-Server
ca /etc/openvpn/client/produnis/ca.crt
cert /etc/openvpn/client/produnis/CLIENTNAME.crt
key /etc/openvpn/client/produnis/CLIENTNAME.key
tls-crypt /etc/openvpn/client/produnis/ta.key
cipher AES-256-CBC
resolv-retry infinite
nobind
persist-key
persist-tun
tun-mtu 1350 # Unitymedia/Vodafone
verb 3
Stelle sicher, dass openVPN auf alle Dateien zugreifen kann:
chown openvpn:network -R /etc/openvpn/client
Starte den Client mittels
openvpn /etc/openvpn/client/produnis.conf
Mit Systemd starten
Alle Konfigurationsdateien liegen in /etc/openvpn/client/
, z.B. /etc/openvpn/client/produnis.conf
. Die passende systemd-Service-Unit heisst nun genauso wie die .conf
-Datei (nur ohne .conf
) openvpn-client@produnis.service
.
In meinem Fall also wieder
sudo systemctl start openvpn-client@produnis.service
sudo systemctl status openvpn-client@produnis.service
statische IP-Adresse für die Clients festlegen
Dies ist eine Art DHCP-light, wir teilen jedem Client eine feste IP innerhalb des VPN-Netzes zu.
Erstelle auf dem Server ein Unterverzeichnis ccd
(client config dir) und lege dort je eine Datei für jeden Client an.
mkdir /etc/openvpn/server/produnis/ccd
cd /etc/openvpn/server/produnis/ccd
nano CLIENTNAME
CLIENTNAME
ist dabei der Name, den du beim Erzeugen der Zertifikate verwendet hast. Anhand des Zertifikats erkennt der Server den Client.
In die Datei schreibst du:
ifconfig-push 10.5.5.x 10.5.5.1
wobei du x
durch die gewünschte IP ersetzt. Die zweite IP ist die des VPN-Servers, also immer 10.5.5.1
.
Damit der Server über unsere IP-Listen Bescheid weiss, muss /etc/openvpn/server/produnis.conf
um folgende Zeile erweitert werden:
client-config-dir /etc/openvpn/server/produnis/ccd
Anschließend muss openVPN neu gestartet werden, z.B. mittels
systemctl restart openvpn-server@produnis.service
Firewall anpassen
Falls ihr eine Firewall benutzt (und ich hoffe doch sehr, dass dies der Fall ist), muss diese für openVPN angepasst werden. Einerseits müssen Ports freigegeben werden (standardmäßig 1194 udp
), anderseits müssen wir intern NAT
einrichten, wenn der Internetverkehr über den Tunnel geroutet werden soll.
iptables
Die iptables-Firewall muss auf dem Server und auf den Clients angepasst werden, damit openVPN funktioniert:
## openvpn general settings für Server und Client
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT
## nur auf dem Server nächste Zeile ausführen
## Dies setzt das NAT auf, damit Internet durch den Tunnel geroutet wird
#iptables -t nat -A POSTROUTING -s 10.5.5.0/24 -o eth0 -j MASQUERADE
## auf Server und Client muss Port 1194 fuer openVPN geöffnet werden
iptables -A INPUT -i eth0 -p udp --destination-port 1194 -j ACCEPT
Wenn euer Device nicht eth0
heisst, müsst ihr den Befehl entsprechend anpassen.
ufw
Die ufw-Firewall muss auf dem Server und auf den Clients angepasst werden, damit openVPN funktioniert:
# openVPN
sudo ufw allow 1194
sudo ufw allow out 1194/udp
Auf dem Server müssen noch drei weitere Einstellungen getroffen werden, damit das Netz funktioniert.
/etc/default/ufw
nano /etc/default/ufw
DEFAULT_FORWARD_POLICY="ACCEPT"
/etc/ufw/before.rules
, füge die folgenden Zeilen vor der*filter
-Sektion ein, um dasNAT
zu aktivieren:
nano /etc/ufw/before.rules
# NAT-Tabelle hinzufügen
*nat
:POSTROUTING ACCEPT [0:0]
# OpenVPN-Regeln hinzufügen
-A POSTROUTING -s 10.5.5.0/24 -o eth0 -j MASQUERADE
COMMIT
Wenn euer Device nicht eth0
heisst, müsst ihr den Befehl entsprechend anpassen.
/etc/ufw/sysctl.conf
nano /etc/ufw/sysctl.conf
net/ipv4/ip_forward=1
net/ipv6/conf/default/forwarding=1
net/ipv6/conf/all/forwarding=1
Fertig
Jetzt sollten sich alle Clients mit dem Server verbinden und sich untereinander “sehen” können. Da jeder Client von mir eine fest IP-Adresse zugewiesen bekommen hat, kann ich nun easy per ssh von Client zu Client oder auf den Server verbinden. Genau so, wie ich es wollte.
gesamten Traffic über das VPN routen
Damit ein Client seinen gesamten Traffic über den VPN tunnelt, muss in der Client-Config folgende Zeile ergänzt werden:
redirect-gateway def1 # leitet gesamten Datenverkehr über das VPN
Das def1
steht für “default route” und muss nicht weiter angepasst werden.
siehe auch
- Im nächsten Blogpost zeige ich, wie ich Handy und Tablet unter Android dem VPN hinzugefügt und IPv6 aktiviert habe.
- Weil es so schön war, hab ich alles nochmal mit Wireguard nachgebaut.
Weblinks
- https://wiki.archlinux.org/title/OpenVPN
- https://wiki.archlinux.org/index.php/Easy-RSA
- https://www.itsfullofstars.de/2018/09/openvpn-assign-static-ip-to-client/
- https://bbs.archlinux.org/viewtopic.php?id=293930
- https://requestforcomments.de/archives/682