From d7e3c4c8433bcb3edf81784d737478671a7c70c2 Mon Sep 17 00:00:00 2001 From: Pascal Bouquet Date: Thu, 18 Sep 2025 10:00:44 +0200 Subject: [PATCH] 99-Captive portal completely revised, routines added --- 99-captive-portal | 168 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 145 insertions(+), 23 deletions(-) diff --git a/99-captive-portal b/99-captive-portal index 2f10ada..9e34f0b 100755 --- a/99-captive-portal +++ b/99-captive-portal @@ -1,54 +1,176 @@ #!/usr/bin/env bash -# Konfiguration -LOG_FILE="/var/log/nm-captive.log" +# ============================================================================= +# 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-Funktion log() { - echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE" + 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() { - # Teste mit Google's Connectivity Check (sollte 204 zurückgeben) - local url="http://connectivitycheck.gstatic.com/generate_204" - local http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "$url") + local captive_detected=false - if [ $? -ne 0 ]; then - log "Network error - captive portal likely" + 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 - fi - - if [ "$http_code" = "204" ]; then - log "Connectivity check passed (204) - no captive portal" - return 0 else - log "Connectivity check failed (HTTP $http_code) - captive portal detected" - return 1 + log "INFO" "All connectivity checks passed - no captive portal" + return 0 fi } -log "=== Dispatch triggered: $1 $2 ===" +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 "CAPTIVE PORTAL DETECTED! Opening browser..." + log "INFO" "CAPTIVE PORTAL DETECTED! Opening browser..." - # Finde Benutzer und starte Firefox + # 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 im Hintergrund + # Starte Firefox sudo -u $local_user env DISPLAY=:0 XAUTHORITY=/home/$local_user/.Xauthority \ firefox --new-window "http://detectportal.firefox.com/canonical.html" & - log "Firefox started for user $local_user" + 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 "No captive portal detected" + log "INFO" "No captive portal detected on connection start" fi + +elif [[ "$1" == wl* ]] && [ "$2" = "down" ]]; then + log "INFO" "WLAN interface $1 disconnected" + fi -log "=== Completed ===" +log "INFO" "=== Completed ===" +