szemenovics~/doku
viktor@vsz:~/doku/projekte/netzwerk/wireguard-watchdog
WireGuardProxmoxDoppel-NATBashCron

WireGuard-Tunnel bricht täglich abDiagnose hinter Doppel-NAT und ein Watchdog, der den Tunnel selbst repariert

Mein Tunnel vom Proxmox-Server zu Hause zum VPS fiel einmal am Tag aus und kam nur per Neustart zurück. So bin ich systematisch vorgegangen, und so sammelt jetzt ein kleines Skript beim nächsten Ausfall die Beweise.

Datum
06.10.2026
Umgebung
Proxmox VE · Ubuntu-VPS
Aufwand
ca. 1 Stunde
Status
stabil · Ursache in Analyse

Problem & Aufbau

Mein Heimnetz ist über einen WireGuard-Tunnel mit einem VPS verbunden. Der VPS hat eine feste öffentliche IP und reicht Dienste aus dem Homelab (z. B. diese Website) über Nginx Proxy Manager nach außen weiter. Am heimischen Router muss dafür kein Port geöffnet werden.

WireGuard-Tunnel · UDP · durch beide NAT-Stufen
Symptom

Etwa einmal am Tag sind die Dienste nicht mehr erreichbar. Der Tunnel baut sich nicht von selbst wieder auf. Ein systemctl restart wg-quick@wg0 behebt es sofort, bis zum nächsten Tag.

Besonderheit: Doppel-NAT

Mein Heimnetz hängt hinter zwei Routern: Der eigene OpenWrt-Router bildet das Heimnetz, davor sitzt der Router des Internetanbieters. Beide übersetzen Adressen (NAT), jedes Paket wird also zweimal umgeschrieben.

  • Warum der VPS-Umweg? Für eine Portfreigabe von außen müsste man in beiden Routern Weiterleitungen einrichten, und die öffentliche IP wechselt trotzdem. Der Tunnel geht dagegen von innen nach außen auf. Das funktioniert durch jedes NAT, ohne eine einzige Portfreigabe.
  • Warum ist das für den Fehler wichtig? Jeder Router führt eine eigene Tabelle, welche UDP-Verbindung zu welchem Gerät gehört, und löscht Einträge nach eigenen Zeitlimits. Bei Doppel-NAT gibt es also zwei Stellen, an denen die Zuordnung verloren oder nach einem Reconnect veraltet sein kann.

Wie WireGuard Verbindungen hält

WireGuard läuft über UDP und kennt keine klassische „Verbindung“. Für die Fehlersuche sind vier Mechanismen wichtig:

MechanismusWas er tut
HandshakeDie Peers tauschen etwa alle 2 Minuten neue Schlüssel aus. Ein alter Handshake bedeutet einen toten Tunnel.
Endpoint-RoamingDer Server merkt sich, woher das letzte gültige Paket kam, und antwortet dorthin. Er folgt so einem IP-Wechsel automatisch.
PersistentKeepaliveDer Client hinter NAT sendet regelmäßig ein Lebenszeichen. Das hält den NAT-Eintrag offen und meldet eine neue IP sofort. Bei Doppel-NAT muss es beide Router-Tabellen offen halten.
MTUMaximale Paketgröße im Tunnel. Unterschiedliche Werte führen zu „Ping geht, Webseiten hängen“.

Diagnose

1

Zustand auf dem Proxmox

bash · Proxmox
wg show
Ausgabe (gekürzt)
interface: wg0
peer: <VPS-Key>
  endpoint: <VPS-IP>:<Port>
  allowed ips: <VPS-Tunnel-IP>/32
  latest handshake: 1 minute, 9 seconds ago
  persistent keepalive: every 25 seconds
Ergebnis

Handshake aktuell, Keepalive bereits gesetzt. Die naheliegendste Ursache, ein fehlendes Keepalive hinter NAT, fällt damit weg.

2

Gegenseite auf dem VPS

