Raspberry Pi – Installation und Betrieb von WireGuard

WireGuard Logo

Obwohl die Bekanntheit von WireGuard in den letzten Monaten stark zugenommen hat, ist das VPN-Protokoll bzw, die VPN-Software immer noch verhältnismäßig unbekannt. Ich nutze WireGuard seit einigen Monaten und möchte es nicht mehr missen. Vor allem der schnelle Verbindungsaufbau, das exzellente Roaming-Verhalten und die gute Performance haben mich überzeugt.

Was sich genau hinter WireGuard verbirgt und wie die Software arbeitet, habe ich bereits in meinem Artikel „​WireGuard – neues VPN-Protokoll mit großer Zukunft“ beschrieben. Jetzt folgt sozusagen der zweite Teil, in dem ich detailliert auf die Einrichtung unter Raspbian Buster und Android eingehe.

WireGuard Installation

Die Installationsanleitung funktioniert nicht bei folgenden Raspberry Pi Modellen: 1, 2 (Ausnahme v1.2), Zero & Zero W. Bei diesen Modellen fehlen benötigte CPU-Features und WireGuard muss dort von Hand compiliert werden. Wie das geht habe ich relativ am Ende meines Artikels aufgezeigt. Davon abgesehen macht die Nutzung auf diesen Modellen aber nur eingeschränkt Spaß.

Zunächst bringen wir die Paketquellen und alle Pakete auf den aktuellen Stand. Anschließend installieren wir noch die Kernel Headers.

sudo apt update
sudo apt upgrade
sudo apt install raspberrypi-kernel-headers

Nachdem dies erledigt ist, widmen wir uns der Installation von WireGuard.

echo "deb http://httpredir.debian.org/debian buster-backports main contrib non-free" | sudo tee --append /etc/apt/sources.list.d/debian-backports.list
wget -O - https://ftp-master.debian.org/keys/archive-key-$(lsb_release -sr).asc | sudo apt-key add -
sudo apt update
sudo apt install wireguard
sudo reboot

Die Installation an sich ist damit erledigt. Jetzt können wir mit der Konfiguration fortfahren.

Generierung der benötigten Schlüsselpaare

Zum Start benötigen wir jeweils einen privaten und öffentlichen Schlüssel für den Client und den Server.

Die Erstellung der Keys wird im Verzeichnis „/etc/wireguard“ durchgeführt. Damit alle Dateien bei der Erstellung direkt restriktive Berechtigungen haben, muss die umask auf 077 gesetzt werden.

sudo su
cd /etc/wireguard
umask 077
wg genkey | tee peer1_private.key | wg pubkey > peer1_public.key
wg genkey | tee server_private.key | wg pubkey > server_public.key

Mittels „ls“ prüfen wir, ob alle vier Dateien erstellt wurden:

ls
peer1_private.key  peer1_public.key  server_private.key  server_public.key

Zum Schluss können die Keys mittels „cat“ ausgegeben werden, da wir diese später sowieso benötigen.

exit
sudo cat /etc/wireguard/peer1_private.key
sudo cat /etc/wireguard/peer1_public.key
sudo cat /etc/wireguard/server_private.key
sudo cat /etc/wireguard/server_public.key

WireGuard Server Konfiguration erstellen

Im ersten Schritt aktivieren wir das IPv4 Forwarding in der Datei „/etc/sysctl.conf“. Dies kann entweder mit Entfernen der Auskommentierung der Zeile „net.ipv4.ip_forward = 1“ oder alternativ mit diesem Befehl erfolgen:

sudo perl -pi -e 's/#{1,}?net.ipv4.ip_forward ?= ?(0|1)/net.ipv4.ip_forward = 1/g' /etc/sysctl.conf

Wer IPv6 nutzt, muss stattdessen entsprechend die Auskommentierung der Zeile „net.ipv6.conf.all.forwarding=1“ aufheben.

