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
- Cache-Validierung bei Aktivierung: Cache wird sofort generiert und auf Mindestanzahl geprüft
- Fail-Open im PHP: Bei Cache-Fehlern wird Traffic durchgelassen statt blockiert
- 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.phpdes 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-ForHeader 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)
- Script starten:
python3 geoip_shop_blocker.py - Option
[1] Aktivieren (einzeln)wählen - Shop aus der Liste auswählen (farbig: 🟢 Link11, 🔴 Direkt)
- Geo-Region wählen (DACH oder Eurozone+GB)
- Modus wählen (PHP+CrowdSec oder Nur PHP)
- Bestätigen mit
ja
Was passiert (PHP + CrowdSec Modus):
- Bei ERSTEM Shop: Systemd-Service wird installiert und gestartet
- Backup der
index.phpwird erstellt geoip_blocking.phpwird 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.phpwird erstellt geoip_blocking.phpwird 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
- Script starten:
python3 geoip_shop_blocker.py - Option
[5] 🚀 ALLE aktivierenwählen - Liste der zu aktivierenden Shops wird angezeigt (farbig nach Link11-Status)
- Geo-Region wählen (gilt für alle Shops)
- Modus wählen (gilt für alle Shops)
- 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)
- Script starten:
python3 geoip_shop_blocker.py - Option
[2] Deaktivieren (einzeln)wählen - Shop aus der Liste auswählen (zeigt Region und Modus an)
- Bestätigen mit
ja
Was passiert:
- Original
index.phpwird 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
- Script starten:
python3 geoip_shop_blocker.py - Option
[6] 🛑 ALLE deaktivierenwählen - Liste der aktiven Shops wird angezeigt (mit Region-Icons)
- Bestätigen mit
ja
Logs anzeigen
- Script starten:
python3 geoip_shop_blocker.py - Option
[3] Logs anzeigenwählen - 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:
- PHP-Blocking: Das Script prüft ein Ablaufdatum und macht
returnnach 72h - CrowdSec-Bans: Werden mit
--duration 72herstellt
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:
- Keine Internet-Verbindung zu ipdeny.com
- Timeout bei vielen Ländern (Eurozone)
- 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:
- CDN/Reverse-Proxy aktiv → Wechsle zu PHP-only Modus
- Bouncer läuft nicht:
systemctl status crowdsec-firewall-bouncer - 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
- ✅ Backup erstellen (macht das Script automatisch)
- ✅ Sicherstellen, dass Admin-Zugriff aus gewählter Region kommt
- ✅ Region wählen (DACH für DACH-only, Eurozone für EU-weit)
- ✅ Modus wählen (PHP+CrowdSec für direkte Server, PHP-only für CDN)
- ✅ Monitoring einrichten
Während aktivem Blocking
- ✅ Logs regelmäßig prüfen (Gesamtübersicht nutzen!)
- ✅ Auf Fehlblockierungen achten (sehr selten)
- ✅ CrowdSec-Statistiken beobachten (nur bei PHP+CrowdSec)
- ✅ Server-Performance monitoren
- ✅ Cache-Status im Status-Menü prüfen
Nach Deaktivierung
- ✅ Prüfen ob alle Decisions entfernt wurden (nur bei PHP+CrowdSec)
- ✅ Backup-Dateien können gelöscht werden (optional)
- ✅ 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:
- Prüfe die Troubleshooting-Sektion
- Prüfe die Logs (Gesamtübersicht oder einzeln)
- Prüfe den Cache-Status im Status-Menü
- 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 0fü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