Files
duffyduckandClaude Opus 4.8 b170759657 geoblock: Regeln an den Chain-Anfang setzen + Reassert-Watchdog fuer gemanagte Firewalls
Problem: auf Hosts mit gemanagter Firewall (z.B. Endian-UTM) stand die DROP-Regel
am Ende der INPUT-Chain (-A) und wurde von einer ACCEPT-Regel davor abgefangen ->
Geoblocking griff nicht, obwohl Set/Config korrekt waren.

geoblock.py:
- DROP-Regel jetzt wie die LOG-Regel per 'iptables -I' an den ANFANG der Chain
  (Reihenfolge LOG -> DROP). Rule-Setzen in set_iptables_rules() refaktoriert.
- Neue Aktion --reassert: leichtgewichtiger Watchdog, der die Regel-Position
  prueft und die Regeln nur bei Bedarf wieder nach oben setzt -- OHNE Zonefiles
  von ipdeny nachzuladen (nutzt bestehendes ipset). Kein Eingriff, wenn kein
  ipset existiert (dann erst voller --apply noetig).
- geoblock_rules_on_top(): erkennt, ob die Regeln luueckenlos die ersten der
  Chain sind. --status zeigt die Position jetzt mit an.

systemd:
- geoblock-reassert.service + .timer (alle 2 Min, opt-in via install_geoblock.sh
  --with-watchdog). uninstall raeumt sie mit ab und stoppt sie vor --remove.

README: Abschnitt "Regeln bleiben nicht oben (gemanagte Firewall)" + tcpdump-
Diagnose (anonymisiert) + Fehlersuche-Abschnitt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 11:35:38 +02:00

