Ein privates Netz mit Wireguard erstellen

In den letzten Blogposts habe ich gezeigt, wie ich mein privates VPN mit openVPN aufsetze. In diesem Post wiederhole ich das - nur eben mit Wireguard.
wireguard
Heimserver
IPv6
ubuntuusers
Autor:in

Joe Slam

Veröffentlichungsdatum

22 März 2024 - 23:24

Geändert

31 März 2024 - 20:00

In den letzten Blogposts habe ich gezeigt, wie ich mein privates VPN mit openVPN aufsetze. In diesem Post wiederhole ich das - nur eben mit Wireguard.

OpenVPN und Wireguard können auch problemlos nebeneinander laufen, wenn sie verschiedene Netzmasken benutzen. So hat man jeweils ein Fall-Back-Netz, mit dem man die Clients noch erreichen kann.

Auf dem Handy verbraucht openVPN mehr Strom, weil die Kryptosachen stärker sind. Wireguard ist da schlanker bei ausreichender Verschlüsselung.

VPN

Mein Wireguard-VPN soll unter den Netzen 10.3.3.0/24 und fd04:bab0:3::/64 laufen. Alle Clients sollen sich gegenseitig sehen und anpingen können. Auf Wunsch soll der gesamte Traffic über das VPN geroutet werden.

Installation

Unter Ubuntu lässt sich Wireguard auf Server und Clients wie folgt installieren:

#Ubuntu
apt install wireguard
 
#Arch, btw
pacman -S wireguard-tools

Schlüssel erzeugen

Auf meiner Zertifikationsinstanz (oder auf jedem anderen Rechner) erstelle ich mir einen neuen Ordner und erzeuge für den Server sowie für jeden Client ein Paar aus privatem und öffentlichem Schlüssel.

sudo bash
umask 077 && wg genkey | tee server-private.key | wg pubkey > server-public.key
umask 077 && wg genkey | tee client1-private.key | wg pubkey > client1-public.key
umask 077 && wg genkey | tee client2-private.key | wg pubkey > client2-public.key
umask 077 && wg genkey | tee client3-private.key | wg pubkey > client3-public.key

Die Inhalte der Schlüsseldateien werden gleich plaintext in die Configdateien geschrieben.

Server aufsetzen

Nach der Installation existiert das Verzeichnis /etc/wireguard. In diesem Verzeichnis liegen die .conf-Dateien der VPNs, egal ob Server oder Client. Der Name der .conf-Datei entscheidet über den Namen der Interfaceschnittstelle. Benenne ich die Datei foobar.conf, so wird ein Tunneldevice mit dem Namen foobar erzeugt. Die Datei tun0.conf erzeugt ein Interface mit dem Namen tun0. Standardmäßig (also in den Manuals im Netz) werden für Wireguard wg0-Interfaces erzeugt.

Wir erzeugen also die Datei wg0.conf und geben ihr folgenden Inhalt:

# ---------- Server Config ----------
[Interface]
## welche IP4-Adresse hat der Server im Tunnel?
Address = 10.3.3.1/24

## welche IPv6-Adresse hat der Server im Tunnel?
Address = fd04:bab0:3::1/64 

# Wenn ihr iptables nutzt, dann wird hier das NAT zum Internet klargemacht
# Mein Device heisst eth0, eures auch? ansonsten ändern!
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -s 10.3.3.0/24 -o eth0 -j MASQUERADE; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -A POSTROUTING -s fd04:bab0:3::/64 -o eth0 -j MASQUERADE 
# Sobald der VPN beendet wird, werden die iptables Regeln rückgängig gemacht
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -s 10.3.3.0/24 -o eth0 -j MASQUERADE; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -t nat -D POSTROUTING -s fd04:bab0:3::/64 -o eth0 -j MASQUERADE

# Hier kommt der private Key des Servers hin, in Plaintext
PrivateKey = OHUJätschibätschifasfdeg92wz4CvFqlWWUW74dfgM5+zPfuEU=
# Auf welchem Port soll der Server lauschen?
# Diesen Port in der Firewall freigeben!
ListenPort = 45881 