Anschließend muss der Raspberry Pi neugestartet werden.

sudo reboot

Wir überprüfen den Status mit folgendem Befehl:

sysctl net.ipv4.ip_forward

Wenn das IPv4 Forwarding aktiv ist muss als Ergebnis „net.ipv4.ip_forward = 1“ zurückgegeben werden.

Jetzt erstellen wir die WireGuard-Konfiguration „/etc/wireguard/wg0.conf“. Welchen Editor ihr bevorzugt, bleibt natürlich euch überlassen.

sudo vim /etc/wireguard/wg0.conf

Folgendes Template könnt ihr als Ausgangsbasis nutzen.

[Interface]
Address = 100.64.0.1/24
ListenPort = 51820
PrivateKey = <insert server_private.key>

#replace eth0 with the interface open to the internet (e.g might be wlan0)
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

#Client1 Smartphone
[Peer]
PublicKey = <insert peer1_public.key>
AllowedIPs = 100.64.0.2/32

Neben den IP-Adressen müsst ihr den privaten Schlüssel vom Server und den öffentlichen Schlüssel vom Client ergänzen. Außerdem müsst ihr bei den iptables-Regeln evtl. die Netzwerkschnittstelle anpassen. Optional könnt ihr zudem einen anderen Port definieren. Wenn alles erledigt ist, solltest ihr die Datei unbedingt speichern.

Die für den Tunnel verwendeten IP-Adressen, dürfen sich mit den lokal verwendeten, privaten IPv4-Blöcken (RFC 1918) nicht überschneiden. Beim Einsatz einer FRITZ!Box als Router wird lokal standardmäßig 192.168.178.0/24 verwendet, d.h. alle anderen Adressbereiche können ohne Probleme genutzt werden.

Eine elegante Alternative ist die Verwendung von IP-Adressen (100.64.0.0/10), die für Carrier-Grade-NAT (RFC 6598) reserviert sind. Damit ist sichergestellt, dass die Tunnel-IPs nie mit den privaten Adressbereichen kollidieren können.

WireGuard Client Konfiguration erstellen

Am besten erstellt ihr für jeden Client eine eigene Konfiguration.

sudo vim /etc/wireguard/peer1.conf

Folgendes Template könnt ihr als Ausgangsbasis nutzen.

[Interface]
Address = 100.64.0.2/32
DNS = 192.168.178.1
PrivateKey = <insert peer1_private.key>

#Server
[Peer]
PublicKey = <insert server_public.key>
Endpoint = t6bibneqwcjxplum.myfritz.net:51820
AllowedIPs = 0.0.0.0/0, ::/0
#PersistentkeepAlive = 25

Hier müsst ihr unter „[Interface]“ die IP-Adresse des Clients anpassen und den gewünschten DNS-Server eintragen. In meinem Beispiel verwende ich die private IP der FRITZ!Box. Wer daheim Pi-Hole im Einsatz hat, kann hier die Pi-Hole Adresse eintragen und kommt somit auch von unterwegs in den Genuss der Werbefreiheit.

Außerdem müsst ihr noch den privaten Schlüssel des Clients ergänzen.

Unter „[Peer]“ tragt ihr zunächst den öffentlichen Schlüssel des Servers ein.

Anschließend folgt die Internetadresse, unter welcher der WireGuard-Server erreichbar ist. Üblicherweise gibt es hier zwei Dinge zu beachten. Bei eurem Internetanschluss daheim, bekommt ihr mit großer Wahrscheinlichkeit eine dynamische IP-Adresse vom Provider zugewiesen. Der WireGuard-Client müsste die wechselnden IP-Adressen stets kennen, um sich zu verbinden. Als Hilfe kommt hier ein dynamischer DNS-Anbieter ins Spiel, der einen festen Domainnamen bereitstellt und dahinter automatisch die jweils aktuelle IP-Adresse zuweist. Bei Verwendung einer FRITZ!Box könnt ihr beispielsweise den Dienst „MyFRITZ!“ nutzen. Eine andere Alternative wäre FreeDNS. Der zweite Punkt ergibt sich, wenn der Raspberry Pi in eurem Heimnetzwerk steht. In diesem Fall müsst ihr an eurem Router ein Port-Forwarding einrichten (UDP 51820), sodass der WireGuard-Traffic des Clients auf den Server weitergeleitet wird.

