Files
2026-08-05 04:15:47 +02:00

5.0 KiB

country-resolve — Logfile Country Resolver

Ein kleiner Stream-Filter, der Logzeilen von stdin liest, die erste Spalte als IP-Adresse interpretiert und die Zeile um Kontinent und Land anreichert wieder auf stdout ausgibt.

Die Auflösung erfolgt offline über eine lokale DB-IP Country Lite MMDB-Datenbank (gelesen via geoip2).

Typischer Einsatzzweck: Webserver-Access-Logs nach Herkunftsland filtern und daraus z. B. CrowdSec-Blockentscheidungen ableiten.


Funktionsweise

Für jede Eingabezeile:

  1. Zeile an Leerzeichen zerlegen, parts[0] ist die IP.
  2. IP gegen die MMDB auflösen → continent.code (z. B. EU) und country.name (z. B. Germany).
  3. Nicht auflösbare IPs (AddressNotFoundError) werden als Land Unknown markiert.
  4. Ausgabe: alle Felder pipe-separiert (|), mit Kontinent und Land vorangestellt:
<Kontinent>|<Land>|<originalfeld1>|<originalfeld2>|...

Fehlerhafte Einzelzeilen werden übersprungen (kein Abbruch des Streams).

Ausgabeformat

EU|Germany|93.229.122.46|-|-|[27/Feb/2025:00:00:02|+0100]|"GET|/pages/...|HTTP/1.1"|200|...
Feld 1 Feld 2 ab Feld 3
Kontinent-Code (EU, AS, NA, …) Ländername (Germany, Unknown, …) die ursprünglichen, an Leerzeichen getrennten Felder

Voraussetzungen

  • Python ≥ 3.13 (siehe .python-version)
  • Python-Paket geoip2 (als Abhängigkeit in pyproject.toml deklariert)
  • Eine MMDB-Datei namens dbip-country-lite-2025-02.mmdb im Arbeitsverzeichnis (Pfad ist in resolver.py fest verdrahtet). MMDB-Dateien sind per .gitignore vom Repository ausgeschlossen und müssen separat bezogen werden.

Installation

Mit uv — installiert die in pyproject.toml deklarierten Abhängigkeiten:

uv sync

Oder klassisch mit pip:

python3 -m venv .venv
source .venv/bin/activate
pip install geoip2

MMDB-Datenbank besorgen

Die Lite-Datenbank kostenlos bei DB-IP herunterladen und passend benennen:

# Beispiel (Dateiname muss zur Konstante in resolver.py passen)
mv dbip-country-lite-2025-02.mmdb ./dbip-country-lite-2025-02.mmdb

Für eine andere/aktuellere DB den Pfad in resolver.py (Zeile mit geoip2.database.Reader(...)) anpassen.


Benutzung

Einzelne Zeile auflösen

head -1 access_crowdsec.log
# 93.229.122.46 - - [27/Feb/2025:00:00:02 +0100] "GET /pages/images/website/home/2502-01.jpg HTTP/1.1" 200 60233 "https://www.plainpicture.com/de" "Mozilla/5.0 ..."

head -1 access_crowdsec.log | ./resolver
# EU|Germany|93.229.122.46|-|-|[27/Feb/2025:00:00:02|+0100]|"GET|/pages/images/website/home/2502-01.jpg|HTTP/1.1"|200|...

./resolver ist das gepackte Binary (siehe Packaging). Alternativ direkt über Python:

head -1 access_crowdsec.log | python3 resolver.py

Anwendungsbeispiel: Länder-basiertes Blocking mit CrowdSec

Access-Log streamen, auf interessante Requests filtern, Herkunft auflösen und nach bestimmten Ländern/Kontinenten filtern:

cat access_crowdsec.log \
  | stdbuf -o0 grep "/search" \
  | grep -v "Safari/" \
  | stdbuf -o0 /tmp/resolver \
  | stdbuf -o0 egrep "Russia|Belarus|^SA|^AS|^AF" \
  > block_20250227.txt

Aus den Treffern /16-Netze ableiten und als CrowdSec-Decisions importieren:

cscli decisions delete --all
cat block_20250227.txt \
  | cut -d"|" -f3 \
  | perl -ne 's/(\d+)\.(\d+)\..*/$1.$2/; print ' \
  | uniq \
  | perl -ne 'chomp; print $_,".0.0/16\n"' \
  | cscli decisions import -i - --format values -d48h -R toomuch_AS_SA_AF

stdbuf -o0 erzwingt ungepuffertes Streaming, damit die Pipeline zeilenweise (nahezu in Echtzeit) durchläuft.


Packaging

Ein eigenständiges Binary (ohne Python-Runtime auf dem Zielsystem) mit PyInstaller erzeugen:

pyinstaller --onefile resolver.py
# oder mit der mitgelieferten Spec-Datei:
pyinstaller resolver.spec

Das Ergebnis liegt anschließend unter dist/resolver und kann z. B. nach /tmp/resolver kopiert und in Pipelines eingesetzt werden.

Die MMDB-Datei wird nicht ins Binary eingebettet — sie muss zur Laufzeit im Arbeitsverzeichnis liegen (bzw. der Pfad in resolver.py entsprechend gesetzt sein).


Projektdateien

Datei Zweck
resolver.py Der eigentliche Stream-Filter
resolver.spec PyInstaller-Spezifikation für das --onefile-Binary
pyproject.toml Projekt-Metadaten (Python ≥ 3.13)
.python-version Fixierte Python-Version (3.13)
*.mmdb GeoIP-Datenbank (nicht im Repo, per .gitignore)