Ein privates Netz mit openVPN erstellen

In diesem Blogpost zeige ich Schritt für Schritt, wie ich mein privates openVPN-Netzwerk aufgebaut habe.
openvpn
Heimserver
ubuntuusers
Autor:in

Joe Slam

Veröffentlichungsdatum

16 März 2024 - 19:24

Geändert

31 März 2024 - 19:59

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 zuhause
  • openVPN-Server - das übernimmit mein Homeserver
  • Clients - 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.

  1. /etc/default/ufw
nano /etc/default/ufw 

DEFAULT_FORWARD_POLICY="ACCEPT"
  1. /etc/ufw/before.rules, füge die folgenden Zeilen vor der *filter-Sektion ein, um das NAT 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.

  1. /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.