Unter „AllowedIPs“ wird definiert, welche IP-Ranges über das WireGuard-VPN geroutet werden. Mit „0.0.0.0/0, ::/0“ wird der komplette IPv4- und IPv6-Traffic geroutet (full tunnel). Mit 192.168.178.0/24 könnt ihr z.B. nur euer Heimnetzwerk routen (split tunnel).

„PersistentKeepalive“ ist standardmäßig deaktiviert. Zunächst ein paar Hintergrundinfos um einzuordnen, ob ihr dieses Feature benötigt oder nicht. Normalerweise ist WireGuard nicht sehr gesprächig und sendet nur Daten, wenn etwas zu übertragen ist. Ansonsten verhält sich WireGuard ruhig. Wenn sich der Server hinter einem NAT oder einer Firewall befindet und der Client für eine bestimmte Zeit keine Daten zum Server sendet, entfernt der NAT-Router bzw. die Firewall den Host-Status aus der Verbindungstabelle. Falls jetzt der Server ein Paket zum Client sendet, kommt dieses nicht an, da der NAT-Router bzw. die Firewall nicht weiß, was mit dem Paket zu tun ist. Mit der Option „PersistentKeepalive“ sendet der Client alle x Sekunden ein leeres Paket, um die Verbindung aufrechtzuhalten. Ein Wert von 25 Sekunden hat sich in der Praxis bewährt und funktioniert mit einem Großteil von Firewalls und NAT-Routern.

Kurz zusammengefasst benötigt ihr dieses Feature also nur, wenn ihr vom Server euren Client erreichen möchtet, obwohl dieser seit längerer Zeit keine Pakete gesendet hat. Die meisten Benutzer werden dieses Feature nicht benötigen. Falls doch, einfach die Auskommentierung der Zeile rückgängig machen.

WireGuard Server starten

Nun können wir WireGuard auf dem Server starten. Anstatt alle einzelnen Schritte manuell mit dem „wg“-Tool durchzuführen, bedienen wir uns beim Tool „wg-quick“.

