Files
geoip_shop_manager/README.md
2025-12-09 12:11:56 +01:00

32 KiB

GeoIP Shop Blocker Manager v3.1.0

Hybrid-System für temporäres GeoIP-Blocking auf Plesk-Servern mit mehreren Shops

Dieses Tool ermöglicht es, einzelne oder alle Shops auf einem Plesk-Server temporär für alle Zugriffe außerhalb einer gewählten Geo-Region zu sperren. Es kombiniert PHP-Level-Blocking mit optionaler CrowdSec Firewall-Integration für maximalen Schutz.

🎯 Features

  • Zwei Geo-Regionen: DACH (3 Länder) oder Eurozone+GB (22 Länder)
  • Präzises Blocking: PHP prüft gegen vollständige IP-Ranges (keine Fehlblockierungen)
  • Flexibler Modus: Wahl zwischen "PHP + CrowdSec" oder "Nur PHP"
  • Cache-Validierung: Sofortige Prüfung bei Aktivierung
  • Fail-Open: Bei Cache-Fehlern wird Traffic durchgelassen (nicht blockiert)
  • Selbstheilender Cache: Korrupte Cache-Dateien werden automatisch regeneriert
  • Doppelter Schutz: PHP-Level + Firewall-Level (CrowdSec) - optional
  • Automatische Synchronisation: Blockierte IPs werden automatisch an CrowdSec weitergegeben
  • Multi-Shop-Management: Verwaltung mehrerer Shops auf einem Server
  • Bulk-Operationen: Alle Shops gleichzeitig aktivieren/deaktivieren
  • Gesamtübersicht: Logs und Statistiken über alle Shops hinweg (Top 50 IPs)
  • Bot-Erkennung: Automatische Identifikation von bekannten Bots/Crawlern
  • Link11-Erkennung: Farbige Anzeige ob Shop hinter Link11 CDN ist
  • Auto-Deaktivierung: PHP-Blocking UND CrowdSec-Bans laufen nach 72 Stunden automatisch ab
  • Systemd-Service: Automatischer Start beim Booten
  • Sauberes Cleanup: Vollständige Deinstallation bei Deaktivierung
  • Plesk-kompatibel: Funktioniert mit Plesk-verwalteten Shops
  • CDN-kompatibel: PHP-only Modus für Link11, Cloudflare & Co.

🌍 Geo-Regionen

Region Icon Länder Beschreibung
DACH 🇩🇪🇦🇹🇨🇭 3 Deutschland, Österreich, Schweiz
Eurozone+GB 🇪🇺 22 DE, AT, CH, BE, CY, EE, ES, FI, FR, GB, GR, HR, IE, IT, LT, LU, LV, MT, NL, PT, SI, SK

Wann welche Region?

Situation Empfohlene Region
Nur deutschsprachige Kunden 🇩🇪🇦🇹🇨🇭 DACH
EU-weiter Versand 🇪🇺 Eurozone+GB
Schnellere Performance gewünscht 🇩🇪🇦🇹🇨🇭 DACH (weniger IP-Ranges)
Maximale Abdeckung 🇪🇺 Eurozone+GB

Performance-Vergleich

Region IP-Ranges RAM-Verbrauch Cache-Größe
🇩🇪🇦🇹🇨🇭 DACH ~3.000-4.000 ~5-10 MB ~100-200 KB
🇪🇺 Eurozone+GB ~12.000-15.000 ~15-25 MB ~500-900 KB

🆕 Neu in v3.1.0: Cache-Validierung & Fail-Open

Problem gelöst

Korrupte Cache-Dateien führten dazu, dass alle IPs blockiert wurden (403 für jeden Besucher).

Lösung

  1. Cache-Validierung bei Aktivierung: Cache wird sofort generiert und auf Mindestanzahl geprüft
  2. Fail-Open im PHP: Bei Cache-Fehlern wird Traffic durchgelassen statt blockiert
  3. Selbstheilung: Korrupter Cache wird automatisch gelöscht und neu generiert
DACH:     min. 1.000 IP-Ranges erwartet
Eurozone: min. 5.000 IP-Ranges erwartet

Wie funktioniert Fail-Open?

// Im PHP-Script:
if (!is_array($allowed_ranges) || count($allowed_ranges) < $min_ranges) {
    // Cache korrupt oder unvollständig → löschen
    @unlink($cache_file);
    
    // Neu laden versuchen...
    $allowed_ranges = download_allowed_ranges($allowed_countries);
}

// Wenn immer noch keine gültigen Ranges → Traffic durchlassen!
if (empty($allowed_ranges)) {
    error_log("GeoIP FAIL-OPEN: Could not load valid IP ranges");
    return; // Allow traffic instead of blocking everything
}