## Für jeden Client kommt hier eine eigene Identifikation
[Peer] # Client1
# Schreibe hier den öffentlichen Schlüssel des Client1 hinein
PublicKey = AfuckAfDfejoqfooobaaarmHILbtoxReB6ZjzNuMtyYNxlM= 
# Mit welchen IP4 und IPv6-Adressen soll sich der Client verbinden?
# Hier müssen ein /32  und /128 verwendet werden (= genau 1 IP-Adresse erlaubt)
AllowedIPs = 10.3.3.2/32, fd04:bab0:3::2/128 


# Hier wiederholt sich das Ganze für Client2
[Peer] # CLient2
# Client public key
PublicKey = 1xejE9Z2OnkqkuckuckFcOsoLA623M1yRr+7/v7SmAtP36UmG8=  
# IPs client can connect as (IPv4 /32  and IPv6 /128)
AllowedIPs = 10.3.3.3/32, fd04:bab0:3::3/128 

[Peer] # Client3
# Client public key
PublicKey = sCid523sdfXwQHoErOyXyIk8UNEz36aff7+R9MIU8Xm4wc=  
# IPs client can connect as (IPv4 /32  and IPv6 /128)
AllowedIPs = 10.3.3.4/32, fd04:bab0:3::4/128 
  • Der Server lauscht unter IP4 und IPv6 auf Port 45881. Ihr könnt auch irgendeinen anderen Port auswählen.
  • Der Server wird unter den Adressen 10.3.3.1/24 und fd04:bab0:3::1/64 über den Tunnel ereichbar sein. Ebenso haben derzeit 3 Clients Zugriff, wobei jeder Client eine fixe IP4 und IPv6 im Tunnelnetz erhält.
  • Bei den AllowedIPs ist euch sicherlich aufgefallen, dass bei IP4 ein /32 und bei IPv6 ein /128 hinter die Adresse geschrieben werden muss.
    • Auf dem Server fungiert AllowedIPs ähnlich wie ein Router und gibt an, wohin der Datenverkehr geroutet werden soll. Daher genügt die Angabe von /32 oder eben /128 (genau eine IP-Adresse).
    • In der gleich folgenden Client-Config fungiert AllowedIPs wie eine Access-Controll-List. Daher muss in der Client-Config ein /24 bzw. /64 definiert werden, um alles von 10.3.3.* bzw. fd04:bab0:3:: zu akzeptieren.
  • Soll ein weiterer Client hinzugefügt werden, muss in der Server-Config ein neuer [Peer]-Block mit dem puplic key des neuen Clients hinzugefügt werden.

Server starten

Ähnlich wie bei openVPN liest systemd das Verzeichnis /etc/wireguard aus und macht alle dort befindlichen MY-VPN.conf-Dateien verfügbar über den Service wg-quick@MY-VPN.service.

Wir können unseren wg0-Server starten mittels:

# Starten
systemctl start wg-quick@wg0.service
# Logs ansehen
journalctl -u wg-quick@wg0.service -f

Firewall anpassen

Falls ihr eine Firewall benutzt (und ich hoffe doch sehr, dass dies der Fall ist), muss diese für Wireguard angepasst werden. Einerseits muss der Server-Port freigegeben werden (ich habe da ja 45881), 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:

## Akzeptiere Pakete von den wg+ Interfaces
iptables -A INPUT -i wg+ -j ACCEPT
iptables -A FORWARD -i wg+ -j ACCEPT

## auf dem Server muss Port 45881 tcp/udp geöffnet werden
iptables -A INPUT -i eth0 -p tcp --dport 45881 -j ACCEPT
iptables -A INPUT -i eth0 -p udp --dport 45881 -j ACCEPT

Wenn euer Device nicht eth0 heisst, müsst ihr den Befehl entsprechend anpassen.

ufw

Die ufw-Firewall muss auf dem Server angepasst werden, damit Wireguard funktioniert. Zunächst muss der Serverport freigegeben werden:

sudo ufw allow 45881

Anschließend müssen drei weitere Dateien editiert werden, damit das Netz funktioniert.

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

DEFAULT_FORWARD_POLICY="ACCEPT"

2a. /etc/ufw/before.rules, füge die folgenden Zeilen vor der *filter-Sektion ein, um das NAT für IPv4 zu aktivieren:

nano /etc/ufw/before.rules

# NAT-Tabelle hinzufügen
*nat
:POSTROUTING ACCEPT [0:0]
# OpenVPN-Regeln hinzufügen
-A POSTROUTING -s 10.3.3.0/24 -o eth0 -j MASQUERADE
COMMIT

