VPN mit Wireguard

VPN mit Wireguard

vpn techstuff security

In diesem Blog installiere ich ein VPN Gateway um den eigenen Internettraffic in öffentlichen W-LANs oder anderen potentiell unsicheren Netzen zu verschlüsseln und über einen eigenen Server in das Internet zu routen.

Wireguard ist eine moderne VPN Implementierung im Linux Kernel die mit einer relativ simplen Konfiguration auskommt. Die entsprechende Software wird auf dem Linux Server als dynamisches Kernelmodul installiert. Dabei besteht die Kernelimplementierung von Wireguard gerade einmal aus ca. 4000 Zeilen Code¹. Für die Clients gibt es entsprechende Pakete über den Packagemanager oder die Wireguard Homepage.

Die Begriffe Client und Server treffen es hier nicht wirklich da Wireguard praktisch "nur" virtuelle Netzwerkinterfaces bereitstellt die untereinander (verschlüsselt) verbunden sind. Der Server erhält seine Rolle dadurch, dass er eine Routinginstanz für den Internettraffic darstellt. Die pink hinterlegten Netzwerkbereiche sehen nur die verschlüsselten Daten.

Serverinstallation

Im ersten Schritt wird die Software auf dem Arch Linux Server installiert. Da es sich um ein dynamisches Kernelmodul handelt, müssen auch die Linux-Header mitinstalliert werden. Für andere Distributionen gibt es Installationsanweisungen auf der Projektseite.

$ sudo pacman -Sy linux-headers wireguard-tools wireguard-dkms

Schlüsselpaare
Als nächstes müssen die privaten und öffentlichen Schlüssel für Client und Server erzeugt werden. Zur Verdeutlichung habe ich hier die Schlüsselrollen mit in die Keys geschrieben; tatsächlich werden nur die kryptischen Strings erzeugt.

$ wg genkey
4EKnzma4x__SERVER-PRIV__EYvAnEBgPs8p3zAt81A=

$ echo 4EKnzma4x__SERVER-PRIV__EYvAnEBgPs8p3zAt81A= | wg pubkey
31/uhemkNP__SERVER-PUB__n4unk8rHV3G5G/TX0m4=

$ wg genkey
yMvuuQou67g__CLIENT-PRIV__2/ruLh9Nb+gGZz/u0E=

$ echo yMvuuQou67g__CLIENT-PRIV__2/ruLh9Nb+gGZz/u0E= | wg pubkey
BT3mIYb93__CLIENT-PUB__Cg3FrnOsoeG2+7/aRCyg=

Konfiguration
Mit diesen Keys wird die Wireguard Konfiguration für den Server und den ersten Client erzeugt. Aus dem Namen der Konfigurationsdatei /etc/wireguard/wg0.conf leitet sich anschließend beim starten der Name des VPN Interfaces ab. Die Funktionen der einzelnen Parameter sind Inline komentiert:

## Die VPN-Serverkonfiguration:
[Interface]
# Die Serveradresse im VPN, hier wird auch das gesamte VPN als
# Klasse C Netz definiert:
Address    = 10.1.1.1/24
# Der Listen Port des Servers:
ListenPort = 51820
# Der private Schlüssel des Servers:
PrivateKey = 4EKnzma4x__SERVER-PRIV__EYvAnEBgPs8p3zAt81A=
# Skritpe die bei starten und stoppen des VPN ausgeführt werden
# Hier wird die NAT für das Internetgateway eingerichtet und beim stoppen
# wieder gelöscht. ens3 ist das Internet-Interface des Servers:
PostUp     = iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o ens3 \
             -j MASQUERADE; \
             iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED \
             -j ACCEPT; \
             iptables -A FORWARD -i wg0 -o ens3 -j ACCEPT
PostDown   = iptables -t nat -D POSTROUTING -s 10.1.1.0/24 -o ens3 \
             -j MASQUERADE; \
             iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED \
             -j ACCEPT; \
             iptables -D FORWARD -i wg0 -o ens3 -j ACCEPT

## Die Konfiguration für den ersten Client
[Peer]
# Der öffentliche schüssel des Clients:
PublicKey  = BT3mIYb93__CLIENT-PUB__Cg3FrnOsoeG2+7/aRCyg=
# Die Adresse nutzt der Client innerhalb des VPN:
AllowedIPs = 10.1.1.2/32

Die Konfiguration sollte nur für root lesbar sein, da der private Serverschlüssel hier hinterlegt ist.

Da der Server als Internetgateway arbeiten soll muss das Forwarding von IP Verbindungen auf dem Server dauerhaft aktiviert werden. Dies erfolgt über einen Eintrag in /etc/sysctl.d/99-sysctl.conf. Dort gemachte Einstellungen werden bei jedem Serverstart geladen.

$ sudo sysctl net.ipv4.ip_forward=1
$ sudo sh -c 'echo net.ipv4.ip_forward=1 >> /etc/sysctl.d/99-sysctl.conf'

Das VPN starten
Das Kommando wg-quick liest diese Konfiguration und baut das VPN Interface auf dem Server auf.

$ sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip address add 10.1.1.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o ens3 -j MASQUERADE;
    iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT;
    iptables -A FORWARD -i wg0 -o ens3 -j ACCEPT

Das VPN Interface soll natürlich automatisch gestartet werden; das kann systemd übernehmen.

$ sudo systemctl enable wg-quick@wg0
Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@wg0.service
                → /usr/lib/systemd/system/wg-quick@.service.

Client

Der Android Client ist als Beta Version im Play Store verfügbar Die Konfiguration selbst sieht dabei der Serverkonfiguration sehr ähnlich und kann über ein Textfile oder einen QR Code importiert werden. Alternativ stehen die Felder auch in der GUI zur Verfügung.

## Das VPN Interface auf dem Client:
[Interface]
Address    = 10.1.1.2/32
PrivateKey = yMvuuQou67g__CLIENT-PRIV__2/ruLh9Nb+gGZz/u0E=
# Ein öffentlicher DNS Server, da wir den aus dem lokalen Netz nicht nutzen
DNS        = 1.1.1.1

## Dieses mal ist der "Peer" unser Server
[Peer]
PublicKey  = 31/uhemkNP__SERVER-PUB__n4unk8rHV3G5G/TX0m4=
# Die AllowedIPs sind hier die Adressen die in das VPN geroutet werden sollen,
# ... also alle
AllowedIPs = 0.0.0.0/0
Endpoint   = vpnserver.example.com:51820

Test

Damit kann das VPN auch auf dem Client gestartet werden. Um zu testen ob wir uns im Tunnel befinden, können wir zwei Tests machen:

  • Vom Client aus kann die private Adresse des Peers 10.1.1.1 angepingt werden. Dies wäre über die Internetleitung nicht möglich.
  • Ein Dienst wie https://canihazip.com/ liefert die öffentliche Adresse des Servers zurück, nicht mehr die des Smartphones.

Vorheriger Beitrag Nächster Beitrag