Vorteile:

  • Kein Total-Lockout bei Cache-Problemen
  • Selbstheilend (regeneriert automatisch)
  • Sicherer als Fail-Closed
  • Validierung bereits bei Aktivierung

🏗️ Architektur

Modus 1: PHP + CrowdSec 🛡️

Komponente 1: PHP-Script

  • Wird in die index.php des Shops integriert
  • Lädt IP-Ranges von ipdeny.com (je nach Region)
  • Prüft jede Anfrage gegen diese Ranges
  • Validiert Cache auf Mindestanzahl
  • Blockt Nicht-Region-IPs sofort mit HTTP 403
  • Schreibt blockierte IPs in Queue-Datei für CrowdSec
  • Fail-Open bei Cache-Problemen
  • Auto-Deaktivierung nach 72 Stunden

Komponente 2: Python Watcher (systemd service)

  • Läuft permanent im Hintergrund als root
  • Überwacht Queue-Dateien aller aktiven Shops
  • Fügt blockierte IPs automatisch zu CrowdSec hinzu
  • Vermeidet Duplikate durch In-Memory-Cache
  • Prüft alle 5 Sekunden auf neue IPs

Komponente 3: CrowdSec Firewall Bouncer

  • Blockiert IPs auf Firewall-Ebene (iptables/nftables)
  • Schützt ALLE Services (HTTP, HTTPS, SSH, FTP, etc.)
  • Übernimmt Bans für 72 Stunden
  • Deutlich performanter als PHP-Checks

Modus 2: Nur PHP 📝

  • Nur das PHP-Script wird aktiviert
  • Keine CrowdSec-Synchronisation
  • Kein Watcher-Service nötig
  • Ideal für Server hinter CDN/Proxy (Link11, Cloudflare, etc.)

Hinweis: Bei Servern hinter einem CDN/Reverse-Proxy (wie Link11, Cloudflare, Hetzner LB) sieht iptables nur die Proxy-IP, nicht die echte Client-IP. In diesem Fall ist der PHP-only Modus die bessere Wahl, da PHP die echte IP aus dem X-Forwarded-For Header liest.

📋 Voraussetzungen

  • Betriebssystem: Ubuntu Server (getestet auf 24.04)
  • Webserver: Apache mit mod_rewrite (oder nginx)
  • PHP: Version 8.0 oder höher
  • Python: Version 3.8 oder höher
  • CrowdSec: Installiert und aktiv (nur für PHP+CrowdSec Modus)
  • CrowdSec Firewall Bouncer: Installiert und konfiguriert (nur für PHP+CrowdSec Modus)
  • Plesk: Optional, aber empfohlen
  • Root-Zugriff: Erforderlich für Installation und Verwaltung

CrowdSec Installation prüfen (nur für PHP+CrowdSec Modus)

# Prüfe ob CrowdSec läuft
systemctl status crowdsec

# Prüfe ob Firewall Bouncer aktiv ist
cscli bouncers list

# Sollte zeigen:
# cs-firewall-bouncer-... mit ✔️ Valid und Recent Last API pull

Falls CrowdSec noch nicht installiert ist:

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
apt-get update
apt-get install crowdsec crowdsec-firewall-bouncer-iptables

🚀 Installation

1. Script herunterladen

# Als root
cd /root
wget https://git.jtl-hosting.de/thomasciesla/geoip_shop_manager/raw/branch/main/geoip_shop_blocker.py
chmod +x geoip_shop_blocker.py

2. Script ausführen

python3 geoip_shop_blocker.py

Das war's! Das Script ist vollständig selbstverwaltend.

📖 Verwendung

Hauptmenü

════════════════════════════════════════════════════════════════
  GeoIP Shop Blocker Manager v3.1.0
  🇩🇪🇦🇹🇨🇭 DACH | 🇪🇺 Eurozone+GB (22 Länder)
  🛡️  Mit Cache-Validierung und Fail-Open
════════════════════════════════════════════════════════════════
  ✅ CrowdSec
  ✅ Watcher-Service

────────────────────────────────────────
[1] Aktivieren (einzeln)
[2] Deaktivieren (einzeln)
[3] Logs anzeigen
[4] Status
────────────────────────────────────────
[5] 🚀 ALLE aktivieren
[6] 🛑 ALLE deaktivieren
────────────────────────────────────────
[0] Beenden

Geo-Region wählen

Bei jeder Aktivierung wird zuerst nach der Region gefragt:

🌍 Wähle die Geo-Region:
   [1] 🇩🇪🇦🇹🇨🇭 DACH - Deutschland, Österreich, Schweiz
   [2] 🇪🇺 Eurozone+GB - 22 Länder

Region wählen [1/2]: 

Blocking-Modus wählen

Danach wird nach dem Modus gefragt:

