Internet-Monitoring auf RPI
Prüft auf
- Router Verfügbarkeit
- Third Hop beim Aufrufen von Google DNS (Verfügbarkeit des Services vom Provider)
- Verfügbarkeit von DNS-Auflösung
- Möglichkeit Daten per HTTP zu bekommen
Achtet auf Installationen von PiHole oder Adguard Home, die die Prüfmethode für den Provider-Hop nach traceroute brechen würden...
Log Rotation bei 10 MB.
Raspbian bringt traceroute nicht von Haus aus mit
sudo apt install traceroute
Generator Claude Sonnet 4 für Linux 6.6.28+rpt-rpi-v8 aarch64
#!/bin/bash
# Internet Connection Monitor Script für Raspbian
# Überwacht Gateway-Erreichbarkeit und Internet-Konnektivität
# Autor: Generated Script
# Version: 1.0
# Konfiguration
LOG_FILE="/var/log/internet_monitor.log"
MAX_LOG_SIZE=10485760 # 10MB in Bytes
TIMEOUT=5 # Ping Timeout in Sekunden
PING_COUNT=3 # Anzahl Ping-Pakete
# DNS Server für Konnektivitätstests
DNS_SERVERS=("8.8.8.8" "1.1.1.1" "9.9.9.9")
# Farben für Terminal-Ausgabe (falls direkt ausgeführt)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Funktion: Timestamp generieren
get_timestamp() {
date '+%Y-%m-%d %H:%M:%S'
}
# Funktion: Log-Datei rotieren wenn zu groß
rotate_log() {
if [[ -f "$LOG_FILE" && $(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null) -gt $MAX_LOG_SIZE ]]; then
mv "$LOG_FILE" "${LOG_FILE}.old"
echo "$(get_timestamp) - Log-Datei rotiert" >> "$LOG_FILE"
fi
}
# Funktion: Gateway ermitteln
get_default_gateway() {
ip route show default | awk '/default/ { print $3; exit }'
}
# Funktion: Provider Next Hop ermitteln (echter Provider-Hop, nicht AdGuard)
get_provider_nexthop() {
local gateway=$(get_default_gateway)
if [[ -n "$gateway" ]]; then
# Traceroute zum ersten externen DNS-Server
local traceroute_output=$(traceroute -n -m 5 -w 2 8.8.8.8 2>/dev/null)
# Durchsuche Hops 2-4 nach dem ersten nicht-privaten IP (Provider-Hop)
for hop in {2..4}; do
local hop_ip=$(echo "$traceroute_output" | awk -v hop="$hop" 'NR==hop+1 {print $2}' | head -1)
# Prüfe ob IP gesetzt und nicht leer/privat/loopback ist
if [[ -n "$hop_ip" && "$hop_ip" != "*" && "$hop_ip" != "* * *" ]]; then
# Prüfe ob es eine öffentliche IP ist (nicht RFC1918/Loopback/AdGuard)
if ! is_private_ip "$hop_ip"; then
echo "$hop_ip"
return 0
fi
fi
done
fi
echo ""
}
# Funktion: Prüfen ob IP privat/loopback/AdGuard ist
is_private_ip() {
local ip="$1"
# Prüfe auf private/reservierte IP-Bereiche
if [[ "$ip" =~ ^10\. ]] || \
[[ "$ip" =~ ^172\.(1[6-9]|2[0-9]|3[01])\. ]] || \
[[ "$ip" =~ ^192\.168\. ]] || \
[[ "$ip" =~ ^127\. ]] || \
[[ "$ip" =~ ^192\.0\.0\. ]] || \
[[ "$ip" =~ ^169\.254\. ]]; then
return 0 # ist privat
else
return 1 # ist öffentlich
fi
}
# Funktion: Netzwerk-Interface des Standard-Gateways ermitteln
get_gateway_interface() {
ip route show default | awk '/default/ { print $5; exit }'
}
# Funktion: Ping-Test durchführen
ping_test() {
local target="$1"
local description="$2"
if ping -c $PING_COUNT -W $TIMEOUT "$target" >/dev/null 2>&1; then
echo "$(get_timestamp) - ✓ $description ($target) - ERREICHBAR" >> "$LOG_FILE"
return 0
else
echo "$(get_timestamp) - ✗ $description ($target) - NICHT ERREICHBAR" >> "$LOG_FILE"
return 1
fi
}
# Funktion: DNS-Auflösung testen
dns_test() {
local test_domain="google.com"
if nslookup "$test_domain" >/dev/null 2>&1; then
echo "$(get_timestamp) - ✓ DNS-Auflösung ($test_domain) - FUNKTIONIERT" >> "$LOG_FILE"
return 0
else
echo "$(get_timestamp) - ✗ DNS-Auflösung ($test_domain) - FEHLGESCHLAGEN" >> "$LOG_FILE"
return 1
fi
}
# Funktion: HTTP/HTTPS Konnektivität testen
http_test() {
local test_url="http://www.google.com"
if curl -s --connect-timeout $TIMEOUT --max-time $((TIMEOUT*2)) "$test_url" >/dev/null 2>&1; then
echo "$(get_timestamp) - ✓ HTTP-Konnektivität ($test_url) - FUNKTIONIERT" >> "$LOG_FILE"
return 0
else
echo "$(get_timestamp) - ✗ HTTP-Konnektivität ($test_url) - FEHLGESCHLAGEN" >> "$LOG_FILE"
return 1
fi
}
# Funktion: Netzwerk-Informationen sammeln
collect_network_info() {
local gateway=$(get_default_gateway)
local provider_hop=$(get_provider_nexthop)
local interface=$(get_gateway_interface)
local ip_addr=$(ip addr show "$interface" 2>/dev/null | grep "inet " | head -n1 | awk '{print $2}' | cut -d'/' -f1)
echo "$(get_timestamp) - Netzwerk-Info: Interface=$interface, IP=$ip_addr, Gateway=$gateway, Provider-NextHop=$provider_hop" >> "$LOG_FILE"
}
# Funktion: Vollständige Verbindungsprüfung
check_connectivity() {
echo "$(get_timestamp) - === Internet-Konnektivitätsprüfung gestartet ===" >> "$LOG_FILE"
# Log rotieren falls nötig
rotate_log
# Netzwerk-Informationen sammeln
collect_network_info
local gateway=$(get_default_gateway)
local provider_nexthop=$(get_provider_nexthop)
local gateway_reachable=false
local provider_reachable=false
local internet_reachable=false
local dns_working=false
local http_working=false
# Gateway-Erreichbarkeit prüfen
if [[ -n "$gateway" ]]; then
if ping_test "$gateway" "Gateway"; then
gateway_reachable=true
fi
else
echo "$(get_timestamp) - ✗ Kein Standard-Gateway gefunden!" >> "$LOG_FILE"
fi
# Provider Next Hop prüfen (wichtigster Test für Providerseite!)
if $gateway_reachable; then
if [[ -n "$provider_nexthop" ]]; then
if ping_test "$provider_nexthop" "Provider Next Hop"; then
provider_reachable=true
fi
else
echo "$(get_timestamp) - ! Provider Next Hop konnte nicht ermittelt werden (AdGuard/Firewall?)" >> "$LOG_FILE"
# Fallback: Teste externe DNS direkt
for dns_server in "${DNS_SERVERS[@]}"; do
if ping_test "$dns_server" "Fallback Provider Test"; then
provider_reachable=true
break
fi
done
fi
fi
# DNS-Server-Erreichbarkeit prüfen (falls Provider erreichbar)
if $provider_reachable || ($gateway_reachable && [[ -z "$provider_nexthop" ]]); then
for dns_server in "${DNS_SERVERS[@]}"; do
if ping_test "$dns_server" "DNS-Server"; then
internet_reachable=true
break
fi
done
fi
# DNS-Auflösung testen
if $internet_reachable; then
if dns_test; then
dns_working=true
fi
fi
# HTTP-Konnektivität testen
if $dns_working; then
if http_test; then
http_working=true
fi
fi
# Gesamtstatus bestimmen
local status="UNBEKANNT"
local status_code=3
if $http_working; then
status="VOLLSTÄNDIG FUNKTIONSFÄHIG"
status_code=0
elif $dns_working; then
status="DNS FUNKTIONIERT, HTTP PROBLEME"
status_code=1
elif $internet_reachable; then
status="INTERNET ERREICHBAR, DNS PROBLEME"
status_code=1
elif $provider_reachable; then
status="PROVIDER ERREICHBAR, INTERNET PROBLEME"
status_code=2
elif $gateway_reachable; then
status="NUR LOKALES NETZWERK - PROVIDER NICHT ERREICHBAR"
status_code=2
else
status="KEINE NETZWERKVERBINDUNG"
status_code=3
fi
echo "$(get_timestamp) - STATUS: $status (Code: $status_code)" >> "$LOG_FILE"
echo "$(get_timestamp) - === Prüfung beendet ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# Status auch auf stdout ausgeben (für manuelle Ausführung)
if [[ -t 1 ]]; then
case $status_code in
0) echo -e "${GREEN}✓ Internet: $status${NC}" ;;
1) echo -e "${YELLOW}⚠ Internet: $status${NC}" ;;
2) echo -e "${YELLOW}⚠ Internet: $status${NC}" ;;
3) echo -e "${RED}✗ Internet: $status${NC}" ;;
esac
fi
return $status_code
}
# Funktion: Hilfe anzeigen
show_help() {
echo "Internet Connection Monitor Script"
echo ""
echo "Verwendung: $0 [OPTION]"
echo ""
echo "Optionen:"
echo " -h, --help Zeige diese Hilfe"
echo " -l, --log Zeige die letzten Log-Einträge"
echo " -s, --status Führe eine einmalige Statusprüfung durch"
echo " -c, --config Zeige aktuelle Konfiguration"
echo ""
echo "Standard-Verhalten: Führe Konnektivitätsprüfung durch"
echo ""
echo "Log-Datei: $LOG_FILE"
}
# Funktion: Log-Einträge anzeigen
show_log() {
local lines=${1:-50}
if [[ -f "$LOG_FILE" ]]; then
echo "Letzte $lines Zeilen aus $LOG_FILE:"
echo "=" $(printf '=%.0s' {1..60})
tail -n "$lines" "$LOG_FILE"
else
echo "Log-Datei $LOG_FILE nicht gefunden."
fi
}
# Funktion: Konfiguration anzeigen
show_config() {
echo "Aktuelle Konfiguration:"
echo "========================"
echo "Log-Datei: $LOG_FILE"
echo "Max. Log-Größe: $((MAX_LOG_SIZE/1024/1024)) MB"
echo "Ping-Timeout: $TIMEOUT Sekunden"
echo "Ping-Count: $PING_COUNT Pakete"
echo "DNS-Server: ${DNS_SERVERS[*]}"
echo ""
echo "Aktuelles Gateway: $(get_default_gateway)"
echo "Gateway-Interface: $(get_gateway_interface)"
echo "Provider Next Hop: $(get_provider_nexthop)"
}
# Hauptprogramm
main() {
# Root-Rechte prüfen (für Log-Datei in /var/log)
if [[ $EUID -ne 0 && "$LOG_FILE" == /var/log/* ]]; then
echo "Warnung: Root-Rechte benötigt für Log-Datei in /var/log/"
echo "Verwende temporäre Log-Datei: /tmp/internet_monitor.log"
LOG_FILE="/tmp/internet_monitor.log"
fi
# Parameter verarbeiten
case "${1:-}" in
-h|--help)
show_help
exit 0
;;
-l|--log)
show_log "${2:-50}"
exit 0
;;
-s|--status)
check_connectivity
exit $?
;;
-c|--config)
show_config
exit 0
;;
"")
check_connectivity
exit $?
;;
*)
echo "Unbekannte Option: $1"
echo "Verwende '$0 --help' für Hilfe."
exit 1
;;
esac
}
# Script ausführen
main "$@"
Installation
sudo cp internet_monitor.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/internet_monitor.sh
Test
sudo /usr/local/bin/internet_monitor.sh --status
Cronjob
*/5 * * * * /usr/local/bin/internet_monitor.sh >/dev/null 2>&1