ARIA Geoblocking
Blockt Verbindungen aus bestimmten Laendern auf Kernel-Ebene (iptables + ipset). Die IP-Bereiche je Land kommen kostenlos (kein API-Key) von ipdeny.com.
Kein Live-GeoIP-Lookup pro Verbindung (langsam, meist kostenpflichtig) —
stattdessen der Standardansatz von fail2ban/CSF: die komplette IP-Range-
Liste jedes Landes liegt im Kernel (ipset), iptables matched dagegen
und droppt Pakete bereits auf Netzwerk-Ebene.
Dateien
| Datei | Zweck |
|---|---|
aria_geoblock.py |
Hauptscript: laedt Laender-IPs, setzt/entfernt ipset+iptables-Regeln |
aria_geoblock.ini |
Konfiguration (Laenderliste, Chain, Logging, ...) |
aria-geoblock.service |
systemd-Unit, fuehrt --apply aus |
aria-geoblock.timer |
systemd-Timer: beim Booten + einmal taeglich |
install_aria_geoblock.sh |
Installer: kopiert alles nach /opt/aria-geoblock, richtet Timer + Testserver ein |
aria_geoblock_checkmk |
checkmk local-check Plugin (manuell kopieren) |
aria_geoblock_testserver.py |
Kleiner Test-Webserver, um die Regeln von aussen zu pruefen |
aria-geoblock-testserver.service |
systemd-Unit, startet den Test-Webserver dauerhaft |
Installation
Auf dem zu schuetzenden Host (root, iptables+ipset+python3 installiert):
git clone https://git.hacker-net.de/Aria-Software/geoblocking-python-script.git
cd geoblocking-python-script
sudo ./install_aria_geoblock.sh
Das:
- installiert
aria_geoblock.py+aria_geoblock.ininach/opt/aria-geoblock/(bestehende.iniwird NICHT ueberschrieben, neue landet als.example) - legt
/var/log/aria_geoblock/an - installiert + aktiviert
aria-geoblock.timer(systemctl enable --now) - installiert + startet
aria-geoblock-testserver.service(Test-Webserver, siehe Abschnitt "Verbindungstest" unten)
Danach /opt/aria-geoblock/aria_geoblock.ini anpassen (Laenderliste!) und
einmal manuell testen:
sudo systemctl start aria-geoblock.service
journalctl -u aria-geoblock.service -f
Der Timer laeuft danach automatisch: ~2 Minuten nach jedem Systemstart
und einmal taeglich (mit bis zu 15min Zufallsversatz, damit nicht alle
Hosts gleichzeitig ipdeny.com anfragen). Verpasste Laeufe (Host war aus)
werden dank Persistent=true beim naechsten Boot nachgeholt.
Manuelle Nutzung (ohne systemd)
sudo python3 aria_geoblock.py --config aria_geoblock.ini --apply # aktivieren/aktualisieren
sudo python3 aria_geoblock.py --config aria_geoblock.ini --apply --dry-run # nur simulieren
sudo python3 aria_geoblock.py --config aria_geoblock.ini --status # Zustand pruefen
sudo python3 aria_geoblock.py --config aria_geoblock.ini --remove # rueckgaengig
--apply ist idempotent (kein doppeltes Anlegen von Regeln) und tauscht
das ipset atomar per swap, damit waehrend der Aktualisierung kein Loch
im Blocking entsteht.
Achtung: iptables-Regeln sind nicht reboot-persistent. Wer das
zusaetzlich braucht: iptables-persistent / netfilter-persistent save
nutzen — der systemd-Timer sorgt aber ohnehin bei jedem Boot fuer einen
frischen --apply-Lauf, das reicht in der Praxis meist aus.
Verbindungstest (Test-Webserver)
aria_geoblock_testserver.py ist ein winziger HTTP-Server ohne
Abhaengigkeiten (nur Python-Stdlib). Er beantwortet jeden Request mit einer
kleinen Info-Seite (Client-IP, Zeitstempel, User-Agent) und loggt jeden
Request. Er weiss selbst NICHTS von Laendern/Blocklisten — der eigentliche
Test ist der Netzwerkeffekt: geblockte IPs erreichen ihn gar nicht erst
(iptables droppt vor dem TCP-Handshake), erlaubte IPs bekommen die Seite.
Laeuft nach install_aria_geoblock.sh automatisch als
aria-geoblock-testserver.service auf Port 8899 (einstellbar unter
[testserver] in aria_geoblock.ini, siehe unten).
Testablauf:
# 1) Von einem ERLAUBTEN Netz/Land aus aufrufen -> sollte laden
curl http://<host>:8899/
# 2) Testweise den eigenen Laendercode (z.B. DE) in aria_geoblock.ini
# eintragen und aktivieren:
sudo python3 aria_geoblock.py --config aria_geoblock.ini --apply
# 3) Jetzt von einem Client MIT einer IP aus diesem Land connecten
# (z.B. Handy im Mobilfunknetz) -> sollte jetzt TIMEOUT geben
curl --max-time 5 http://<host>:8899/
# 4) Land wieder aus der .ini entfernen + --apply -> Zugriff geht wieder
Manuell ohne systemd starten:
python3 aria_geoblock_testserver.py --config aria_geoblock.ini
# oder komplett ohne .ini:
python3 aria_geoblock_testserver.py --port 8899 --bind 0.0.0.0 \
--log-file /var/log/aria_geoblock/testserver.log
Requests landen (Zeit, Client-IP, Methode/Pfad, User-Agent) in der unter
log_file im [testserver]-Abschnitt konfigurierten Datei.
Achtung Firewall/Portfreigabe: der Testserver selbst oeffnet nur den Port lokal — ob er von aussen erreichbar ist, haengt von eurer sonstigen Firewall/Portweiterleitung ab (das ist bewusst getrennt von den Geoblock-DROP-Regeln, die ja genau diesen Port betreffen sollen).
Gezieltes Blocken einzelner Ports (Selbstaussperr-Schutz)
Per Default blockt --apply alle Ports/Protokolle fuer die gelisteten
Laender — das ist klassisches Geoblocking auf Host-Ebene. Das ist beim
Testen riskant: testet man testweise den eigenen Laendercode (siehe oben),
sperrt man sich damit auch von SSH & Co. aus, falls der Test-Client zufaellig
aus demselben Land connectet.
Ueber ports (und optional protocol) in der .ini laesst sich das
Blocking auf einzelne Anwendungen eingrenzen. Beispiel: nur den
Testserver-Port blocken, SSH bleibt fuer alle Laender offen:
[geoblock]
countries = de
...
ports = 8899
protocol = tcp
--apply legt dann statt einer allgemeinen DROP-Regel eine mit
-p tcp -m multiport --dports 8899 an — matched nur Pakete zu Port 8899,
alles andere (inkl. Port 22) bleibt unberuehrt. Mehrere Ports/Bereiche
gehen kommaseparat (80,443,8000:9000), mehrere Protokolle ebenso
(protocol = tcp,udp, legt dann eine Regel pro Protokoll an).
--status zeigt an, ob gerade eine Port-Einschraenkung aktiv ist und
welche. --remove entfernt automatisch die zur aktuellen .ini passenden
Regel-Varianten — falls ports/protocol zwischen zwei Laeufen geaendert
wurden, lohnt sich vor dem naechsten --apply ein Blick mit
iptables -L INPUT -n --line-numbers, ob noch Altregeln mit der vorherigen
Variante stehen.
Logging
In aria_geoblock.ini unter log_file einen Pfad eintragen (Default:
/var/log/aria_geoblock/aria_geoblock.log, wird vom Installer angelegt).
Bei jedem Lauf wird eine Zeile angehaengt, u.a. eine maschinenlesbare
RESULT status=OK/ERROR ...-Zeile — genau die wertet das checkmk-Plugin
aus. Leer lassen = keine Datei-Logs (nur stderr/systemd-Journal).
checkmk-Monitoring
aria_geoblock_checkmk ist ein klassisches checkmk local check-Plugin
(kein extra Agent-Plugin-Verzeichnis noetig). Manuell einrichten:
- Im Script-Kopf
LOG_FILEauf den Pfad aus der.ini(log_file) anpassen. - Ausfuehrbar machen und kopieren:
(Pfad haengt vom Setup ab — bei OMD-Sites z.B.
chmod 755 aria_geoblock_checkmk cp aria_geoblock_checkmk /usr/lib/check_mk_agent/local/~/local/lib/check_mk_agent/local/.) - Naechster Agent-Abruf zeigt den Service ARIA_Geoblock.
Status-Logik: ERROR im letzten Lauf → CRIT. Letzter erfolgreicher Lauf
36h alt → WARN, > 72h alt → CRIT (Timer laeuft taeglich, das faengt einen einzelnen verpassten Lauf ab, ohne sofort zu alarmieren). Sonst OK, inkl. Perfdata (Alter in Sekunden, Anzahl geblockter IP-Bereiche).
Konfiguration (aria_geoblock.ini)
Siehe Kommentare in der Datei selbst — kurz:
countries: Komma-Liste ISO-3166-1-alpha-2 Codes (z.B.RU, CN, KP, IR)chain: iptables-Chain (INPUT= eingehender Traffic zu diesem Host)interface: optional, nur ein Interface pruefenlog: iptables-LOG-Eintrag vor dem DROP (dmesg/kern.log) an/ausipset_name: Name des ipset-Setslog_file: Pfad zur script-eigenen Log-Datei (fuer checkmk)ports: optional, Komma-Liste von Ports/Bereichen (z.B.80,443,8000:9000). Leer = alle Ports/Protokolle werden geblockt (klassisches Geoblocking). Gesetzt = nur diese Ports werden fuer die gelisteten Laender geblockt, der Rest des Hosts bleibt erreichbar. Siehe Abschnitt "Gezieltes Blocken einzelner Ports" unten.protocol: nur relevant wennportsgesetzt ist —tcp(Default),udpodertcp,udp
Abschnitt [testserver] (fuer aria_geoblock_testserver.py):
port: TCP-Port des Test-Webservers (Default8899)bind: Bind-Adresse (0.0.0.0= alle IPv4-Interfaces)log_file: Pfad zur Request-Log-Datei des Testservers
Betrieb hinter einem Reverse-Proxy (z.B. nginx)
Wichtig zu verstehen, weil es leicht zu falschen Testergebnissen fuehrt: Geoblocking mit iptables/ipset arbeitet auf Netzwerk-Ebene (TCP), nicht auf HTTP-Ebene. Es sieht immer nur die IP, die die TCP-Verbindung tatsaechlich zum jeweiligen Host aufbaut — unabhaengig davon, was in HTTP-Headern steht.
Wo die echte Client-IP ankommt, haengt vom Aufbau ab:
- nginx ist der einzige "Proxy" (direkt am Internet, kein CDN/WAF davor): Die TCP-Verbindung vom Client landet direkt am nginx-Host. Dort sieht sowohl iptables als auch nginx selbst die echte oeffentliche Client-IP. In diesem Setup muessen die Geoblock-Regeln auf dem nginx-Host greifen, und zwar auf dem Port, auf dem nginx nach aussen lauscht (z.B. 80/443) — NICHT auf dem internen Port des dahinterliegenden Testservers/Backends.
- Davor haengt zusaetzlich ein CDN/WAF (Cloudflare, Fastly, ...): Dann kommt am nginx-Host nur noch die IP des CDN-Rechenzentrums an, nicht die echte Client-IP. iptables auf dem nginx-Host wuerde dann effektiv das CDN blocken, nicht den Endnutzer — Geoblocking muesste in diesem Fall beim CDN selbst konfiguriert werden (die meisten bieten das nativ an).
- Der Testserver haengt NUR intern hinter nginx (z.B.
proxy_passauf127.0.0.1:8899): Der Testserver selbst sieht dann nur die IP von nginx (127.0.0.1), nicht die des echten Clients — die Verbindung des Clients wurde ja schon vorher bei nginx "verbraucht" und neu aufgebaut. Ein iptables-DROP auf Port 8899 wuerde in diesem Aufbau gar nichts bewirken, weil der Traffic zum Testserver nie ueber das oeffentliche Netz laeuft, sondern nur lokal von nginx zum Backend.
Praktische Konsequenz fuer den Verbindungstest:
Um den Testserver (aria_geoblock_testserver.py, siehe oben) sinnvoll von
aussen zu testen, muss er entweder:
- selbst direkt mit einer oeffentlichen IP/Port erreichbar sein (kein Proxy dazwischen) — z.B. indem die Testmaschine testweise eine eigene oeffentliche IP bekommt, oder
- hinter nginx haengen, wobei dann nginx (nicht der Testserver) der Punkt ist, an dem die Geoblock-Regeln greifen muessen.
Fuer einen sauberen End-to-End-Test der iptables-Regeln selbst (ohne Fragen zu Proxy-Ketten/CDN reinzumischen) ist Variante 1 — Testmaschine direkt mit eigener oeffentlicher IP, Geoblocking direkt auf dieser Maschine — der einfachste und eindeutigste Weg.