🔧 Wähle den Blocking-Modus:
   [1] PHP + CrowdSec (IPs werden an CrowdSec gemeldet)
   [2] Nur PHP (keine CrowdSec-Synchronisation)

Modus wählen [1/2]: 

Wann welchen Modus wählen?

Situation Empfohlener Modus
Server direkt im Internet PHP + CrowdSec 🛡️
Server hinter CDN (Link11, Cloudflare) Nur PHP 📝
CrowdSec nicht installiert Nur PHP 📝
Minimaler Overhead gewünscht Nur PHP 📝
Maximaler Schutz (alle Ports) PHP + CrowdSec 🛡️

Blocking aktivieren (einzelner Shop)

  1. Script starten: python3 geoip_shop_blocker.py
  2. Option [1] Aktivieren (einzeln) wählen
  3. Shop aus der Liste auswählen (farbig: 🟢 Link11, 🔴 Direkt)
  4. Geo-Region wählen (DACH oder Eurozone+GB)
  5. Modus wählen (PHP+CrowdSec oder Nur PHP)
  6. Bestätigen mit ja

Was passiert (PHP + CrowdSec Modus):

  • Bei ERSTEM Shop: Systemd-Service wird installiert und gestartet
  • Backup der index.php wird erstellt
  • geoip_blocking.php wird erstellt und eingebunden
  • Cache wird generiert und validiert
  • Shop wird für Tracking registriert
  • Blocking ist sofort aktiv
  • Erlaubt werden nur IPs aus gewählter Region

Was passiert (Nur PHP Modus):

  • Backup der index.php wird erstellt
  • geoip_blocking.php wird erstellt (ohne CrowdSec-Queue)
  • Cache wird generiert und validiert
  • Shop wird für Tracking registriert
  • Blocking ist sofort aktiv
  • Kein Watcher-Service nötig

Beispielausgabe:

🔧 Aktiviere 🇪🇺 Eurozone + GB GeoIP-Blocking für: shop.example.com
   Erlaubt: 22 Länder: DE, AT, CH, BE, CY, EE, ES, FI, FR, GB, GR, HR, IE, IT, LT, LU, LV, MT, NL, PT, SI, SK
   Modus: PHP + CrowdSec
════════════════════════════════════════════════════════════════

[1/4] Installiere CrowdSec-Watcher-Service...
  ✅ Service gestartet

[2/4] Aktiviere PHP-Blocking...
  ✅ PHP-Blocking aktiviert

[3/4] Generiere IP-Range-Cache (22 Länder)...
  ✅ Cache generiert: 12,345 IP-Ranges

[4/4] Registriere Shop...
  ✅ Shop registriert

════════════════════════════════════════════════════════════════
✅ 🇪🇺 Eurozone + GB GeoIP-Blocking aktiviert
   Shop: shop.example.com
   IP-Ranges: 12,345
   Gültig bis: 2025-12-12 10:30:00 CET
   🛡️  Fail-Open: Bei Cache-Fehlern wird Traffic durchgelassen
════════════════════════════════════════════════════════════════

Blocking für ALLE Shops aktivieren

  1. Script starten: python3 geoip_shop_blocker.py
  2. Option [5] 🚀 ALLE aktivieren wählen
  3. Liste der zu aktivierenden Shops wird angezeigt (farbig nach Link11-Status)
  4. Geo-Region wählen (gilt für alle Shops)
  5. Modus wählen (gilt für alle Shops)
  6. Bestätigen mit ja

Beispielausgabe:

══════════════════════════════════════════════════════════════
  GeoIP-Blocking für ALLE Shops aktivieren
══════════════════════════════════════════════════════════════

📋 5 Shop(s):
   • shop1.example.com [Link11]      ← grün
   • shop2.example.com [Direkt]      ← rot
   • shop3.example.com [Link11]
   ...

🌍 Wähle die Geo-Region:
   [1] 🇩🇪🇦🇹🇨🇭 DACH - Deutschland, Österreich, Schweiz
   [2] 🇪🇺 Eurozone+GB - 22 Länder

Region wählen [1/2]: 2

🔧 Wähle den Blocking-Modus:
   [1] PHP + CrowdSec (IPs werden an CrowdSec gemeldet)
   [2] Nur PHP (keine CrowdSec-Synchronisation)

Modus wählen [1/2]: 2

⚠️  Region: 🇪🇺 Eurozone + GB
   Modus: Nur PHP 📝

Fortfahren? (ja/nein): ja

══════════════════════════════════════════════════════════════

[1/5] shop1.example.com
   ⏳ Cache generieren...
   ✅ Aktiviert (12,345 Ranges)
...

══════════════════════════════════════════════════════════════
  ✅ 5 Shop(s) aktiviert
  🛡️  Fail-Open bei Cache-Fehlern aktiv
