# 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](https://www.ipdeny.com/ipblocks/). 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): ```bash 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.ini` nach `/opt/aria-geoblock/` (bestehende `.ini` wird 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: ```bash 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) ```bash 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:** ```bash # 1) Von einem ERLAUBTEN Netz/Land aus aufrufen -> sollte laden curl http://: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://:8899/ # 4) Land wieder aus der .ini entfernen + --apply -> Zugriff geht wieder ``` Manuell ohne systemd starten: ```bash 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). ## 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: 1. Im Script-Kopf `LOG_FILE` auf den Pfad aus der `.ini` (`log_file`) anpassen. 2. Ausfuehrbar machen und kopieren: ```bash chmod 755 aria_geoblock_checkmk cp aria_geoblock_checkmk /usr/lib/check_mk_agent/local/ ``` (Pfad haengt vom Setup ab — bei OMD-Sites z.B. `~/local/lib/check_mk_agent/local/`.) 3. 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 pruefen - `log`: iptables-LOG-Eintrag vor dem DROP (dmesg/kern.log) an/aus - `ipset_name`: Name des ipset-Sets - `log_file`: Pfad zur script-eigenen Log-Datei (fuer checkmk) Abschnitt `[testserver]` (fuer `aria_geoblock_testserver.py`): - `port`: TCP-Port des Test-Webservers (Default `8899`) - `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_pass` auf `127.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: 1. selbst direkt mit einer oeffentlichen IP/Port erreichbar sein (kein Proxy dazwischen) — z.B. indem die Testmaschine testweise eine eigene oeffentliche IP bekommt, oder 2. 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.