sudo wg-quick up wg0
[#] ip link add wg0 type wireguard
[#] wg setconf wg0 /dev/fd/63
[#] ip -4 address add 100.64.0.1/24 dev wg0
[#] ip link set mtu 1420 up dev wg0
[#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Danach prüfen wir den Status der wg0-Schnittstelle.

sudo wg
interface: wg0
  public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxljP1wpITnI=
  private key: (hidden)
  listening port: 51820

peer: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxtJd9/esWN4=
  allowed ips: 100.64.0.2/32

Der Server läuft und ist für die Verbindung des Clients bereit.

WireGuard beenden funktioniert mit diesem Befehl:

sudo wg-quick down wg0

Wenn WireGuard beim Systemstart automatisch geladen werden soll, kann dies mit folgendem Befehl realisiert werden:

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

Der Daemon kann folgendermaßen gesteuert werden. Dabei müsst ihr allerdings darauf achten, dass ihr WireGuard zuerst beendet, sofern ihr es manuell gestartet habt.

sudo systemctl start wg-quick@wg0
sudo systemctl stop wg-quick@wg0
systemctl status wg-quick@wg0

Zum Schluss werden die Berechtigungen von „/etc/wireguard/“ und allen Dateien noch einmal korrigiert. Damit wird sichergestellt, dass nur root die entsprechenden Berechtigungen besitzt.

sudo chown -R root:root /etc/wireguard/
sudo chmod -R og-rwx /etc/wireguard/*

WireGuard Client unter Android einrichten

Die Einstellungen in der Android-App können manuell, mittels einer Datei oder mit einem QR-Code erfolgen. Die letzte Variante ist dabei am bequemsten. Hierfür muss auf dem Server der QR-Code erstellt werden.

sudo apt install qrencode

Nach dem Installieren von „qrencode“ kann der QR-Code von der Client-Konfiguration erstellt werden:

sudo cat /etc/wireguard/peer1.conf | qrencode -t ansiutf8

Auf dem Android-Gerät muss zunächst die WireGuard App via Google Play installiert werden. Daraufhin kann der erstellte QR-Code mit der App gescannt werden, um die Konfiguration zu importieren. Nachdem ein Name vergeben wurde, kann die Verbindung aktiviert werden.

Mit einem Klick auf den gerade erstellten Tunnel werden einige Infos angezeigt, unter anderem auch eine Trafficstatistik.

Auf dem Server kann ebenfalls der Status ausgegeben werden. Dort werden unter anderem alle verbundenen Clients angezeigt:

sudo wg
interface: wg0
  public key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxljP1wpITnI=
  private key: (hidden)
  listening port: 51820

peer: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxtJd9/esWN4=
  endpoint: 11.12.13.14:53019
  allowed ips: 100.64.0.2/32
  latest handshake: 56 seconds ago
  transfer: 927.04 KiB received, 64.85 MiB sent

Der Client kann nun auch via Ping erreicht werden:

ping 100.64.0.2
PING 100.64.0.2 (100.64.0.2) 56(84) bytes of data.
64 bytes from 100.64.0.2: icmp_seq=1 ttl=64 time=95.9 ms
64 bytes from 100.64.0.2: icmp_seq=2 ttl=64 time=112.4 ms
64 bytes from 100.64.0.2: icmp_seq=3 ttl=64 time=71.7 ms

Noch zwei kleine Tipps für die Android-App. Ich importieren die Konfig vom Server immer zweimal. Einmal als „full tunnel“ mit „0.0.0.0/0, ::/0“ und einmal als „split tunnel“, lediglich mit dem Heimnetzwerk eingetragen, z.B. 192.168.178.0/24. So habt ihr volle Kontrolle und könnt je nach Situation den richtigen Tunnel nutzen.

Beim Bearbeiten eines Tunnels (Tunnel Infos anzeigen und dann rechts oben auf das Stift-Icon) könnt ihr außerdem festlegen, welche Apps keinen Traffic über den Tunnel schicken dürfen.

Troubleshooting

WireGuard ist ein Kernel-Modul, das via DKMS automatisch installiert wird, sobald das System einen neuen Kernel benutzt. In seltenen Fällen kann es jedoch passieren, dass WireGuard nicht automatisch eingebunden wird und mit dem neuen Kernel nicht mehr funktioniert.

In diesem Fall sollte zunächst geprüft werden, ob das WireGuard Modul geladen wurde:

lsmod | grep wireguard

Falls nicht kann es hilfreich sein, das Kernel-Modul neu zu konfigurieren:

sudo dpkg-reconfigure wireguard-dkms
sudo modprobe wireguard

Wenn dies keine Abhilfe schafft, könnt ihr noch folgendes ausprobieren:

sudo apt remove wireguard
sudo apt install bc libncurses5-dev
sudo apt install wireguard

Sollte dies auch keine Besserung bringen, könnt ihr alternativ das WireGuard Kernel Module und das wg Tool selber kompilieren. Davor muss aber sichergestellt sein, dass alle installierten WireGuard-Pakete deinstalliert sind!

sudo apt remove wireguard
# Toolchain installieren
sudo apt install libmnl-dev raspberrypi-kernel-headers build-essential git pkg-config
#Code laden
git clone https://git.zx2c4.com/wireguard-linux-compat
git clone https://git.zx2c4.com/wireguard-tools
# Kernel Module und das wg Tool kompilieren und installieren
make -C wireguard-linux-compat/src -j$(nproc)
sudo make -C wireguard-linux-compat/src install
make -C wireguard-tools/src -j$(nproc)
sudo make -C wireguard-tools/src install
# Neustarten und fertig
sudo reboot

Die aktuell installierte Version könnt ihr am besten via „dmesg“ herausfinden:

dmesg | grep wireguard
[   15.677458] wireguard: loading out-of-tree module taints kernel.
[   15.687104] wireguard: WireGuard 0.0.20200318 loaded. See www.wireguard.com for information.
[   15.687119] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved.

Quellen

  • https://www.wireguard.com/install/
  • https://github.com/adrianmihalko/raspberrypiwireguard
  • https://www.reddit.com/r/pihole/comments/bnihyz/guide_how_to_install_wireguard_on_a_raspberry_pi/
  • https://emanuelduss.ch/2018/09/wireguard-vpn-road-warrior-setup/
  • https://www.bachmann-lan.de/raspberry-pi-mit-wireguard-als-vpn-server-mit-wireguard/

Tobi

Hallo, mein Name ist Tobias und ich habe diesen Blog im April 2009 ins Leben gerufen. Seitdem blogge ich hier über Software, Internet, Windows und andere Themen, die mich interessieren. SSDblog ist mein zweiter Blog, indem es rund um das Thema SSDs geht. Ich würde mich freuen, wenn ihr meinen Feed abonniert oder mir auf Twitter und Facebook folgt.

11 Antworten

  1. Jörg sagt:

    Hallo Tobias,
    nach deiner Anleitung habe ich WireGuard Server auf einen Raspberry Pi 2 (etwas overclockt) installiert und eingerichtet. Ich baue auschließlich einen einzigen Tunnel von einem GL-AR750S-Ext Mini Router mit integrierten WireGuard Client auf. Das klappt soweit sehr gut. Ein mobiles WLAN mit VPN im Hosentaschenformat.

    Der Tunnel baut sich automatisch bei einer Internetverbindung des Mini Routers auf. So sind alle Clients aus dem WLAN über den Tunnel in das LAN des Raspberry Pis verbunden. Im LAN befindet sich außerdem mein NAS.

    Deine Beschreibung ist sehr verständlich und vollständig, auch für Linux Noobs wie mich. Danke dafür!

    Leider funktioniert die Namesauflösung über den Tunnel nicht. Ich kann also aus dem WLAN des Minirouters nur über IP Adressen auf das NAS im LAN zugreifen.

    Wie könnte man das lösen?
    Ist es möglich den DNS Suffix aus dem LAN in die WireGuard Client config einzubinden?

    Eine weniger schöne Methode wäre das NAS in die hosts Datei einzutragen, was aber auch nur bei Windows anwendbar wäre.

    VG
    Jörg

    • Tobi sagt:

      Hallo Jörg,
      ich denke das Problem liegt am Mini-Router bzw. am eingebauten WireGuard-Client. Kannst du hier explizit einen DNS-Server setzen? Die Geräte die du dann via WLAN mit dem Mini-Router verbindest, nutzen natürlich diesen als DNS-Resolver.
      Du kannst ja testweise dein Smartphone direkt mit dem WireGuard-Server verbinden und schauen, ob die interne Namensauflösung dann funktioniert.
      Viele Grüße Tobias

    • Stefan sagt:

      Hallo Jörg,
      ich versuche schon „ewig“, meinen GL-300-ARM Router von unterwegs über den eingebauten Wireguard-Client mit meinem Raspi-WG-Server zu Hause zu verbinden…
      Obwohl die Weboberfläche vom Router „Success“ meldet, läuft der Tunnel nicht…
      Könntest Du mal Deinen Einträge aus dem GL-AR750S posten (natürlich zensiert…)
      Danke!
      Stefan

  2. Claus sagt:

    Hallo Tobi,
    danke für die super Anleitung! Damit habe ich es problemlos geschafft, Wireguard auf meinem Pi 4 einzurichten. Das ganze dann noch auf dem Android Handy mit Tasker gesteuert und mein Handy verbindet sich jedesmal automatisch mit meinem Raspi zu Hause sobald ich das heimische Wlan verlasse.
    Wenn man übrigens Pihole auf demselben Raspi benutzt wie Wireguard, dann muss man in den Pihole Settings noch darauf achten, im DNS Reiter „Listen on all interfaces“ zu aktivieren, sonst funktioniert die DNS Auflösung mit Pihole nicht.
    Ich hatte es anfangs auf „Listen only on interface eth0“ stehen und da kann er natürlich lange suchen…

    Viele Grüße
    Claus

  3. Thomas sagt:

    Hallo Tobi,
    ich habe einen Wireguard Server auf einer FritzBox installiert. Allerdings sollte mein Problem bei deiner Installation auch auftreten.
    Sobald ich mich mit meinem VPN Client in einem WLAN befinde, das den gleichen IP-Bereich wie mein Zuhause LAN verwendet (z.B. 192.168.178.0/24) klappt zwar die Verbindung, aber nach kurzer Zeit `hängt‘ sich die Verbindung auf. Gehe ich z.B. nur über ein Mobil-Verbindung, klappt alles. Ist dir das auch schon einmal aufgefallen?
    Viele Grüße
    Thomas

    • Tobi sagt:

      Ja das Problem kommt daher, dass auf beiden Seiten dasselbe Netz verwendet wird. Daher würde ich bei Inbetriebnahme einer FRITZ!Box immer zuerst das lokale Netz von 192.168.178.0/24 auf etwas anderes ändern.

  4. Thomas sagt:

    Mit deiner Anleitung habe ich eben mal schnell auch auf einem Raspi Wireguard installieren können. Leider habe ich hier das gleiche Verhalten.
    Mit IPSec VPN auf einer FritzBox klappt es ohne Probleme. Keine Ahnung, wo das Problem liegt.
    Vielleicht liegt es doch an der FritzBox, in der ich als Gast eingeloggt bin.

    Gruss Thomas

  5. Thomas sagt:

    Hallo Tobi,
    die Netze sind doch verschieden.
    Hier 192.168.178.0/24
    Zu Hause: 192.168.0.0/24
    Gestern hab ich mich auch über ein anderes WLAN eingewählt und auch das gleiche Verhalten gehabt. Ich vermute nun fast, dass es an meiner Fritzbox zu Hause liegt.
    Ich habe es auch mit 2 verschiedenen Peers versucht, beide das gleiche.
    D.h. Es kommt eine Verbindung zustande, ich kann mich z.B. auch per SSH auf meine Server zu Hause verbinden, kann ein paar Kommandos absetzen und dann bleibt die Verbindung stehen. Die Dauer ist unwichtig, scheinbar nur die Menge an Daten. Ich muss mal in meiner FritzBox suchen, ob ich da irgendeine Einstellung dazu habe.
    Gruss Thomas

  6. Martin sagt:

    Gibt es schon eine Möglichkeit mit der Android App WLANs auszuschließen?

    Sprich: „Wann man in WLAN xy ist, dann kein VPN an machen.“

  7. Holger PRang sagt:

    Hallo Tobias,

    großes Kompliment – die erste Anleitung, bei der es für mich auf Anhieb funktionierte!
    Habe zahlreiche Vorschläge ausprobiert, bisher scheiterten alle irgendwo an „Unverträglichkeiten“ im Zusammenspiel der Pakete mit dem OS.

    Viele Grüße
    Holger

Schreibe einen Kommentar zu Martin Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.