172 lines
6.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# Geoblocking - Installer
#
# Installiert geoblock.py + .ini nach /opt/geoblock (oder ein
# anderes Zielverzeichnis), legt das Log-Verzeichnis an und richtet einen
# systemd-Timer ein, der den Block beim Systemstart UND einmal taeglich
# aktualisiert.
#
# Nutzung (als root, im Verzeichnis mit allen Repo-Dateien):
# sudo ./install_geoblock.sh [--with-testserver] [--with-watchdog] [ZIELVERZEICHNIS]
#
# Der kleine Test-Webserver (geoblock_testserver.py +
# geoblock-testserver.service), gegen den man von aussen connecten
# kann um die Geoblocking-Regeln zu pruefen, wird NUR installiert wenn
# die Option --with-testserver angegeben wird. Ohne die Option passiert
# in Sachen Testserver gar nichts (kein Copy, kein systemd-Unit, kein
# offener Port).
#
# Der Reassert-Watchdog (geoblock-reassert.service + .timer) prueft alle
# 2 Minuten, ob die Block-Regeln noch am Anfang der iptables-Chain stehen,
# und setzt sie ggf. wieder nach oben (ohne ipdeny-Download). Nur noetig auf
# Hosts mit einer gemanagten Firewall (Shorewall/firewalld/UFW/UTM-Appliance),
# die die Chain neu baut und dabei fremde Regeln nach unten schiebt. Wird NUR
# bei --with-watchdog installiert/aktiviert.
#
# Beispiele:
# sudo ./install_geoblock.sh
# sudo ./install_geoblock.sh --with-testserver
# sudo ./install_geoblock.sh --with-watchdog
# sudo ./install_geoblock.sh --with-testserver --with-watchdog /opt/geoblock
# sudo ./install_geoblock.sh /opt/geoblock
#
# Benoetigt im selben Verzeichnis:
# geoblock.py
# geoblock.ini.example
# geoblock.service
# geoblock.timer
# (nur bei --with-testserver:)
# geoblock_testserver.py
# geoblock-testserver.service
# (nur bei --with-watchdog:)
# geoblock-reassert.service
# geoblock-reassert.timer
#
# Voraussetzungen auf dem Host: python3, iptables, ipset, systemd.
set -euo pipefail
if [[ $EUID -ne 0 ]]; then
echo "Bitte als root ausfuehren (sudo ./install_geoblock.sh)." >&2
exit 1
fi
SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WITH_TESTSERVER=0
WITH_WATCHDOG=0
INSTALL_DIR=""
for arg in "$@"; do
case "$arg" in
--with-testserver)
WITH_TESTSERVER=1
;;
--with-watchdog)
WITH_WATCHDOG=1
;;
-h|--help)
grep '^# ' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
exit 0
;;
*)
INSTALL_DIR="$arg"
;;
esac
done
INSTALL_DIR="${INSTALL_DIR:-/opt/geoblock}"
LOG_DIR="/var/log/geoblock"
REQUIRED_FILES=(geoblock.py geoblock.ini.example geoblock.service geoblock.timer)
if [[ "$WITH_TESTSERVER" -eq 1 ]]; then
REQUIRED_FILES+=(geoblock_testserver.py geoblock-testserver.service)
fi
if [[ "$WITH_WATCHDOG" -eq 1 ]]; then
REQUIRED_FILES+=(geoblock-reassert.service geoblock-reassert.timer)
fi
for f in "${REQUIRED_FILES[@]}"; do
if [[ ! -f "$SRC_DIR/$f" ]]; then
echo "FEHLER: $f fehlt in $SRC_DIR - bitte komplettes Repo verwenden." >&2
exit 1
fi
done
for bin in python3 iptables ipset systemctl; do
if ! command -v "$bin" >/dev/null 2>&1; then
echo "FEHLER: '$bin' ist nicht installiert. Bitte nachinstallieren (z.B. apt install iptables ipset)." >&2
exit 1
fi
done
echo "==> Installiere Script + Config nach $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
cp "$SRC_DIR/geoblock.py" "$INSTALL_DIR/geoblock.py"
chmod 755 "$INSTALL_DIR/geoblock.py"
cp "$SRC_DIR/geoblock.ini.example" "$INSTALL_DIR/geoblock.ini.example"
if [[ -f "$INSTALL_DIR/geoblock.ini" ]]; then
echo "==> Bestehende $INSTALL_DIR/geoblock.ini gefunden - wird NICHT ueberschrieben."
echo " Aktuelle Beispiel-Config liegt unter $INSTALL_DIR/geoblock.ini.example (zum Vergleich)."
else
cp "$SRC_DIR/geoblock.ini.example" "$INSTALL_DIR/geoblock.ini"
echo " -> bitte $INSTALL_DIR/geoblock.ini pruefen/anpassen (Laenderliste!)."
fi
echo "==> Lege Log-Verzeichnis an: $LOG_DIR"
mkdir -p "$LOG_DIR"
chmod 750 "$LOG_DIR"
echo "==> Installiere systemd-Units (Geoblock-Timer)"
sed "s#__INSTALL_DIR__#$INSTALL_DIR#g" "$SRC_DIR/geoblock.service" \
> /etc/systemd/system/geoblock.service
cp "$SRC_DIR/geoblock.timer" /etc/systemd/system/geoblock.timer
if [[ "$WITH_TESTSERVER" -eq 1 ]]; then
echo "==> --with-testserver gesetzt: installiere Test-Webserver nach $INSTALL_DIR"
cp "$SRC_DIR/geoblock_testserver.py" "$INSTALL_DIR/geoblock_testserver.py"
chmod 755 "$INSTALL_DIR/geoblock_testserver.py"
sed "s#__INSTALL_DIR__#$INSTALL_DIR#g" "$SRC_DIR/geoblock-testserver.service" \
> /etc/systemd/system/geoblock-testserver.service
else
echo "==> Test-Webserver wird NICHT installiert (Option --with-testserver nicht angegeben)."
fi
if [[ "$WITH_WATCHDOG" -eq 1 ]]; then
echo "==> --with-watchdog gesetzt: installiere Reassert-Watchdog (haelt die Regeln am Chain-Anfang)"
sed "s#__INSTALL_DIR__#$INSTALL_DIR#g" "$SRC_DIR/geoblock-reassert.service" \
> /etc/systemd/system/geoblock-reassert.service
cp "$SRC_DIR/geoblock-reassert.timer" /etc/systemd/system/geoblock-reassert.timer
else
echo "==> Reassert-Watchdog wird NICHT installiert (Option --with-watchdog nicht angegeben)."
fi
systemctl daemon-reload
systemctl enable --now geoblock.timer
if [[ "$WITH_TESTSERVER" -eq 1 ]]; then
systemctl enable --now geoblock-testserver.service
fi
if [[ "$WITH_WATCHDOG" -eq 1 ]]; then
systemctl enable --now geoblock-reassert.timer
fi
echo ""
echo "==> Fertig."
echo " Config anpassen: $INSTALL_DIR/geoblock.ini"
echo " Jetzt sofort testen: systemctl start geoblock.service && journalctl -u geoblock.service -f"
echo " Timer-Status: systemctl list-timers geoblock.timer"
echo " Naechste/letzte Läufe: systemctl status geoblock.timer"
if [[ "$WITH_WATCHDOG" -eq 1 ]]; then
echo " Watchdog-Status: systemctl list-timers geoblock-reassert.timer"
fi
echo " Log-Datei: $LOG_DIR/geoblock.log"
if [[ "$WITH_TESTSERVER" -eq 1 ]]; then
echo " Test-Webserver: systemctl status geoblock-testserver.service"
echo " Port/Bind/Log siehe [testserver] in $INSTALL_DIR/geoblock.ini"
else
echo " Test-Webserver: nicht installiert (spaeter nachruesten mit: sudo $0 --with-testserver $INSTALL_DIR)"
fi
echo " checkmk-Plugin: siehe geoblock_checkmk im Repo (manuell kopieren, README beachten)"