2b. /etc/ufw/before6.rules, füge die folgenden Zeilen vor der *filter-Sektion ein, um das NAT für IPv6 zu aktivieren:

nano /etc/ufw/before6.rules

# NAT-Tabelle hinzufügen
*nat
:POSTROUTING ACCEPT [0:0]
# OpenVPN-Regeln hinzufügen
-A POSTROUTING -s fd04:bab0:3::/64 -o eth0 -j MASQUERADE
COMMIT

Wenn euer Device nicht eth0 heisst, müsst ihr den Befehl entsprechend anpassen. Und falls ihr diese Einstellung gerade getroffen habt, könnt ihr in der wg0.conf des Servers die Parameter PostUp und PostUp wieder auskommentieren.

  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

Client einrichten

Auf den Clients erzeugen wir ebenfalls die Datei /etc/wireguard/wg0.conf und geben ihr diesen Inhalt:

# -------- Client Config ------------------
[Interface]
# IP4 Adresse des Clients, so wie in der Server-Config angegeben (/32!)
# Dieser Client bekommt 10.3.3.2
Address = 10.3.3.2/32 
# IPv6 Adresse des Clients (use /128!)
# Dieser Client bekommt fd04:bab0:3::2
Address = fd04:bab0:3::2/128 
# Der Private Key von Client1 im Plaintext
PrivateKey = GNJJAJT0MQnxRHga8Rzp/hLGoCtsefljhelahDks6EMD8Vw= 


[Peer]
# Wie ist der Server erreichbar? Adresse und Port
#Endpoint = [2a02:08:15:4500:fckafd:4]:45881
#Endpoint = 192.168.0.1:45881
Endpoint = vpn.myserver.org:45881

# Der öffentliche Schlüssel des Servers im Plaintext
PublicKey = emV/wFCKAFD4WIyakB/JEi7jp9wH7zBCi81W+qjuMkWc= 

# Sende alle x Sekunden einen Ping an das Netz 
# um den Tunnel aufrecht zu erhalten. 
# Sollte NIE auf dem Server gesetzt werden, 
# sondern nur dort, wo auch "Endpoint" definiert ist. 
# Also hier im Client...
PersistentKeepalive = 5

# Was soll durch den Tunnel geroutet werden?
## Option 1: nur Tunnelkrams durch den Tunnel routen
AllowedIPs = 10.3.3.0/24, fd04:3::/64 
## Option 2: ALLES durch den Tunnel routen
#AllowedIPs = 0.0.0.0/0, ::/0 
  • Diese Datei muss ich nun bei jedem Client nach dem selben Muster anlegen.
  • Der Client erhält seine fest IP4 und IPv6 über den Tunnel
  • Dieses Mal müssen unter Address jeweils ein /32 bzw /128 vergeben werden (= 1 IP Adresse).
    • Der Parameter AllowedIPs fungiert im Clientmodus wie eine Access-Controll-List. Daher wird an dieser Stelle wieder ein /24 bzw. /64 definiert, um alles von 10.3.3.* bzw. fd04:bab0:3:: über den Tunnel zu routen.
  • Soll der gesamte Datenverkehr über den VPN-Tunnel geroutet werden, muss die zweite AllowedIPs-Zeile aktiviert (und die darüberstehende auskommentiert) werden.

Android

Für mein Handy erstelle mich mir wie oben beschrieben ein Schlüsselpaar und generiere mir eine Clientconfig wie oben, wobei ich die zweite AllowedIPs-Option wähle (alles übers VPN routen). Diese wg0.conf übertrage ich per KDE Connect auf mein Handy.

Als App installiere ich mittels F-Droid WG Tunnel von Zane Schepke, da die Original-Wireguard-App Ende 2023 aus dem F-Droid-Repository geflogen ist (weil sie einen integrierten Aktualisierer bekommen hat, der standardmäßig aktiviert ist und nicht transparent angibt, von wo aus er Aktualisierungen herunterlädt; noch fragt er um Zustimmung).

Jetzt kann ich einfach die übertragene wg0.conf-Datei in der App importieren, und alles funktioniert bestens. Ok, in den App-Einstellungen musste ich noch “Tunnel on untrusted wifi” und “Tunnel on mobile data” aktivieren, dann hat es aber sofort funktioniert.

“Tunnel on untrusted wifi” und “Tunnel on mobile data” aktivieren