Wireguard: Peer-IP-Check

Wer Wireguard mit Peers benutzt, deren IP-Adresse sich ändert (z.B. weil sie an einem privaten DSL-Anschluss sind), muss regelmäßig die IP-Adresse überprüfen.

Wireguard selbst macht nur beim Starten der Schnittstelle eine DNS-Auflösung um die aktuelle IP-Adresse des Peers zu bekommen. Wenn sich aber z.B. die Adresse des Servers ändert, schlägt die Verbindung irgendwann fehl.

Zum Glück lässt sich dies mit einem kleinen Script, welches z.B. alle 10 Minuten ausgeführt wird, abfangen. Ein Ansatz ist das Script in der Ubuntu-Dokumentation zu Wireguard, welches aber auf meinem Debian-Client nicht ohne weiteres funktionierte (und mir auch etwas kompliziert vorkam).

#!/bin/bash
# Status von der Schnittstelle überprüfen
# wg0-client: Name der Schnittstelle, die geprüft werden soll
# meinpeer.dyndns.net: der Name des Peers, dessen IP geprüft werden soll
        
cip=$(wg show wg0-client endpoints | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}") 	
echo "$cip"
digIP=$(dig +short meinpeer.dyndns.net) # Die Adresse des Peers muss angepasst werden
   echo "$digIP"
     if [ "$digIP" != "$cip" ]
       then
          echo "Daten sind anders"
          /usr/sbin/service [email protected] restart
            
        else 
	  echo "Daten sind gleich"
	  #nichts zu tun
	 fi

Die wesentlichen Elemente des Scripts oben: in Zeile 6 wird mittels der wireguard-tools und grep die aktuelle IP-Adresse, die die Schnittstelle verwendet ermittelt. In Zeile 8 wird geprüft, welche IP-Adresse der Peer aktuell hat. Weichen diese beiden Werte voneinander ab, wird die Wireguard-Schnittstelle in Zeile 13 neu gestartet – dann erfolgt auch die Auflösung der IP-Adresse erneut und die Verbindung steht wieder.

Der Restart der Wireguard-Schnittstelle in Zeile 13 muss ggf. angepasst werden, abhängig davon wie die Schnittstelle in eurem Setup tatsächlich heißt.

Es gibt natürlich noch andere Ansätze, die IP-Auflösung durchzuführen, aber für mein Setup ist dies ein sehr einfacher Weg. Ein Nachteil: sollten mehrere Peers vorhanden sein, klappt dieser Ansatz nicht so einfach – dann müsste man erst einmal den richtigen Peer per Regex ermitteln, um dann dort die entsprechenden Daten auszulesen.

Nötig ist dieses Script für das Aufrechterhalten der Verbindung in meinem FreeNAS-Replications-Setup, welches jetzt mit Wireguard funktioniert.

Ergänzung: IP-Check mit mehreren Peers

Wer in seiner Wireguard-Config mehrere Peers eintragen hat (z.B. eine statische Verbindung und einmal die Einwahl über ein Smartphone für ein VPN), will unter Umständen nur für einen Peer den hier beschriebenen IP-Check machen. Der einfachste Weg ist dabei, zusätzlich auf einen bestimmten Peer zu prüfen. Ausgehend von folgender Peer-Konfiguration (deren Werte keinem echten Peer entsprechen):

[Peer]
PublicKey = mhzqblUOAzxVhOypkidxLnxp5rfYD7uRtvyj0sOi4GE=
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = meinpeer.dyndns.net:51820

Muss die erste Zeile im Check-Script entsprechend angepasst werden:

cip=$(wg show wg0-client endpoints | grep -E "mhzqblUO" | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}") 	

Komplett sieht es dann so aus:

#!/bin/bash
# Status von der Schnittstelle überprüfen
# wg0-client: Name der Schnittstelle, die geprüft werden soll
# meinpeer.dyndns.net: der Name des Peers, dessen IP geprüft werden soll
        
cip=$(wg show wg0-client endpoints | grep -E "mhzqblUO" | grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}") 	
echo "$cip"
digIP=$(dig +short meinpeer.dyndns.net) # Die Adresse des Peers muss angepasst werden
   echo "$digIP"
     if [ "$digIP" != "$cip" ]
       then
          echo "Daten sind anders"
          /usr/sbin/service [email protected] restart
            
        else 
	  echo "Daten sind gleich"
	  #nichts zu tun
	 fi

