Administration BSD Internet IT Linux Mac OS X Networking Netzwerk Raspberry Pi Software Windows

Netze knüpfen mit wireguard

Raspberry Pi 3 B+ mit Raspbian als wireguard VPN Gateway an einer SRX300 Firewall angeschlossen.

Heute möchte ich darüber berichten, was für ein großartiges Tool wireguard ist. Ich beschreibe hier, was es macht, wie man es konfiguriert und welche Möglichkeiten sich daraus ergeben.

Wireguard wird gerne als das neue, schnelle VPN des Linux Kernels beschrieben. Dabei gibt es aber zwei Probleme. Patches liegen für den mainline Linux Kernel schon seit einiger Zeit vor. Dennoch dauern die Diskussionen um eine Aufnahme weiter an, da wireguard eine neue crypto-api einführen möchte. Zweitens vermuten Menschen unter VPN eine Lösung, die einen Client mit einem Netz oder zwei Netze untereinander verbindet, dies leistet wireguard aber gar nicht von Haus aus.

Was macht wireguard?

WireGuard® is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache.

wireguard.com

Die wireguard Entwickler sind da schon etwas präziser, was die Software macht. Sie stellt eine Punkt-zu-Punkt Verbindung zwischen zwei Interfaces zweier an das Internet angeschlossener Geräte her. Die Authentifizierung erfolgt dabei mit einem public/private Key-Verfahren ähnlich zu SSH. Dabei kommen moderne, gut auditierte Kryptofunktionen wie Noise protocol framework, Curve25519, ChaCha20, Poly1305, BLAKE2, SipHash24, HKDF zum Einsatz. Und diese werden auch automatisch ohne Benutzerinteraktion mit sicheren Einstellungen benutzt.

Mit OpenVPN gemein hat wireguard, dass es sich genauso einfach und komfortabel durch (NAT-)Firewalls durchschleusen lässt. Ein einzelner, frei konfigurierbarer UDP Port reicht hier aus.

Und das schließt den Funktionsumfang für das Tool auch schon ab.

wireguard installieren

Später wird es genügen, auf jedem unixoiden System, die “wireguard-tools” zu installieren und das mitgelieferte Kernelmodul zu laden. Solange dies nicht der Fall ist, muss man je nach Distribution etwas basteln. Fedora hat es bereits in RPM Fusion drin, für die meisten andere Systeme findet sich ein Fingerzeig auf der Webseite des Projekts. Bei Debian und Raspbian kann man sich das Paket gut aus unstable pinnen.

Den Raspberry Pi erwähne ich nicht umsonst, denn darauf teste ich wireguard derzeit als VPN Gateway. Insbesondere möchte ich die beworbene, hohe Geschwindigkeit testen. Hier gibt es allerdings zu beachten, dass man den Kernel der Raspbian Paketquellen verwendet und nicht jenen, den rpi-update zieht. Für letzteren kann man sich zwar auch die Quellen und Header besorgen, allerdings bekam ich so immer ein angeblich nicht zur Architektur passendes Kernelmodul (.ko) raus.

[ 2422.674108] wireguard: version magic '4.19.30+ mod_unload modversions ARMv6 p2v8 ' should be '4.19.30-v7+ SMP mod_unload modversions ARMv7 p2v8 '

wireguard konfigurieren

Zuerst generieren wir uns für jedes teilnehmende Gerät einen Satz aus public und private key. Diese Schlüssel können wir auf einem beliebigen Gerät erstellen. Die Dateien müssen nicht auf den beteiligten Systemen liegen bleiben, weil die enthaltenen Strings in die Konfigurationsdateien geschrieben werden. Desgalb sollten die Configs auf dem System vor Zugriffen durch unprivilegierte Nutzer geschützt werden.

root@battery:~ $ mkdir wgkeys
root@battery:~ $ cd wgkeys  
root@battery:~/wgkeys $ wg genkey > server_private.key  
Warning: writing to world accessible file.
Consider setting the umask to 077 and trying again.

root@battery:~/wgkeys $ wg pubkey > server_public.key < server_private.key
root@battery:~/wgkeys $ wg genkey > client1_private.key  
Warning: writing to world accessible file.
Consider setting the umask to 077 and trying again.
root@battery:~/wgkeys $ wg pubkey > client1_public.key < client1_private.key
root@battery:~/wgkeys $ ls
client1_private.key client1_public.key server_private.key server_public.key

Nun können wir auf dem Server die Konfigurationsdatei unter /etc/wireguard/wg0.conf erstellen.

