99-Captive portal completely revised, routines added

This commit is contained in:
Pascal Bouquet 2025-09-18 10:00:44 +02:00
parent 8c338df532
commit d7e3c4c843

View File

@ -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
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 "Network error - captive portal likely"
return 1
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
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"
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
}
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 ==="