#!/usr/bin/env bash # ============================================================================= # NetworkManager Captive Portal Auto-Detector # ============================================================================= # Erstellt von Pascal Bouquet am 16.09.2025 # Aktualisiert am 17.09.2025 # # Dieses Skript ist freie Software: Es kann frei verwendet, bearbeitet und # verbreitet werden. Es wird keine Garantie für die Funktionsfähigekeit übernommen. # ============================================================================= # ============================================================================= # KONFIGURATION # ============================================================================= LOG_FILE="/var/log/nm-captive.log" LOG_LEVEL="INFO" # NONE, DEBUG, INFO, WARNING, ERROR CHECK_INTERVAL=300 # 5 Minuten in Sekunden MAX_CHECKS=48 # Maximal 4 Stunde lang prüfen (48 * 5min) # Test-URLs für Captive Portal Erkennung TEST_URLS=( "http://captive.apple.com/hotspot-detect.html" "http://connectivitycheck.gstatic.com/generate_204" ) # ============================================================================= # FUNKTIONEN # ============================================================================= log() { local level=$1 local message=$2 # Kein Logging wenn LOG_LEVEL=NONE if [ "$LOG_LEVEL" = "NONE" ]; then return fi # Log-Level Filterung case $LOG_LEVEL in "DEBUG") echo "$(date '+%Y-%m-%d %H:%M:%S') - $level - $message" >> "$LOG_FILE" ;; "INFO") if [[ "$level" != "DEBUG" ]]; then echo "$(date '+%Y-%m-%d %H:%M:%S') - $level - $message" >> "$LOG_FILE" fi ;; "WARNING") if [[ "$level" == "WARNING" || "$level" == "ERROR" ]]; then echo "$(date '+%Y-%m-%d %H:%M:%S') - $level - $message" >> "$LOG_FILE" fi ;; "ERROR") if [[ "$level" == "ERROR" ]]; then echo "$(date '+%Y-%m-%d %H:%M:%S') - $level - $message" >> "$LOG_FILE" fi ;; esac } check_captive_portal() { local captive_detected=false for url in "${TEST_URLS[@]}"; do log "DEBUG" "Testing URL: $url" if [[ "$url" == *"apple.com"* ]]; then # Apple Check: Erwartet "Success" in der Response local response=$(curl -s -L --connect-timeout 5 "$url") if [ $? -ne 0 ]; then log "DEBUG" "Network error for $url" captive_detected=true break elif ! echo "$response" | grep -qi "success"; then log "DEBUG" "Apple check failed - no 'Success' in response" captive_detected=true break fi elif [[ "$url" == *"google"* || "$url" == *"gstatic"* ]]; then # Google Check: Erwartet HTTP 204 local http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$url") if [ $? -ne 0 ]; then log "DEBUG" "Network error for $url" captive_detected=true break elif [ "$http_code" != "204" ]; then log "DEBUG" "Google check failed - HTTP $http_code instead of 204" captive_detected=true break fi fi done if [ "$captive_detected" = true ]; then log "INFO" "Captive portal detected" return 1 else log "INFO" "All connectivity checks passed - no captive portal" return 0 fi } start_periodic_checks() { local interface="$1" local user="$2" local check_count=0 log "INFO" "Starting periodic checks for $interface (every ${CHECK_INTERVAL}s)" while [ $check_count -lt $MAX_CHECKS ]; do sleep $CHECK_INTERVAL ((check_count++)) log "DEBUG" "Periodic check $check_count/$MAX_CHECKS for $interface" if ! check_captive_portal; then log "INFO" "Captive portal still active - re-opening browser" export DISPLAY=:0 export XAUTHORITY=/home/$user/.Xauthority # Starte Firefox mit Firefox's eigenem Portal Detect sudo -u $user env DISPLAY=:0 XAUTHORITY=/home/$user/.Xauthority \ firefox --new-window "http://detectportal.firefox.com/canonical.html" & log "INFO" "Firefox re-started for user $user" else log "INFO" "Captive portal resolved - stopping periodic checks" break fi done log "INFO" "Periodic checks completed for $interface" } # ============================================================================= # HAUPTPROGRAMM # ============================================================================= log "INFO" "=== Dispatch triggered: $1 $2 ===" if [[ "$1" == wl* ]] && [ "$2" = "up" ]; then sleep 3 if ! check_captive_portal; then log "INFO" "CAPTIVE PORTAL DETECTED! Opening browser..." # Finde Benutzer local_user=$(w -hs | grep ":0" | awk '{print $1}' | head -n1) if [ -n "$local_user" ]; then log "INFO" "Found user: $local_user" export DISPLAY=:0 export XAUTHORITY=/home/$local_user/.Xauthority # Starte Firefox sudo -u $local_user env DISPLAY=:0 XAUTHORITY=/home/$local_user/.Xauthority \ firefox --new-window "http://detectportal.firefox.com/canonical.html" & log "INFO" "Firefox started for user $local_user" # Starte periodische Checks im Hintergrund start_periodic_checks "$1" "$local_user" & else log "WARNING" "No local user found for GUI access" fi else log "INFO" "No captive portal detected on connection start" fi elif [[ "$1" == wl* ]] && [ "$2" = "down" ]]; then log "INFO" "WLAN interface $1 disconnected" fi log "INFO" "=== Completed ==="