[Interface]
Address = 192.168.128.1/24,fd16:b3a5:697e:5324::1/64
ListenPort = 51820
PrivateKey = <server-private-key>

[Peer]
# Client 1
PublicKey = <client1-public-key>
AllowedIPs = 192.168.128.10, fd16:b3a5:697e:5324::10

[Peer]
# Client 2
PublicKey = <client2-public-key>
AllowedIPs = 192.168.128.20, fd16:b3a5:697e:5324::20

Auf dem Client kommt die Datei an den gleichen Ort.

[Interface]
Address = 192.168.128.11/24,fd16:b3a5:697e:5324::11/64
DNS = 192.168.125.1
PrivateKey = <client1-private-key>

[Peer]
# Battery
PublicKey = <server-public-key>
Endpoint = vpn.commander1024.de:51820
AllowedIPs = 192.168.128.0/24, fd16:b3a5:697e:5324::0/64, 192.168.xxx.0/24, 192.168.125.1/32, 192.168.yyy.0/24, 2001:xyz:xyaz:xxx::/64, 2001:xyz:xyz:yyy::/64, 

# This is for if you're behind a NAT and
# want the connection to be kept alive.
PersistentKeepalive = 25

wireguard starten und Status überprüfen

Wenn der Raspberry Pi in einem Netz hinter der Firewall oder dem “Router” steht, muss dort selbstverständlich der gewählte Port des Servers noch an seine internen IPs weitergeleitet werden. In diesem Fall wäre dies der Port UDP 51820. Das Stichwort in den meisten Heimroutern sollte “Port-forwarding” sein.

root@battery:~# wg-quick up wg0
mscholz@Warrior:~# sudo wg-quick up wg0

Nun können wir den Status des Dienstes sowie der (nicht) verbundenen Peers mit dem tool wg abrufen.

root@battery:~# wg
interface: wg0
  public key: <server-public-key>
  private key: (hidden)
  listening port: 51820

peer: <client1-public-key>
  endpoint: 109.91.240.102:12813
  allowed ips: 192.168.128.11/32, fd16:b3a5:697e:5324::11/128
  latest handshake: 3 seconds ago
  transfer: 66.75 KiB received, 400.19 KiB sent

peer: <client2-public-key>
  endpoint: 109.40.3.183:3779
  allowed ips: 192.168.128.21/32, fd16:b3a5:697e:5324::21/128
  latest handshake: 39 seconds ago
  transfer: 676 B received, 1.51 KiB sent

peer: <client3-public-key>
  allowed ips: 192.168.128.10/32, fd16:b3a5:697e:5324::10/128


mscholz@Warrior:~# sudo wg
interface: wg0
  public key: <client1-public-key>
  private key: (hidden)
  listening port: 51244

peer: <server-public-key>
  endpoint: 109.91.240.102:51820
  allowed ips: 192.168.128.0/24, fd16:b3a5:697e:5324::0/64, 192.168.xxx.0/24, 192.168.125.1/32, 192.168.yyy.0/24, 2001:xyz:xyaz:xxx::/64, 2001:xyz:xyz:yyy::/64
  latest handshake: 25 seconds ago
  transfer: 156.29 KiB received, 31.00 KiB sent
  persistent keepalive: every 25 seconds

Installation absichern und Autostart einrichten

Zuerst schützen wir die Daten vor Zugriff durch andere lokale Benutzer.

root@battery:~# chown -R root:root /etc/wireguard/
root@battery:~# chmod -R og-rwx /etc/wireguard/*

Nun aktivieren wir den Autostart des Dienstes durch systemd, falls gewünscht.

root@battery:~# systemctl enable wg-quick@wg0.service

Starten und Stoppen kann man wireguard nun wie jeden anderen systemd Service.

root@battery:~# systemctl start wg-quick@wg0.service
root@battery:~# systemctl stop wg-quick@wg0.service

Nun können sich Client und Server jeweils gegenseitig pingen. Nicht aber die Clients untereinander oder mit anderen Netzen. Alles weitere müssen nun andere Tools und Systemdienste erledigen.

Routing und NAT Setup

Dazu schalten wir IP-Fowarding für IPv4 und IPv6 ein:

root@battery:~ $ sysctl net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
root@battery:~ $ sysctl net.ipv6.conf.all.forwarding=1 
net.ipv6.conf.all.forwarding = 1

Um die Änderungen permanent zu machen, ändern wir diese Zeilen in /etc/sysctl.d/99-sysctl.conf:

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward = 1

# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
net.ipv6.conf.all.forwarding=1