Wichtig ist, dass das Check-Script in der Variante mit bestimmten Peers nicht funktionieren wird, wenn ihr den entsprechenden Wert nicht gegen den aus eurem Setup ersetzt. In meinem Setup lasse ich es alle 5min laufen, bisher hat es seinen Zweck soweit erfüllt. Da ein reiner abgleich der IP-Adresse stattfindet, sollte es auch in einem IPv6-Setup funktionieren – da ich jedoch noch einen klassischen Telekom-Anschluss mit IPv4 verwende, habe ich mich mit der Thematik nicht näher auseinander gesetzt. Falls jemand der Leser damit erfahrung hat (auch was DynDNS und IPv6 an der Fritzbox angeht) kann er gerne etwas in den Kommentaren hinterlassen!

10 Gedanken zu "Wireguard: Peer-IP-Check".

    1. Das Script gibt es tatsächlich auch für Debian, liegt dann in

      /usr/share/doc/wireguard-tools/examples/reresolve-dns/reresolve-dns.sh
      (der Pfad ist minimal anders als unter Arch)

      Muss ich mir noch mal genauer anschauen, als ich das eingerichtet habe gab es soweit ich mich erinnere irgendein Problem mit dem Script.

  1. Das sollte sich doch leichter mit Hilfe der „PersistentKeepalive =“ Option lösen lassen.

    Die Verbindung initiiere ich von unterwegs (zum Beispiel vom iPhone) auf eine DynDNS-Adresse. Dank Keepalive wird alle 25 Sekunden ein Paket an die Gegenseite geschickt. Man kann davon ausgehen, dass es höchst unwahrscheinlich ist, dass sich die Adresse auf beiden Seiten gleichzeitig ändert. Also wird immer mindestens eine Seite des Tunnels erreicht.

    Wenn die jeweilige Gegenseite das Paket von einer anderen externen IP-Adresse erhält, das Crypto Key Routing aber ansonsten passt (stimmige Kombination aus privater IP-Adresse und Public Key) wird die Zuordnung der externen IP des Peers aktualisiert und nachfolgende Antworten kommen wieder korrekt an.

    Ich müsste Adresswechsel forcieren und explizit testen, um es ganz sicher sagen zu können, aber im Alltagsbetrieb hatte ich bislang weder mit iPhone/iPad noch mit Linux oder macOS Probleme mit abbrechenden oder toten Tunneln.

  2. Das funktioniert, weil der IP-Adressen abgleich beim Aufbau der Verbindung stattfindet. Ein Mobil-Gerät initialisiert dann doch öfter mal, z.B. wenn der Empfang zu schlecht war etc.

    Wenn man mit einem Setup von zwei festen DSL-Anschlüssen arbeitet, kann es durchaus sein, dass sich ein Ende ändert ohne das die Verbindung neu aufgebaut wird. Dann passt die Auflösung der DynDNS-Adresse nicht mehr und die Verbindung geht auf eine falsche IP. Dafür braucht es dann die Abgleich, entweder wie hier gepostet oder mit dem Script von Michael.

    Mit dem iPhone muss ich das tatsächlich auch nie machen, die Replikation geht aber am dritten Tag spätestens ins leere.

  3. Das ist eben gerade nicht so. Die DynDNS-Adresse, die man in der wg0.conf hinterlegt hat, wird für den initialen Verbindungsaufbau genutzt. Während aber eine Verbindung besteht, wird die Zuordnung von Peer zu Public-IP auch auf dem Server konstant durch neu eintreffende Pakete aktualisiert (siehe https://www.wireguard.com/#cryptokey-routing, Abschnitt „Built-In Roaming“; siehe https://www.wireguard.com/papers/wireguard.pdf, Abschnitt 2.1). Wireguard verhält sich da wie mosh und sollte sehr robust sein, wenn es um wechselnde IP-Adressen geht. Wichtig ist aber tatsächlich, dass immer der Peer, dessen öffentliche Adresse sich geändert hat, zeitnah eine Kommunikation beginnt, um die anderen über die Änderung zu informieren. Der Server dürfte das in der Tat nicht so oft tun.

    Was ich gerade gelernt habe: der Keepalive wird nur gesendet, wenn ein Peer Pakete erhalten hat, aber eigentlich nicht antworten müsste. Vor Ablauf des KeepAlive-Timers wird dann ein leeres Wireguard-Antwortpaket gesendet. Es muss also das Gegenüber tatsächlich regelmäßig etwas senden, damit der Mechanismus zuverlässig funktioniert. Für sich alleine genommen ist er demnach nicht geeignet, um die Adresstabellen der Peers dauerhaft auf aktuellem Stand zu halten. Da lag ich also falsch. Von daher hast Du auch mit dem iPhone recht. Hier werden sicherlich öfter mal Verbindungen komplett neu aufgebaut, wodurch die Problematik der wechselnden Server-IP nicht so sehr spürbar wird. Es fühlt sich aber so an, als ob der Tunnel einfach immer da ist, solange eine Internetverbindung besteht.

    Wenn Ihr im DSL-NAT-Aufbau mit wechselnder Server-IP aber dafür sorgt, dass aus den Netzwerken beider Peers regelmäßig mal eine Nachricht gesendet wird, zum Beispiel durch regelmäßige beiderseitige Pings im Minutentakt (Cron-Job auf den beiden FreeNAS?!), dann darf die VPN-Verbindung nie bzw. nur kurz ins Leere gehen, weil zeitnah die aktuelle IP-Adresse bekannt sein wird. Wie schnell, das hängt von der Frequenz der Pings ab.

    Auf diesem Wege muss man nicht regelmäßig die Netzwerk-Schnittstelle wegnehmen und das Routing ändern. Das fühlt sich etwas eleganter an (meine Meinung).

    1. Ein Problem ist wohl auch noch, dass im blödesten Fall bei einem Setup mit zwei DSL-Anschlüssen ein Peer versucht die IP des anderen Aufzulösen während bei diesem der automatische Reconnect (den einige Provider nach wie vor machen) durchgeführt wird – Wireguard gibt hier wohl recht schnell komplett auf: https://lists.zx2c4.com/pipermail/wireguard/2019-February/003866.html

      Wenn es erstmal ausgestiegen ist, ist der neustart der Schnittstelle recht zuverlässig, um wieder eine Verbindung zu bekommen. In meinem Fall werden auch nur einmal pro Stunde Daten übertragen.

      Aber das ist ja das schöne: je nach konkretem Anwendungszweck führen verschiedene Wege zu Ziel 😉

  4. Hallo,
    ich habe ebenfalls genau dieses Szenario.
    Ich habe auf meinem Phone die Android-App installiert. In der conf-Datei für diesen Peer ist die DynDns meiner FritzBox eingetragen. Der Wireguard-Server befindet sich zuhause im Netzwerk hinter der FritzBox auf einem Raspberry. Auf beiden ist KeepAlive eingetragen mit 25. App gestartet und alles funktioniert bestens.
    Bis zur Zwangstrennung und den Reconnect durch den DSL-Anbieter. Der Tunnel ist unterbrochen, keine Verbindung, nichts.
    Ich habe die Timer-Unit mit dem o. a. Script reresolve-dns.sh eingerichtet – kein Erfolg.
    Bin etwas ratlos.

    Grüße

    Harald

    1. Die Beobachtung von Harald kann ich so bestätigen.
      IMHO müsste der Android Client die Konnektivität testen und neu initialisieren mit neuem Auflösen der ’server‘ Peers. Also müssten wir eine Android App haben, die das hier unter Ubuntu / Debian gesagte auch umsetzt.
      Oder liege ich da komplett falsch? Mir scheint es jedenfalls, als ob wir ohne Änderung an den Android App keine Verhaltensänderung erreichen können.
      Grüße
      Markus

  5. Hi Falk, thanks for the script! The second to last line can’t be right, I guess it is supposed to say „echo ‚Nothing to do'“. Or am I missing something? Cheers Philipp

Einen Kommentar hinterlassen

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

de_DEDeutsch
Nach oben blättern