══════════════════════════════════════════════════════════════

Blocking deaktivieren (einzelner Shop)

  1. Script starten: python3 geoip_shop_blocker.py
  2. Option [2] Deaktivieren (einzeln) wählen
  3. Shop aus der Liste auswählen (zeigt Region und Modus an)
  4. Bestätigen mit ja

Was passiert:

  • Original index.php wird wiederhergestellt
  • Alle PHP-Dateien werden gelöscht (inkl. Cache)
  • Bei PHP+CrowdSec Modus: Alle CrowdSec-Decisions werden entfernt
  • Shop wird deregistriert
  • Bei LETZTEM Shop mit CrowdSec: Systemd-Service wird deinstalliert

Blocking für ALLE Shops deaktivieren

  1. Script starten: python3 geoip_shop_blocker.py
  2. Option [6] 🛑 ALLE deaktivieren wählen
  3. Liste der aktiven Shops wird angezeigt (mit Region-Icons)
  4. Bestätigen mit ja

Logs anzeigen

  1. Script starten: python3 geoip_shop_blocker.py
  2. Option [3] Logs anzeigen wählen
  3. Auswahl treffen:
📋 Logs für:
  [0] 📊 ALLE (Zusammenfassung)
  [1] shop1.example.com [Link11] 🇪🇺 🛡️
  [2] shop2.example.com [Direkt] 🇩🇪🇦🇹🇨🇭 📝
  ...

Die Icons zeigen:

  • 🛡️ = PHP + CrowdSec Modus
  • 📝 = Nur PHP Modus
  • 🇪🇺 = Eurozone+GB Region
  • 🇩🇪🇦🇹🇨🇭 = DACH Region
  • [Link11] grün = hinter Link11 CDN
  • [Direkt] rot = direkt erreichbar

Option [0]: Gesamtübersicht aller Shops

Zeigt eine aggregierte Statistik über alle aktiven Shops:

══════════════════════════════════════════════════════════════════════
  📊 GESAMTÜBERSICHT ALLER SHOPS
══════════════════════════════════════════════════════════════════════
   Grün = hinter Link11 | Rot = Direkt

📝 PHP-Blocks gesamt: 5037 (⌀ 125.3 req/min, Laufzeit: 40m)
   ├─ shop1.example.com 🇪🇺: 923 (23.0 req/min, seit 40m) ████████████████████
   │     └─➤ Top: 216.244.66.196 (DotBot) - 30x, 0.7 req/min
   ├─ shop2.example.com 🇩🇪🇦🇹🇨🇭: 412 (10.3 req/min, seit 40m) ████████████
   │     └─➤ Top: 40.77.167.48 (Bingbot) - 25x, 0.6 req/min
   └─ shop3.example.com 🇪🇺: 312 (7.8 req/min, seit 40m) ████████
         └─➤ Top: 52.167.144.139 (Bingbot) - 18x, 0.4 req/min

🛡️  CrowdSec-Bans gesamt: 892
   ├─ shop1.example.com 🇪🇺: 401 ████████████████
   ├─ shop2.example.com 🇩🇪🇦🇹🇨🇭: 298 ███████████
   └─ shop3.example.com 🇪🇺: 193 ███████

🔥 Top 50 blockierte IPs (alle Shops):
   40.113.19.56 (Bingbot): 146 (3.6 req/min) → shop1.example.com [89x] █████████████
   185.220.101.34 (Unbekannt): 127 (3.2 req/min) → shop2.example.com [65x] ██████████
   45.95.169.22 (SemrushBot): 89 (2.2 req/min) → shop1.example.com [52x] ███████
   ...

══════════════════════════════════════════════════════════════════════

Enthält:

  • Legende für Link11-Farben
  • PHP-Blocks pro Shop mit req/min, Laufzeit und visuellen Balken
  • Top-IP pro Shop mit Bot-Erkennung und req/min
  • CrowdSec-Bans pro Shop (nur für PHP+CrowdSec Shops, farbig nach Link11)
  • Top 50 der am häufigsten blockierten IPs mit:
    • Bot-Erkennung
    • req/min
    • Top-Shop für diese IP (farbig nach Link11)
    • Visuelle Balken

Option [1-n]: Einzelner Shop

Zeigt detaillierte Logs für einen spezifischen Shop:

══════════════════════════════════════════════════════════════════════
📊 shop1.example.com | 🇪🇺 Eurozone + GB
══════════════════════════════════════════════════════════════════════
⏱️  Laufzeit: 2h 30m
📈 Blocks: 1234 (8.2 req/min)
✅ Cache: 12,345 Ranges