Mit diesen Voraussetzungen könnte man jetzt weitermachen und ein geroutetes Layer 3 Netzwerk aufspannen. Dies halte ich persönlich für den Königsweg. Im besten Fall auch direkt mit öffentlichen IPv6 Adressen im VPN. Die generierten ULA Prefixe hier im Beispiel können nicht ins Internet gerouted werden. Für den ausschießlichen Zugriff auf interne Systeme eignen sie sich aber gut. Erstellen kann man solche Netze überall mit Generatoren wie diesem hier.

NAT

Für einfachen, schnellen Remotezugriff auf ein Netzwerk geht es vielleicht am schnellsten mit NAT. Ich rate allerdings in fast allen Situationen davon ab, NAT an Stellen zu verwenden, wo es nicht absolut notwendig ist. Auf dem Server reicht es aus, diese 2 Zeilen der /etc/wireguard/wg0.conf einzufügen. Am besten vor den Peers:

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

Brücken schlagen?

Selbstverständlich wäre es ebenfalls denkbar, mit Bridges herumzuspielen. Aber auch dies ist mit Vorsicht zu genießen. Steigen die Gerätezahlen in dem gemeinsamen Layer 2 Netz, nimmt der Broad- und Multicasttraffic alsbald messbar störende Volumina an. Sind die einzelnen Blasen dann auch noch latenzmäßig schlecht oder unterschiedlich gut angebunden, potenzieren sich die Probleme.

BGP, OSPF, MPLS, IS-IS, Link-Aggregation?

Um BGP oder OSPF durch wireguard Tunnel zu sprechen, braucht es gar keine Zusatzkonfiguration des wg* Interfaces an jeder Seite. Bekäme man das ISO-Protokoll als Adressfamilie auf das wg0 Interface, wäre auch IS-IS eine Option. Ebenso wäre denkbar, mehrere (unterschiedliche) Internetverbindungen mit Wireguard zu einem Aggregations-Server im Rechenzentrum zu verbinden. So könnte man mit anderen Techniken die Bandbreite bündeln und Ausfallsicherheit schaffen.

Auch die ersten kommerziellen VPN-Anbieter bieten bereits Konfigurationsoptionen mit wireguard an, einige allerding noch im Beta Stadium.

Der Möglichkeiten sind hier kaum Grenzen gesetzt.

Performance!

Wireguard ist schnell. Wireguard ist extem schnell! Auf durchschnittlichen Desktops und Notebooks erreicht man locker die 1Gbps Marke, moderne CPUs lassen sich kaum beeindrucken. Hier sind bestimmt auch Vielfache Gbit/s drin. Ein Raspberry Pi 3 B+ kommt durchaus an die 100Mbit/s heran. Im Umkehrschluss könnte dies auch zur Folge haben, dass mobile Geräte wie Handys und co. geringeren Akkuverbrauch im Vergleich zu anderen Lösungen haben könnten.

Ist das sicher?

Verwendet werden scheinbar weitgehend etablierte Techniken, die schon den einen oder anderen Audit bekommen haben. Auf den Code haben auch schon einige Leute draufgeguckt, auch namhafte aus der Szene. Bei den Diskussionen auf der Linux Kernel Mailingliste dreht es sich hauptsächlich um kleinere Reibungspunkte, statt um die Softwarequalität selbst. Ob das Einführen einer neuen crypto api so fürchterlich ist, wie einige meinen, vermag ich nicht abzuschätzen. Fest steht aber, dass eine gesunde Portion Skepsis gegenüber neuer Kryptographiesoftware angebracht sein sollte. Die findigen Hacker hatten ja noch gar nicht so viel Gelegenheit, das System so gründlich zu testen – zumal wireguard auch noch in einem einigermaßen regen Entwicklungsprozess steckt.

Autor

Seit Kindheitstagen ist der Computer sein Begleiter. Was mit Linux anfing, wurde 2005 ein/e Beruf/ung, die weit über den Arbeitsplatz hinausgeht. Durch stetige Weiterentwicklung fasste er auch im *BSD Segment Fuß und bietet mittlerweile professionelle Lösungen im Bereich Hosting, Networking und Infrastruktur an. Als Ausgleich beschäftigt er sich neben Computerspielen mit der Fotografie.

