Dieser Artikel beschreibt die Konfiguration eines Wireguard - VPN-Servers auf debian 9 (stretch,stable). Sämtlicher IPv4- als auch IPv6-Verkehr eines Roadwarriors soll durch Wireguard getunnelt werden. Als Server kommt ein Hetzner-Cloud-server CX11 zum Einsatz. Für 2,96€ im Monat bekommt man genügend Leistung, eine fixe IPv4-Adresse und ein IPv6-Netz (/64) zugewiesen.
Wireguard ist eine moderne VPN-Lösung mit einer sehr schmalen Codebasis. Wireguard implementiert nur wenige, dafür aber aktuelle Verschlüsselungsverfahren und läuft, anders als zum Beispiel OpenVPN, im Kontext des Kernels. Eine detaillierte Beschreibung des Protokolls und eine Übersicht über die verwendeten kryptografischen Verfahren kann man im Wireguard-whitepaper nachlesen. In den nächsten Monaten (stand März 2019) soll Wireguard Aufnahme in den Linux-Kernel finden. Für debian 10 testing und unstable/sid stehen aktuelle Pakete in den debian-repositories bereit. Die Installation auf allen gängigen Linux-Distributionen und BSD-Systemen ist auf der Wireguard-Homepage beschrieben. Als Transportprotokoll setzt Wireguard ausschließlich auf UDP, möchte man stattdessen TCP einsetzen (einziger Grund wäre eine Blockierung von UDP), muss man Wireguard zum Beispiel über WebSockets tunneln.
Da Wireguard ein Kernelmodul benötigt, muss das System zu dessen Übersetzung vorbereitet werden:
sudo apt-get install linux-headers-$(uname -r) build-essential
Für debian 9 stretch/stable existieren noch keine Pakete im offiziellen repository, daher muss das unstable-repository auf dem System verfügbar gemacht werden. Bei debian 10 kann dieser Schritt übersprungen werden. Dabei werden alle Pakete aus unstable jedoch so niedrig priorisiert, dass alle Pakete aus stable bei Updates den Vorzug erhalten, außer explizit installierten Paketen aus unstable:
$ sudo echo "deb http://deb.debian.org/debian/ unstable main" > /etc/apt/sources.list.d/unstable.list
$ sudo printf 'Package: *\nPin: release a=unstable\nPin-Priority: 90\n' > /etc/apt/preferences.d/limit-unstable
Im Anschluss wird Wireguard installiert und das Kernelmodul wird automatisch übersetzt und geladen:
$ sudo apt update && apt install wireguard
Ob das Kernelmodul geladen ist, lässt sich leicht überprüfen:
$ sudo lsmod | grep wireguard
Damit der VPN-Server IPv4 und IPv6 Pakete weiterleitet muss diese Funktionalität dem Kernel mitgeteilt werden:
$ sysctl net.ipv4.ip_forward=1
$ sysctl net.ipv6.conf.all.forwarding=1
Um diese Einstellungen auch nach einem Neustart zu setzen, sind folgende Zeilen zur Datei /etc/sysctl.d/99-sysctl.conf
zu ergänzen:
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
Wireguard basiert auf dem Konzept des Crypto-Routing. Jeder Kommunikationsteilnehmer an einem VPN besitzt ein asymmetrisches Schlüsselpaar, der jeweilige öffentliche Schlüssel wird demjenigen Kommunikationspartner mitgeteilt, der über den Kommunikationskanal kommunizieren darf. Die Schlüssel sind sehr kurze base64-kodierte ECDH-Schlüssel. Die Schlüssel können auf jedem System, auf auf dem Wireguard verfügbar ist, generiert werden.
Schlüsselpaar für den VPN-Server:
$ wg genkey > vpn-server.seckey
$ wg pubkey < vpn-server.seckey > vpn-server.pubkey
Schlüsselpaar für einen weiteren Kommunikationsteilnehmer:
$ wg genkey > mobile.seckey
$ wg pubkey < mobile.seckey > mobile.pubkey
Optional ist die Generierung eines weiteren pre shared keys um eine weitere Schicht symmetrischer Verschlüsselung hinzuzufügen. Gründe hierfür werden in Abschnitt 5.2 des Wireguard-Whitepapers erläutert.
$ wg genpsk > vpn.psk
Es existieren zwei Möglichkeiten Wireguard zu betreiben, man kann mithilfe von wg
einen Tunnel
etablieren und Kommunikationspartner (peers) hinzufügen. Alternativ dazu hat man die Möglichkeit eine Konfigurationsdatei zu erstellen,
welche später von wg-quick
eingelesen wird. Die zweite Möglichkeit hat den Vorteil, dass sich wg-quick
auch gleich um die Erstellung
und Konfiguration der Wireguard-Netzwerkschnittstelle (im Beispiel: wg0
) kümmert. Zudem bringt das Debian-Paket auch gleich ein
Systemd-Interface-Template mit, was ein Start des VPNs erleichtert und keine zusätzlichen Systemd-Kenntnisse erfordert.
Bevor die Konfiguration von Wireguard erfolgen kann, noch einige Worte zur IP-Adresskonfiguration von Hetzner. IPv4-Adressen
werden durch Hetzner per DHCP vergeben, sind aber persistent. IPv6 Adressen werden stattdessen statisch konfiguriert, Hetzner
verwendet dazu auf ihren debian Cloud-Servern die debian networking-scripte. Die IP-Adresskonfiguration findet sich unter:
/etc/network/interfaces.d/50-cloud-init.cfg
.
Exemplarisch sind folgende Adressen auf dem Interface eth0
konfiguriert:
IPv4: 203.0.113.1/32
IPv6: 2001:db8:ffff:ffff::1/64
Da Wireguard über das virtuelle Tunnelinterface wg0
kommuniziert, müssen, jeweils für IPv4 und IPv6, interne Tunnel-Netze und Adressen
vergeben werden. Für IPv4 wählt man ein privates Netz gemäß RFC1918, in diesem Beispiel verwenden wir 172.16.100.0/24
. Dem VPN-Server
wird später die erste Adresse aus diesem Bereich zugewiesen.
Die Adressen aus diesem privaten IPv4-Bereich müssen später noch einer Adressumsetzung auf die öffentliche Adresse 203.0.113.1
unterzogen werden.
Bei IPv6 hingegen reicht es aus das öffentliche Netz 2001:db8:ffff:ffff::/64
zu segmentieren. Zum Beispiel kann man das Netz in
256 Subnetze unterteilen: 2001:db8:ffff:ffff::/72
. Die IPv6-Adresse auf eth0
ändert sich dadurch nicht, lediglich die Netzgröße.
Daher muss diese in der Datei /etc/network/interfaces.d/50-cloud-init.cfg
angepasst werden:
#address 2001:db8:ffff:ffff::1/64
address 2001:db8:ffff:ffff::1/72
Im Anschluss muss die Konfiguration neu eingelesen werden:
$ sudo systemctl restart networking.service
Das zweite Netz aus dem IPv6-Bereich (2001:db8:ffff:ffff:100:/72
) wird für die internen Tunneladressen verwendet.
Die Konfigurationsdatei von Wireguard muss nach dem Wireguard-Interface benannt benannt werden: /etc/wireguard/wg0.conf
.
In diesem Beispiel lauscht der Wireguard-VPN-Server auf dem Port upd/443
auf eth0
. Lediglich die Schlüssel müssen noch ergänzt werden:
[Interface]
Address = 172.16.100.1/24
Address = 2001:db8:ffff:ffff:100::1/72
SaveConfig = true
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
ListenPort = 443
PrivateKey = [vpn-server.seckey]
[Peer]
PublicKey = [mobile.pubkey]
PresharedKey = [vpn.psk]
AllowedIPs = 172.16.100.0/24, 2001:db8:ffff:ffff:100::/72
Wireguard kann nun mittels wg-quick
gestartet werden:
$ sudo wg-quick up /etc/wireguard/wg0.conf
Sollte der VPN-Server ohne Probleme starten, kann man die Konfiguration mittels Systemd persistent machen:
$ sudo systemctl enable wg-quick@wg0
Die Teilnehmer am VPN-Netzwerk sollen DNS-Anfragen durch den Tunnel an den VPN-Server richten können. In diesem Beispiel wird dnsmasq verwendet, aber auch andere resolver wie unbound können verwendet werden.
Eine exemplarische Konfiguration für dnsmasq (/etc/dnsmasq.conf
):
# Quad9 - Initiative https://www.quad9.net/
server=9.9.9.9
server=149.112.112.112
server=2620:fe::fe
server=2620:fe::9
listen-address=127.0.0.1,172.16.100.1
bind-interfaces
cache-size=1000
Neustart von dnsmasq:
$ systemctl restart dnsmasq.service
Damit DNS-Anfragen an dnsmasq
gerichtet werden, müssen auf dem VPN-Server die Nameserver in der Datei /etc/resolv.conf
auf eine Loopbackadresse verweisen. Dazu wird in der Datei /etc/dhclient/dhclient.conf
folgende Zeile auskommentiert:
#prepend domain-name-servers 127.0.0.1;
prepend domain-name-servers 127.0.0.1;
Im Anschluss muss die Konfiguration neu eingelesen werden:
$ sudo systemctl restart networking.service
Die Datei kann auf einem beliebigen System erstellt werden:
[Interface]
Address = 172.16.100.2/24, 2001:db8:ffff:ffff:100::2/72
PrivateKey = [mobile.seckey]
DNS = 172.16.100.1
[Peer]
PublicKey = [vpn-server.pubkey]
PresharedKey = [vpn.psk]
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = 203.0.113.1:443
Diese Datei kann nun als QR-Code kodiert werden und mithilfe der Android-/IOS-App eingelesen werden
$ qrencode -t ansiutf8 < client.conf