Mit grep -v PrivateKey zeigt man die Config, ohne den geheimen Schlüssel preiszugeben:

bash · VPS
cat /etc/wireguard/wg0.conf | grep -v PrivateKey
[Interface]
Address    = <VPS-Tunnel-IP>/24
MTU        = 1380
ListenPort = <Port>

[Peer]
# Proxmox zuhause – bewusst OHNE Endpoint
PublicKey  = <Proxmox-Key>
AllowedIPs = <Proxmox-Tunnel-IP>/32, <Heimnetz>/24
Ergebnis

Für den Proxmox ist kein fester Endpoint eingetragen. Der VPS lernt die wechselnde Heim-IP also selbst. Das ist korrekt.

3

MTU auf beiden Seiten

bash · beide Seiten
ip link show wg0 | grep mtu
Ergebnis

Beide Seiten: mtu 1380. Ein MTU-Problem ist ausgeschlossen.

Nebenbefund: Das Interface hatte auf dem Proxmox die Nummer 89. Jeder Neustart legt wg0 neu an. Die Zahl zeigt, wie oft schon von Hand neu gestartet wurde.

GeprüftErgebnis
PersistentKeepalive (Proxmox)✓ gesetzt, 25 s
Kein fester Endpoint (VPS)✓ korrekt
MTU beidseitig✓ 1380 / 1380
Ursache des Abbruchs? nur im Fehlerfall messbar

Erkenntnis

Beide Konfigurationen sind sauber. Die Ursache lässt sich nur im Moment des Ausfalls sehen. Ich brauche also ein Werkzeug, das genau dann Daten sammelt, ohne dass ich daneben sitzen muss.

Lösung: Watchdog mit Diagnose-Log

Ein kleines Bash-Skript auf dem Proxmox prüft alle 2 Minuten, ob der VPS durch den Tunnel erreichbar ist. Wenn nicht, hält es zuerst den Zustand fest und startet danach WireGuard neu. Der Tunnel ist nach höchstens etwa 2 Minuten wieder da, und der Ausfall ist dokumentiert.

/usr/local/bin/wg-watchdog.sh
#!/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LOG=/var/log/wg-watchdog.log
VPS_TUNNEL=<VPS-Tunnel-IP>
VPS_PUBLIC=<VPS-IP>

if ! ping -c 3 -W 2 "$VPS_TUNNEL" > /dev/null 2>&1; then
    {
        echo "===== $(date) Tunnel down ====="
        echo "--- Öffentliche IP:";       curl -4 -s --max-time 5 ifconfig.me; echo
        echo "--- wg show:";              wg show wg0
        echo "--- Route zum VPS:";        ip route get "$VPS_PUBLIC"
        echo "--- Ping VPS ohne Tunnel:"; ping -c 2 -W 2 "$VPS_PUBLIC" | tail -2
    } >> "$LOG" 2>&1
    systemctl restart wg-quick@wg0
    sleep 5
    echo "--- Nach Neustart: $(ping -c 1 -W 2 "$VPS_TUNNEL" > /dev/null \
        && echo OK || echo IMMER NOCH DOWN)" >> "$LOG"
fi

Die Platzhalter in spitzen Klammern durch die eigenen Werte ersetzen.

Zeile für Zeile erklärt
CodeBedeutung
PATH=…Cron startet Skripte mit minimalem Suchpfad. Ohne diese Zeile werden wg oder ip evtl. nicht gefunden.
ping -c 3 -W 23 Pings mit je 2 Sekunden Timeout durch den Tunnel.
> /dev/null 2>&1Ausgabe verwerfen. Es zählt nur, ob der Ping Erfolg hatte.
if ! …Das ! kehrt das Ergebnis um. Der Block läuft nur bei einem Ausfall.
{ … } >> "$LOG" 2>&1Alles in den Klammern wird an das Log angehängt, Fehler inklusive.
$(date)Zeitstempel. Daran sieht man, ob die Ausfälle immer zur gleichen Uhrzeit passieren.
curl -4 ifconfig.meAktuelle öffentliche IPv4. Zeigt, ob sich die Heim-IP geändert hat.
wg show wg0Endpoint und letzter Handshake im Moment des Ausfalls.
ip route getWelche Route der Server zum VPS nimmt. Zeigt Routing-Fehler.
ping … | tail -2Ist der VPS ohne Tunnel erreichbar? Unterscheidet einen Internet-Ausfall von einem WireGuard-Problem.
systemctl restart wg-quick@wg0Tunnel neu starten.
&& … || …Kurzform für „wenn erfolgreich, dann OK, sonst IMMER NOCH DOWN“.