17 Kommentare Neuen Kommentar hinzufügen

  1. Karsten Meyer sagt:

    Wie sieht es denn mit Multicast aus? Avahi scheint das nicht hinzubekommen auch wenn Pakete über die Verbindung geschickt werden.

  2. Martin sagt:

    Hallo Marcus,
    ich versuche seit geraumer Zeit zwei räumlich getrennte Netzwerke, jeweils hinter einer FritzBox, per WG und zwei Pi 4b zu verbinden. Pi1 ist als Server konfiguriert und funktioniert auch zügig und problemlos mit einem Handy per App. Pi2 ist als Client konfiguriert. Allerdings bekomme ich mit dem Pi2 keine Verbindung zum Pi1 aufgebaut. Laut Status von wg bei Pi2 werden Datenpakete geschickt aber es kommen keine Datenpakete zurück. Pi1 erhält die Datenpakete von Pi2 nicht.
    Ich habe bei beiden FritzBoxen den Port 51820 geöffnet und auf den jeweiligen Pi verwiesen. Aber an irgendeiner Stelle scheinen die Pakete vom Pi2 hängen zu bleiben.
    Hast Du eine Idee, wie ich prüfen kann wo die Pakete hängen bleiben. Eine Checkliste wäre super. Ich bin im Bereich Linux und Netzwerkstruktur eher ein Amateur und komme einfach nicht weiter.

    1. Mein erster Verdacht wäre Carrier Grade NAT (CGN, DS-Lite, etc.) an einer der beiden Seiten. Dies kannst Du überprüfen, indem Du die WAN-IP der Fritzbox mit dem Ergebnis einer Seite wie https://www.wieistmeineip.de/ zu vergleichen. Sind sie an beiden Seiten identisch, dürfte Dein Setup theoretisch funktionieren. Anderenfalls könnte man es über IPv6 versuchen. Auf jeden Fall wirst Du ‘PersistentKeepalive = 25’ benötigen, zumindest auf Pi2.
      Zuerst solltest Du mit Dritttools sicherstellen, dass Pi2s Pakete an Pi1 ankommen. Dafür könntest Du Port 51820 als TCP und UDP durchreichen und mit nmap von der anderen Seite scannen. TCP deswegen, weil ein nicht erreichbarer UDP Port genauso aussieht wie einer, der einfach nicht antwortet. nmap -sS -Pn -p 51820 . Gibt er “filtered” aus, kommt nix an, bei “closed” (der wg lauscht ja nicht auf TCP) heisst das, die Antwort kommt vermutlich von Pi1. Dies könnte man natürlich auch lauschend mit tcpdump und/oder wireshark überprüfen.

      1. Martin sagt:

        Hallo Marcus,
        bei der Abfrage der IP kommt bei PI1 immer die korrekte Antworten bei aktivem wie auch inaktivem WG. Beim PI2 ist bei deaktivierten WG die Rückmeldung korrekt im Bereich IPv4 sowie IPv6. Bei aktiviertem WG bei PI2 wird kein IPv4 gefunden und IPv6 ist korrekt. Dies dürfte auch so richtig sein, da ich WG nur für IP4 eingerichtet habe.
        Der Befehl: `’sudo nmap -sS -Pn -p 51820′ liefert mir auf beiden PIs nur folgende Rückmeldung:
        Starting Nmap 7.70 ( https://nmap.org ) at 2020-03-03 14:38 CET
        WARNING: No targets were specified, so 0 hosts scanned.
        Nmap done: 0 IP addresses (0 hosts up) scanned in 0.14 seconds
        Ich werde wohl noch ein entscheidendes Detail vergessen haben. Muss ich zeitgleich pingen oder im Befehl von nmap noch eine Adresse ergänzen?
        Beim Ping-Versuch vom PI2 zum PI1 mit der IP aus dem WG-Netz kam folgende Meldung:
        ping 192.168.175.1
        PING 192.168.175.1 (192.168.175.1) 56(84) bytes of data.
        From 192.168.177.1: icmp_seq=1 Redirect Host(New nexthop: 192.168.177.150)
        Ich hatte in der Fritz.Box eine IPv4-Route in das WG-Netz eingerichtet in der Hoffnung, dass dies Sinn macht. Der PI2 hat die IP 192.168.177.150.
        Ich habe übrigens zur Zeit eine Lan-Lan-Koppelung über die Fritzboxen laufen um die zwei Netze zu verbinden. Kann dies ein Problem darstellen?

        1. ‘sudo nmap -sS -Pn -p 51820 ′ da muss die Zieladresse natürlich noch angegeben werden.
          Die Route in der Fritzbox kann und wird nützlich werden, sobald es funktioniert. Dann muss sie den LAN Bereich der anderen Seite gesetzt und das gw auf die IP des lokalen Pis zeigen. Erstmal würde ich sie weglassen.
          Die LAN-LAN Kopplung der Fritzboxen kann sich mit der Route beißen, aber die wirst Du vermutlich benötigen, bis die Verbindung zwischen den Pis steht.
          Aus den Angaben Deiner Kommentare schließe ich, dass eine LAN Seite 192.168.175.0/24 und die andere 192.168.177.0/24 als IPv4 Netz verwenden. Das Transfernetz über das die Pis sich via WG unterhalten, muss natürlich ein 3., neues Netz sein.
          Was ich noch vermisse, ist die Klärung, ob nicht doch ein DS-LITE Setup besteht und die Kommunikation direkt via public routed IPv4 überhaupt möglich ist.

  3. Marcusg562 sagt:

    Hi zusammen hat jemand ne Idee wieso ich weder ins lokale noch ins WAN komme?

    root@raspberrypi:/home/pi# wg-quick up wg0
    [#] ip link add wg0 type wireguard
    [#] wg setconf wg0 /dev/fd/63
    [#] ip -4 address add 10.10.10.1 dev wg0
    [#] ip link set mtu 1420 up dev wg0
    [#] resolvconf -a tun.wg0 -m 0 -x
    [#] wg set wg0 fwmark 51820
    [#] ip -6 route add ::/0 dev wg0 table 51820
    [#] ip -6 rule add not fwmark 51820 table 51820
    [#] ip -6 rule add table main suppress_prefixlength 0
    [#] ip -4 route add 0.0.0.0/0 dev wg0 table 51820
    [#] ip -4 rule add not fwmark 51820 table 51820
    [#] ip -4 rule add table main suppress_prefixlength 0
    [#] iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
    root@raspberrypi:/home/pi#

  4. Jens Dolgner sagt:

    Leider geht aus dem Artikel nicht hervor ob man zwei (IPv4) Netze miteinander verbinden kann (also zwei /24 Netze), oder ob es nur Clients gibt, die jeweils nur eine IP bekommen.

    1. Na klar geht das, analog natürlich auch mit IPv6. Wenn der Wireguard auf jeder Seite das Default gateway ist, sollte es auf Anhieb funktionieren, ansonsten muss man an die Clients noch Netzrouten verteilen lassen, damit sie den Weg rüber ins andere Netzwerk über den wireguard Node finden.

  5. Tim sagt:

    Ich hätte eine Verständnisfrage. Wenn ich einen raspi als Client habe ,kann ich ihn dann als vpn Gateway nutzen? Das heißt wenn ich clients in meinen Netzwerk die IP vom raspi mitgebe ,der Traffic dann durch den vpn geleitet wird.

    1. Na klar geht das. Du gibst Deinen Rechnern im Netz (am besten dem Router/Firewall) die Route zum VPN Netzbereich mit der internen IP des Raspberrys als Gateway. So in etwa:

      JunOS: set routing-options static route 192.168.128.0/24 next-hop 192.168.125.5
      Linux: sudo ip route add 192.168.128.0/24 via 192.168.125.5 dev enp0s25

  6. röstiberg sagt:

    Mein Turris Omnia mit meinem android (lineageos) und wireguard aus dem f-droid store verbinden hat leider nicht funktioniert. Zwischen durch hat es mal geklappt, aber sobald android in den standby geht, ist ein Neustart des Mobiltelefons fällig um das Mobiltelefon wieder mit wireguard zu verbinden. Ich dachte dann, ein Update auf dem Turris könnte bei der Stabilität noch helfen.
    Nun funktioniert wireguard gar nicht mehr.

    1. Uff, zu dem spezifischen Gerät kann ich nix sagen. Wireguard verwendet wie so ziemlich alle anderen VPN Lösung auf android die stock VPN API. Ich hatte es mit wireguard aus f-droid und Play Store probiert. Bei meinen bisherigen Tests bleiben die Telefone den ganzen Tag mit Roaming durch verschiedene Netze verbunden und haben jederzeit Konnektivität. Klingt ein bisschen merkwürdig. Hab aber momentan auch kein Gerät mit Lineage zum Testen zur Hand

  7. Lukas sagt:

    Dank deinem Post hab ich mich da auch mal rangewagt. Das grundlegende Setup ist auch echt einfach. Nur die Sache mit der Firewall oder dem NAT scheinen nicht zu funktionieren. Pings funktionieren aber Seitenaufrufe (oder curl ) funktionieren nicht. DNS geht allerdings.

    1. Michael sagt:

      Hatte genau das selbe Problem. Auf meinem Raspberry PI3 läuft Fedora Minimal und das hatte folgenden Eintrag in iptables: “-A INPUT -j REJECT –reject-with icmp-host-prohibited”. Nach dem Entfernen funktionierte dann alles einwandfrei :).

Schreibe einen Kommentar

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

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.