Misst kontinuierlich, ob ein WireGuard-Tunnel wirklich funktioniert — nicht nur ob die App "verbunden" anzeigt. Zwei Tools im Paket: ein Browser-Dashboard zum Live-Mitlesen und ein Terminal-Skript für Langzeitmessungen über Stunden oder Tage.
VPN-Clients lügen. Nicht absichtlich, aber zuverlässig: Sie zeigen "verbunden" an, obwohl der Tunnel längst tot ist. Das passiert, weil der Client den Status anhand der lokalen Konfiguration bewertet — nicht anhand eines echten Test-Pakets, das tatsächlich am anderen Ende ankommt.
Konkret: WireGuard meldet "aktiv", solange das Interface auf dem System hochgefahren ist. Ob die letzten Pakete am Server angekommen sind, prüft die App nicht aktiv. Erst nach mehreren fehlgeschlagenen Handshakes — oft nach vielen Minuten — wird der Tunnel intern als "still" markiert. Bis dahin: trügerische Sicherheit.
Dieses Tool löst das, indem es aktiv und kontinuierlich ein Paket durch den Tunnel schickt — typischerweise einen Ping zur internen Server-IP, die nur durch den Tunnel erreichbar ist. Antwortet sie, lebt der Tunnel. Antwortet sie nicht, ist er tot. Mit Zeitstempel.
Bash-Skript für macOS und Linux. Misst im Terminal mit minimalem Footprint. Mit caffeinate auch bei geschlossenem Bildschirm. Schreibt persistente Logdatei.
Standalone-Browser-Dashboard. Doppelklick zum Starten. Live-Statusanzeige, Statistik, CSV-Export. Funktioniert auf jedem System mit Browser, kein Setup nötig.
Vollständige Anleitung als HTML. Click-to-Copy für jeden Befehl. Funktioniert offline, kein Internet nötig zum Lesen.
Browser-Tool speichert Verlauf in localStorage, Shell-Skript schreibt Logdatei. Auch nach Neustart sind Messungen abrufbar.
Das Skript ist ein einfaches Bash-Script ohne Abhängigkeiten — es nutzt nur Tools, die auf jedem macOS und jeder gängigen Linux-Distribution vorinstalliert sind: ping, date, sleep.
ZIP an eine feste Stelle entpacken — z.B. ins Home-Verzeichnis:
cd ~ unzip ~/Downloads/vpn-monitor-paket.zip -d vpn-monitor cd vpn-monitor
chmod +x vpn-monitor.sh
Kurzer Funktionstest mit Standardeinstellungen:
./vpn-monitor.sh
Wenn der Tunnel aktiv ist, sollte das Skript nach wenigen Sekunden ● Verbindung erkannt melden. Mit Strg+C beenden.
172.17.87.162 per Ping erreichbar sein. Diese IP ist nur durch den aktiven Tunnel zu erreichen — genau das ist der Sinn. Ist das Ziel in deinem Setup eine andere IP, siehe Anpassen.
./vpn-monitor.sh
# Test alle 5 Sekunden ./vpn-monitor.sh -i 5 # Anderes Test-Ziel ./vpn-monitor.sh -t 10.125.26.1 # Anderer Logdatei-Pfad ./vpn-monitor.sh -l ~/Desktop/vpn.log # Alles kombiniert ./vpn-monitor.sh -i 5 -t 10.125.26.1 -l ~/Desktop/vpn.log
Der Schlüssel-Trick für Langzeitmessungen über Stunden: caffeinate ist ein eingebautes macOS-Tool, das das System wachhält.
caffeinate -dis ./vpn-monitor.sh
Das Skript läuft damit durchgehend, auch wenn du weggehst und der Bildschirm schwarz wird. Erst Strg+C beendet beides — Skript und Wachhalten.
caffeinate in den Clamshell-Modus, sobald kein externer Monitor angeschlossen ist. MacBook offen lassen während der Messung — der Bildschirm darf aus gehen, das ist okay.
┌─────────────────────────────────────────────────┐ │ VPN-Monitor · Geno50 │ └─────────────────────────────────────────────────┘ Test-Ziel: 172.17.87.162 Intervall: 10s Logdatei: /Users/bigbrain/vpn-monitor.log Gestartet: 2026-04-30 15:58:40 Beenden mit Strg+C — Zusammenfassung wird gezeigt. Damit Mac nicht schläft: 'caffeinate -dis ./vpn-monitor.sh'. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 15:58:40 ● Verbindung erkannt 15:59:31 · online seit 51s (test #6) 16:00:42 · online seit 2m 02s (test #12) 16:01:53 · online seit 3m 13s (test #18) ... 17:42:19 ● VERBINDUNG VERLOREN war 1h 43m 39s online 17:42:30 ● Verbindung wiederhergestellt war 11s offline
Strg+C zeigt automatisch eine Zusammenfassung:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Monitoring beendet
Tests gesamt: 540
Abbrüche: 2
Längste Online-Zeit: 1h 43m 39s
Letzter Status: online seit 5m 12s
Logdatei: /Users/bigbrain/vpn-monitor.log
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Die Logdatei (Default: ~/vpn-monitor.log) ist eine einfache Textdatei mit Zeitstempel-Einträgen. Pro Status-Wechsel ein Eintrag.
cat ~/vpn-monitor.log
tail -20 ~/vpn-monitor.log
tail -f ~/vpn-monitor.log
grep "DOWN" ~/vpn-monitor.log
awk '{print $1}' ~/vpn-monitor.log | sort | uniq -c
2026-04-30 15:58:40 [START] Monitoring gestartet · target=172.17.87.162 interval=10s 2026-04-30 15:58:40 [UP] Initial-Status: online 2026-04-30 17:42:19 [DOWN] Verbindung verloren · Online-Phase dauerte 1h 43m 39s 2026-04-30 17:42:30 [UP] Verbindung wieder da · Offline-Phase dauerte 11s 2026-04-30 19:15:02 [STOP] Monitoring beendet · checks=540 fails=2 longest=1h 43m 39s
Das Browser-Tool ist eine einzelne HTML-Datei. Doppelklick öffnet sie im Standard-Browser. Keine Installation, keine Abhängigkeiten, keine Dateien außer der einen HTML.
ZIP entpacken, vpn-monitor.html doppelklicken. Die Seite lädt komplett offline — externe Schriften werden bei erster Internetverbindung geladen, danach nicht mehr nötig.
Im Eingabefeld Test-URL eintragen, was getestet werden soll:
| URL | Was testet das? |
|---|---|
| https://www.cloudflare.com/cdn-cgi/trace | Generelles Internet (Default) |
| http://172.17.87.162 | Interner Server — nur durch Tunnel erreichbar |
| https://intranet.firma.lokal | Internes Webportal |
Im Dropdown Intervall wählen, alle wieviel Sekunden gemessen werden soll. 10–20 Sekunden sind ein guter Kompromiss zwischen Reaktionszeit und Server-Last.
Start-Button drücken. Das Tool zeigt sofort:
Mit Export CSV wird der gesamte Verlauf als CSV-Datei mit deutschem Trennzeichen heruntergeladen — direkt in Excel oder Numbers öffnen, Pivot-Tabellen erstellen, Diagramme zeichnen.
Verlauf löschen (rote Schaltfläche) entfernt alle Events und Statistiken. Bestätigung erforderlich. Sinnvoll vor einer neuen Messreihe, damit alte Daten nicht die Statistik verfälschen.
Das Browser-Tool nutzt einen fetch() mit mode: 'no-cors' — es prüft nur, ob eine Antwort kommt, nicht den Inhalt. Damit funktioniert es auch mit Servern, die normalerweise CORS-restrictions haben. Der Test schreibt eine zufällige Query ans Ende der URL, damit kein Browser-Cache die Antwort fälscht.
| Anforderung | Shell | Browser |
|---|---|---|
| Schnell starten ohne Setup | — | ✓ |
| Kein Terminal-Wissen nötig | — | ✓ |
| Visuell ansprechend, gute Übersicht | — | ✓ |
| CSV-Export für Excel | — | ✓ |
| Über Stunden zuverlässig | ✓ | eingeschränkt |
| Über Nacht / Tage hinweg | ✓ | nein |
| Auch bei schwarzem Bildschirm | ✓ (mit caffeinate) | nein |
| Pingt interne IPs zuverlässig | ✓ | nur HTTP/HTTPS |
| Persistente Logdatei | ✓ | nur localStorage |
| Funktioniert auf Windows | via WSL/Git Bash | ✓ |
Default ist 172.17.87.162 — das ist der Geno50-DietPi. Für andere Setups das Ziel ändern. Für aussagekräftige Tunnel-Tests sollte das Ziel nur durch den Tunnel erreichbar sein.
# Per Argument: ./vpn-monitor.sh -t 192.168.1.1 # Oder fest in der Datei ändern (Zeile 22): TEST_TARGET="192.168.1.1"
Im Eingabefeld Test-URL eintragen — z.B.:
http://192.168.1.1 — Router-Webinterfacehttp://10.125.26.1 — WireGuard-Server-IPhttps://intranet.firma.lokal — Internes Web./vpn-monitor.sh -l ~/Documents/vpn-langzeit.log
Default ist 10 Sekunden. Schnelleres Polling reagiert empfindlicher auf kurze Aussetzer, erzeugt aber mehr Last:
# Alle 5 Sekunden ./vpn-monitor.sh -i 5 # Alle 30 Sekunden (für Tageslang-Messungen) ./vpn-monitor.sh -i 30
Das Test-Ziel ist nicht erreichbar. Prüfen:
# Manuell pingen — geht das? ping -c 3 172.17.87.162 # Tunnel-Status anschauen ifconfig utun0 # oder utun1, utun2 — je nach System # Routing-Tabelle netstat -rn | grep 172.17
Das Skript wurde nicht ausführbar gemacht. Korrigieren:
chmod +x vpn-monitor.sh
./vpn-monitor.sh
Sehr selten. Wenn doch, kombinieren mit pmset:
# Standby zeitweise komplett deaktivieren sudo pmset -a sleep 0 caffeinate -dis ./vpn-monitor.sh # Nach der Messung wieder normal stellen sudo pmset -a sleep 10
Die eingestellte Test-URL antwortet aus anderen Gründen nicht — vielleicht CORS-Header, Server down, falscher Pfad. Auf Default-URL https://www.cloudflare.com/cdn-cgi/trace zurückstellen oder eine andere stabile URL versuchen.
Bei extrem langen Messreihen (>500 Events) wird der ältere Verlauf automatisch gekürzt. Falls Probleme: Verlauf löschen klicken oder im Browser den localStorage manuell leeren.
Das Skript ruft in einer Schleife ping -c 1 -t 4 <IP> auf. -c 1 sendet genau ein Paket, -t 4 setzt das Timeout auf 4 Sekunden. Der Exit-Code von ping verrät, ob eine Antwort kam:
Bei jedem Status-Wechsel wird ein Logeintrag geschrieben. Statusmeldungen zur Konsole erfolgen alle 60 Sekunden, um die Anzeige nicht zu überfluten.
Das Tool nutzt die fetch()-API mit mode: 'no-cors'. Damit prüft der Browser nur, ob ein TCP-Connect zustande kommt und der Server irgendetwas antwortet — der Inhalt wird nicht inspiziert. Das macht das Tool sehr robust gegenüber CORS-restriktiven Servern.
Eine zufällige Query (?cb=1714512345678) wird angehängt, damit weder Browser-Cache noch Service-Worker die Antwort fälschen.
Events werden in localStorage gespeichert (Schlüssel vpnwatch.events und vpnwatch.stats). Beim Laden der Seite wird der Verlauf automatisch wieder hergestellt. Maximal 500 Events werden behalten — ältere werden beim Speichern abgeschnitten, um die Speichergrenze nicht zu sprengen.
Eine öffentliche IP wie 8.8.8.8 ist auch ohne Tunnel erreichbar — Mac hat ja Internet, mit oder ohne VPN. Ein Test gegen 8.8.8.8 würde also auch dann "online" melden, wenn der Tunnel tot ist und der Verkehr direkt am VPN vorbei rausläuft.
Eine interne IP wie 172.17.87.162 dagegen ist nur durch den Tunnel erreichbar. Antwortet sie, lebt der Tunnel definitiv. Antwortet sie nicht, ist der Tunnel kaputt — egal was die VPN-App anzeigt. Genau das wollen wir messen.