📝 Letzte 30 Blocks:
[2025-12-09 10:24:57] IP: 202.8.43.232 | UA: Bytespider | URI: /produkt-123
[2025-12-09 10:24:55] IP: 45.95.169.22 | UA: SemrushBot/7 | URI: /kategorie
...

🔥 Top 10 IPs:
   202.8.43.232 (Bytespider): 127x
   45.95.169.22 (SemrushBot): 89x
   40.77.167.48 (Bingbot): 67x
   ...

Bei PHP-only Shops wird angezeigt:

📝 CrowdSec-Synchronisation ist für diesen Shop deaktiviert (PHP-only Modus)

Status prüfen

Option [4] Status zeigt:

📊 2/5 Shops aktiv
   shop1.example.com [Link11] 🇪🇺 🛡️
      1234 blocks, 2h 30m, Cache: ✅12,345
   shop2.example.com [Direkt] 🇩🇪🇦🇹🇨🇭 📝
      567 blocks, 1h 15m, Cache: ✅3,456

Zeigt pro Shop:

  • Link11-Status (farbig)
  • Geo-Region Icon
  • Modus Icon (🛡️ oder 📝)
  • Anzahl Blocks
  • Laufzeit
  • Cache-Status ( mit Anzahl oder ⚠️ bei Problemen)

🔧 Erweiterte Verwendung

Cache manuell regenerieren

# Cache für einen Shop löschen (wird automatisch neu generiert)
rm /var/www/vhosts/SHOP/httpdocs/geoip_ip_ranges.cache

Cache-Status prüfen

# Cache-Größe und Alter prüfen
ls -la /var/www/vhosts/SHOP/httpdocs/geoip_ip_ranges.cache

# Anzahl der Ranges im Cache
php -r 'echo count(unserialize(file_get_contents("/var/www/vhosts/SHOP/httpdocs/geoip_ip_ranges.cache")));'

Manuell CrowdSec Decisions prüfen

# Alle Decisions anzeigen (mit vollständiger Liste)
cscli decisions list --limit 0

# Nur GeoIP-Blocks anzeigen
cscli decisions list --limit 0 | grep "GeoIP"

# Decisions für einen bestimmten Shop
cscli decisions list --limit 0 | grep "shop.example.com"

Alle GeoIP-Decisions löschen (Einzeiler)

while cscli decisions list -o raw --limit 0 | grep -q "GeoIP"; do cscli decisions list -o raw --limit 0 | grep "GeoIP" | cut -d',' -f3 | cut -d':' -f2 | while read ip; do echo "🗑️  Lösche: $ip"; cscli decisions delete --ip "$ip" 2>/dev/null; done; done && echo "✅ Alle GeoIP-Decisions gelöscht"

Firewall-Statistiken prüfen

# Geblockte Pakete in iptables
iptables -L -n -v | grep crowdsec

# IPs im CrowdSec ipset
ipset list crowdsec-blacklists-5 | head -50

# Prüfe ob eine bestimmte IP gebannt ist
ipset test crowdsec-blacklists-5 1.2.3.4

Systemd-Service verwalten

# Status des Watcher-Service
systemctl status geoip-crowdsec-watcher.service

# Logs des Watcher-Service
journalctl -u geoip-crowdsec-watcher.service -f

# Service neu starten
systemctl restart geoip-crowdsec-watcher.service

Manuelle IP-Tests

# Eigene IP für 3 Minuten bannen (Test)
cscli decisions add --ip DEINE_IP --duration 3m --type ban --reason "Test"

# Prüfen ob Ban aktiv ist
ipset test crowdsec-blacklists-5 DEINE_IP

# Ban manuell entfernen
cscli decisions delete --ip DEINE_IP

📁 Dateistruktur

Pro Shop (in /var/www/vhosts/SHOP/httpdocs/)

Datei Beschreibung
index.php.geoip_backup Backup der Original index.php
geoip_blocking.php PHP-Blocking-Script
geoip_ip_ranges.cache Gecachte IP-Ranges (erneuert alle 24h)
geoip_blocked.log Log der PHP-Level Blocks
geoip_crowdsec_queue.log Queue für CrowdSec-Synchronisation (nur PHP+CrowdSec)

System-weit

Datei Beschreibung
/usr/local/bin/geoip_crowdsec_watcher.py Watcher-Service Script
/etc/systemd/system/geoip-crowdsec-watcher.service Systemd Service
/var/lib/crowdsec/geoip_active_shops.json Tracking aktiver Shops (inkl. Modus und Region)

⚙️ Konfiguration

Blocking-Dauer ändern

Standardmäßig 72 Stunden. Zum Ändern editiere das Python-Script:

# In activate_blocking() und activate_all_shops()
expiry = datetime.now() + timedelta(hours=72)  # Hier ändern

Watcher-Intervall ändern