Einrichtung

1

Skript anlegen

Skript einfügen, speichern mit Strg+O und Enter, beenden mit Strg+X.

bash · Proxmox
nano /usr/local/bin/wg-watchdog.sh
2

Ausführbar machen

bash · Proxmox
chmod +x /usr/local/bin/wg-watchdog.sh
3

Cronjob anlegen

Beim ersten Aufruf fragt das System nach einem Editor, 1 = nano.

bash · Proxmox
crontab -e

Ganz unten diese Zeile eintragen:

crontab
*/2 * * * * /usr/local/bin/wg-watchdog.sh
4

Kontrollieren

bash · Proxmox
crontab -l | tail -1
head -3 /usr/local/bin/wg-watchdog.sh
Gutes Zeichen

cat /var/log/wg-watchdog.log meldet „No such file or directory“? Perfekt. Das Log entsteht erst beim ersten Ausfall.

Log auswerten

Im LogBedeutungNächster Schritt
Neue öffentliche IP, alter HandshakeKein neuer Handshake nach IP-WechselBeide NAT-Stufen prüfen: veralteter Eintrag im OpenWrt nach Reconnect des Provider-Routers
VPS auch ohne Tunnel nicht erreichbarInternetanschluss war wegKein WireGuard-Problem
Frischer Handshake, Ping scheitertRouting oder Firewalliptables/nftables und Routen prüfen
„IMMER NOCH DOWN“Neustart allein hilft nichtVPS-Seite und Firewall prüfen
Immer gleiche UhrzeitGeplanter VorgangMit Router-Log und Cronjobs abgleichen

Stolperfallen

  • Auf welchem Host bin ich? Der Prompt (root@proxmox oder root@vps) verrät es. Ein Ping auf die eigene Tunnel-IP antwortet in 0,04 ms und sagt nichts über den Tunnel.
  • Nur den Befehl kopieren, nicht den Prompt und nicht die alte Ausgabe. Sonst versucht die Bash, root@…:~# auszuführen.
  • Public Keys sind nicht geheim. Schützen muss man nur den Private Key, den wg show ohnehin als (hidden) ausgibt.
  • Diagnosetests im richtigen Moment: Läuft der Tunnel gerade, sieht jeder Test gesund aus. Deshalb sammelt der Watchdog die Daten automatisch beim Ausfall.

Fazit

Statt im Dunkeln an Einstellungen zu drehen, habe ich zuerst beide Seiten systematisch geprüft. Keepalive, Endpoint-Handling und MTU waren korrekt. Der Watchdog löst das praktische Problem sofort: Ausfälle dauern jetzt höchstens etwa 2 Minuten, und niemand muss mehr eingreifen. Gleichzeitig liefert er die Daten, um die eigentliche Ursache zu finden.

Verdacht

Am wahrscheinlichsten ist das Doppel-NAT: Wechselt der Provider-Router seine öffentliche IP, kann im OpenWrt noch ein alter UDP-Eintrag stehen, und die Pakete des Proxmox laufen ins Leere. Ein Neustart von WireGuard erzeugt einen neuen Eintrag, deshalb hilft er.

Update folgt

Sobald das Log den ersten Ausfall festgehalten hat, ergänze ich hier die Ursache und die endgültige Lösung.

← Alle Projekte Anleitung: Dell DW5821e