Standard: 5 Sekunden. Im Watcher-Script:

CHECK_INTERVAL = 5  # In Sekunden

IP-Range-Cache-Dauer ändern

Standard: 24 Stunden. Im PHP-Script:

$cache_duration = 86400; // In Sekunden

Mindest-Ranges für Cache-Validierung ändern

MIN_RANGES = {
    "dach": 1000,      # Minimum für DACH
    "eurozone": 5000   # Minimum für Eurozone+GB
}

🛡️ Sicherheit

Was wird geblockt?

  • Alle IPs außerhalb der gewählten Region
  • Auf PHP-Ebene: Sofortiger 403 Response
  • Auf Firewall-Ebene (nur PHP+CrowdSec): Alle Ports (HTTP, HTTPS, SSH, FTP, etc.)

Was wird NICHT geblockt?

  • Alle IPs aus der gewählten Region (basierend auf RIPE/ipdeny.com Daten)
  • Private IPs (192.168.x.x, 10.x.x.x, etc.)
  • Localhost (127.0.0.1)
  • Bei Cache-Fehlern: Alle IPs (Fail-Open)

Fail-Open vs. Fail-Closed

Strategie Verhalten bei Cache-Fehler Risiko
Fail-Open Traffic durchlassen Kurzzeitig kein Schutz
Fail-Closed Alles blockieren Totaler Lockout möglich

Wir nutzen Fail-Open - lieber kurzzeitig keinen Schutz als alle Kunden aussperren!

Auto-Deaktivierung nach 72 Stunden

Beide Blocking-Mechanismen laufen automatisch aus:

  1. PHP-Blocking: Das Script prüft ein Ablaufdatum und macht return nach 72h
  2. CrowdSec-Bans: Werden mit --duration 72h erstellt

Sicherheitsfeature: Falls jemand vergisst zu deaktivieren, läuft der Schutz automatisch aus.

🌐 CDN/Reverse-Proxy Hinweise

Problem bei CDN-Nutzung (Link11, Cloudflare, etc.)

Wenn dein Server hinter einem CDN oder Reverse-Proxy steht:

Client (202.8.43.232) → CDN (85.131.143.x) → Dein Server
                              ↓
                 iptables sieht nur CDN-IP!

Folge: CrowdSec Firewall-Bouncer kann die echte Client-IP nicht blocken, da er nur die CDN-IP sieht.

Lösung: PHP-only Modus

Das PHP-Script liest die echte IP aus dem X-Forwarded-For Header:

  • Funktioniert auch hinter CDN/Proxy
  • Blockt zuverlässig auf Anwendungsebene
  • Kein unnötiger CrowdSec-Overhead

Empfehlung für CDN-Nutzer: Wähle bei der Aktivierung den Modus [2] Nur PHP.

Link11 Erkennung

Das Script erkennt automatisch ob ein Shop hinter Link11 ist:

  • 🟢 Grün [Link11] = Shop resolves zu 128.65.223.106
  • 🔴 Rot [Direkt] = Shop ist direkt erreichbar

Prüfen ob CDN aktiv ist

# Welche IPs verbinden sich zu nginx/Apache?
ss -tn state established '( sport = :80 or sport = :443 )' | head -20

# Wenn nur interne/CDN-IPs erscheinen → PHP-only Modus verwenden

🐛 Troubleshooting

Shop zeigt 403 für ALLE Besucher

Mögliche Ursache: Korrupter Cache (sollte mit v3.1.0 durch Fail-Open verhindert werden)

# Cache prüfen
php -r 'var_dump(unserialize(file_get_contents("/var/www/vhosts/SHOP/httpdocs/geoip_ip_ranges.cache")));'

# Cache löschen (regeneriert automatisch)
rm /var/www/vhosts/SHOP/httpdocs/geoip_ip_ranges.cache

# Oder: Blocking deaktivieren
python3 geoip_shop_blocker.py  # Option 2

Cache-Generierung schlägt fehl

Mögliche Ursachen:

  1. Keine Internet-Verbindung zu ipdeny.com
  2. Timeout bei vielen Ländern (Eurozone)
  3. ipdeny.com temporär nicht erreichbar
# Manuell testen
curl -v https://www.ipdeny.com/ipblocks/data/aggregated/de-aggregated.zone | head -20

Hinweis: Bei Cache-Fehlern greift Fail-Open - Traffic wird durchgelassen!

Shop zeigt 500 Error

Ursache: PHP-Syntax-Fehler oder falsche Einbindung

# Prüfe PHP-Fehler-Log
tail -50 /var/www/vhosts/SHOP/logs/error_log

# Stelle Original-Index wieder her
cd /var/www/vhosts/SHOP/httpdocs
mv index.php.geoip_backup index.php

# Deaktiviere via Script
python3 geoip_shop_blocker.py  # Option 2

Watcher-Service läuft nicht

# Status prüfen
systemctl status geoip-crowdsec-watcher.service

# Logs prüfen
journalctl -u geoip-crowdsec-watcher.service -n 100

# Service neu starten
systemctl restart geoip-crowdsec-watcher.service

CrowdSec Decisions werden nicht erstellt

# Prüfe ob Queue-Datei beschrieben wird
tail -f /var/www/vhosts/SHOP/httpdocs/geoip_crowdsec_queue.log

# Prüfe Watcher-Logs
journalctl -u geoip-crowdsec-watcher.service -f

# Prüfe CrowdSec API
cscli decisions add --ip 1.2.3.4 --duration 1m --type ban --reason "Test"
cscli decisions list | grep "1.2.3.4"
cscli decisions delete --ip 1.2.3.4

Firewall blockt nicht (trotz CrowdSec-Ban)

Mögliche Ursachen:

  1. CDN/Reverse-Proxy aktiv → Wechsle zu PHP-only Modus
  2. Bouncer läuft nicht:
    systemctl status crowdsec-firewall-bouncer
    
  3. iptables-Regeln fehlen:
    iptables -L -n -v | grep crowdsec
    

Cleanup nach Deaktivierung unvollständig

# Manuelle Bereinigung aller GeoIP-Decisions (Einzeiler mit Fortschritt)
while cscli decisions list -o raw --limit 0 | grep -q "GeoIP"; do cscli decisions list -o raw --limit 0 | grep "GeoIP" | cut -d',' -f3 | cut -d':' -f2 | while read ip; do echo "🗑️  Lösche: $ip"; cscli decisions delete --ip "$ip" 2>/dev/null; done; done && echo "✅ Alle GeoIP-Decisions gelöscht"

# Prüfen
cscli decisions list --limit 0 | grep "GeoIP"

Migration von älteren Versionen

Falls du von einer älteren Version wechselst:

# 1. Alle aktiven Shops deaktivieren (alte Version)
python3 geoip_shop_manager_old.py  # Option 6 (alle deaktivieren)

# 2. Alte Cache-Dateien löschen
rm /var/www/vhosts/*/httpdocs/dach_ip_ranges.cache

# 3. Neue Version verwenden
python3 geoip_shop_blocker.py  # Shops wieder aktivieren

📊 Performance

PHP-Level Blocking

Region Overhead pro Request Erster Request Cache-Dauer
🇩🇪🇦🇹🇨🇭 DACH ~2-5ms ~200-400ms 24h
🇪🇺 Eurozone+GB ~5-10ms ~800-1200ms 24h

CrowdSec Firewall Blocking (nur PHP+CrowdSec Modus)

  • Overhead: 0ms (blockt vor PHP)
  • RAM: ~20-50 MB (Watcher-Service)
  • Geblockte Pakete: Werden gar nicht erst an Apache weitergeleitet

Empfohlene Limits

Server RAM Max. Shops
Klein 2 GB 10
Mittel 4-8 GB 50
Groß 16+ GB Unbegrenzt

📝 Logs und Monitoring

PHP-Level Logs

# Blockierte IPs für einen Shop
tail -f /var/www/vhosts/SHOP/httpdocs/geoip_blocked.log

# Statistik
wc -l /var/www/vhosts/SHOP/httpdocs/geoip_blocked.log

CrowdSec Logs

# Watcher-Service Logs (Echtzeit)
journalctl -u geoip-crowdsec-watcher.service -f

# CrowdSec-Agent Logs
tail -f /var/log/crowdsec.log

# Firewall-Bouncer Logs
journalctl -u crowdsec-firewall-bouncer.service -f

Statistiken

# Geblockte Pakete zählen
iptables -L -n -v | grep crowdsec-blacklists-5

# Anzahl aktiver Bans
cscli decisions list --limit 0 | grep "GeoIP" | wc -l

# Top 10 blockierte IPs (PHP-Level)
cat /var/www/vhosts/SHOP/httpdocs/geoip_blocked.log | \
    grep -oP 'IP: \K[0-9.]+' | sort | uniq -c | sort -rn | head -10

🔐 Best Practices

Vor Aktivierung

  1. Backup erstellen (macht das Script automatisch)
  2. Sicherstellen, dass Admin-Zugriff aus gewählter Region kommt
  3. Region wählen (DACH für DACH-only, Eurozone für EU-weit)
  4. Modus wählen (PHP+CrowdSec für direkte Server, PHP-only für CDN)
  5. Monitoring einrichten

Während aktivem Blocking

  1. Logs regelmäßig prüfen (Gesamtübersicht nutzen!)
  2. Auf Fehlblockierungen achten (sehr selten)
  3. CrowdSec-Statistiken beobachten (nur bei PHP+CrowdSec)
  4. Server-Performance monitoren
  5. Cache-Status im Status-Menü prüfen

Nach Deaktivierung

  1. Prüfen ob alle Decisions entfernt wurden (nur bei PHP+CrowdSec)
  2. Backup-Dateien können gelöscht werden (optional)
  3. Logs archivieren (falls benötigt)

⚠️ Wichtige Hinweise

Rechtliches

  • DSGVO: IP-Adressen werden nur temporär geloggt (72h)
  • Geoblocking: Kann gegen EU-Verordnungen verstoßen bei B2C-Geschäften
  • Haftung: Nur für technische Notfälle/DDoS-Abwehr empfohlen

Technisches

  • API-Calls: Bei vielen aktiven Shops könnten viele IPs in CrowdSec landen
  • CrowdSec-Limits: Kostenloser Tier hat API-Limits
  • Netzwerk: Kein Blocking möglich, wenn Server selbst unter DDoS steht
  • CDN: Bei CDN-Nutzung ist PHP-only Modus empfohlen

Empfehlungen

  • Nur temporär nutzen (Notfälle, Angriffe)
  • Nicht als permanente Lösung
  • Kombinieren mit anderen Security-Maßnahmen
  • Regelmäßig Logs prüfen (Gesamtübersicht für schnellen Überblick)
  • Bei CDN: PHP-only Modus verwenden

📄 Lizenz

MIT License

🙏 Credits

  • IP-Ranges: ipdeny.com (RIPE-basiert)
  • CrowdSec: crowdsec.net
  • Entwickelt für: Plesk-basierte Multi-Shop-Server

📞 Support

Bei Problemen:

  1. Prüfe die Troubleshooting-Sektion
  2. Prüfe die Logs (Gesamtübersicht oder einzeln)
  3. Prüfe den Cache-Status im Status-Menü
  4. Erstelle ein GitHub Issue mit:
    • Fehlerbeschreibung
    • Relevante Logs
    • System-Infos (OS, PHP-Version, CrowdSec-Version)
    • Verwendete Region (DACH oder Eurozone+GB)
    • Verwendeter Modus (PHP+CrowdSec oder PHP-only)

📚 Weitere Dokumentation


Version: 3.1.0
Letztes Update: Dezember 2025
Status: Production Ready
Regionen: 🇩🇪🇦🇹🇨🇭 DACH (3 Länder) | 🇪🇺 Eurozone+GB (22 Länder)
Features: Cache-Validierung 🛡️ | Fail-Open 🔓 | Bot-Erkennung 🤖 | Link11-Erkennung 🌐

Changelog

v3.1.0

  • NEU: Cache-Validierung bei Aktivierung
  • NEU: Fail-Open bei Cache-Fehlern (kein Total-Lockout mehr)
  • NEU: Selbstheilender Cache (automatische Regeneration bei Korruption)
  • NEU: Mindest-Range-Prüfung pro Region (DACH: 1000, Eurozone: 5000)
  • NEU: Cache-Status in Status-Anzeige ( oder ⚠️)

v3.0.0

  • NEU: Eurozone+GB Region (22 Länder)
  • NEU: Region-Auswahl bei Aktivierung
  • NEU: Region-Icons in Status/Logs (🇩🇪🇦🇹🇨🇭 oder 🇪🇺)
  • NEU: Bot-Erkennung in Logs (GPTBot, Googlebot, Bingbot, etc.)
  • NEU: Link11-Erkennung (farbige Anzeige)
  • NEU: req/min Statistiken pro Shop und IP
  • NEU: Top-IP pro Shop in Gesamtübersicht
  • Cache-Datei umbenannt zu geoip_ip_ranges.cache

v2.2.0

  • NEU: Modus-Auswahl bei Aktivierung (PHP+CrowdSec 🛡️ oder Nur PHP 📝)
  • NEU: PHP-only Modus für Server hinter CDN/Reverse-Proxy (Link11, Cloudflare)
  • NEU: Top 100 blockierte IPs in Gesamtübersicht (jetzt Top 50)
  • FIX: CrowdSec Cleanup nutzt jetzt --limit 0 für vollständige Löschung

v2.1.0

  • NEU: Option [5] - Alle Shops gleichzeitig aktivieren
  • NEU: Option [6] - Alle Shops gleichzeitig deaktivieren
  • NEU: Gesamtübersicht in Logs (Option [0]) mit aggregierten Statistiken
  • NEU: Visuelle Balken in der Statistik-Anzeige

v2.0.0

  • DACH-Support (DE, AT, CH statt nur DE)
  • Systemd-Service für Watcher
  • CrowdSec-Integration
  • Multi-Shop-Management