2026-10-25 20:46:32 +01:00
2026-10-25 20:46:32 +01:00
2026-10-25 20:46:32 +01:00
2026-10-25 20:46:32 +01:00

npm-scanner

fail2ban als Docker-Container für den Nginx Proxy Manager (NPM): sperrt IPs, die nach Schwachstellen scannen (/.env, /.git/, phpinfo, /vendor/phpunit …), direkt in der Firewall des Hosts.

  • Liest die Access-Logs des NPM nur lesend – für jc21/nginx-proxy-manager und jlesage/nginx-proxy-manager
  • Sperrt in der Kette DOCKER-USER auf allen Ports (Docker leitet veröffentlichte Ports an INPUT vorbei)
  • 3 Treffer in 1 Stunde → 24 h, bei Wiederholung steigend bis 4 Wochen
  • Optional: WordPress-Login-Schutz (npm-wplogin) und Wiederholungstäter (recidive)
  • Neue Proxy-Hosts im NPM werden automatisch überwacht, ohne Neustart
  • Alle Einstellungen in einer .env, Filter werden beim Image-Build getestet
  • amd64 und arm64, Basis crazymax/fail2ban
 Internet ──▶ Host-Firewall ──DOCKER-USER──▶ NPM (Docker) ──▶ Dienste
                   ▲                          │ schreibt
                   │ sperrt                   ▼
              npm-scanner ◀──── liest ──── proxy-host-*_access.log
              (fail2ban, network_mode: host)

Bewusst nicht gezählt: reine 404 (Nextcloud-/Matrix-Clients erzeugen legitim viele davon) und Weiterleitungen am Default-Host ohne Scanner-Pfad (Suchmaschinen).

Quellen

Repository https://git.retronerd.at/schiwagoa/npm-scanner
Image git.retronerd.at/schiwagoa/npm-scanner
Basis-Image https://github.com/crazy-max/docker-fail2ban · https://hub.docker.com/r/crazymax/fail2ban
fail2ban https://github.com/fail2ban/fail2ban
Nginx Proxy Manager https://nginxproxymanager.com · https://github.com/jlesage/docker-nginx-proxy-manager

Voraussetzungen

  • Linux-Host mit Docker Engine und Compose-Plugin (docker compose version)
  • NPM läuft auf demselben Host als Container
  • Kein fail2ban direkt auf dem Host, das dieselben NPM-Logs liest – sonst wird doppelt gesperrt
  • Im LXC-Container: auf dem Proxmox-Host pct set <id> --features nesting=1,keyctl=1

Installation

Alle Befehle als root.

1. Log-Ordner des NPM ermitteln

docker ps --format '{{.Names}}\t{{.Image}}' | grep -i proxy

Den Containernamen einsetzen:

docker inspect <npm-container> --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}'
Image Container-Pfad NPM_LOG_DIR NPM_LOG_DIR2
jc21/nginx-proxy-manager /data <Quelle von /data>/logs leer
jlesage/nginx-proxy-manager /config <Quelle von /config>/log <Quelle von /config>/logs

Bei jlesage schreiben neu gespeicherte Hosts nach logs/, ältere nach log/ – deshalb beide.

Kontrolle – es müssen proxy-host-*_access.log erscheinen:

ls /home/docker-projekte/nginx/data/log | grep proxy-host | head

2. Projektordner anlegen

mkdir -p /home/docker-projekte/npm-scanner
cd /home/docker-projekte/npm-scanner
curl -fsSLO https://git.retronerd.at/schiwagoa/npm-scanner/raw/branch/main/docker-compose.yaml
curl -fsSL -o .env https://git.retronerd.at/schiwagoa/npm-scanner/raw/branch/main/.env.example
chmod 600 .env

3. .env anpassen

nano .env

Mindestens NPM_LOG_DIR, NPM_LOG_DIR2 und WHITELIST (eigene öffentliche IP, LAN, VPN, Monitoring) setzen. Alle Variablen: docs/configuration.md.

4. Konfiguration prüfen (startet nichts)

docker compose run --rm npm-scanner check

Erwartet: die erzeugte jail.local und am Ende OK: configuration test is successful.

5. Starten

docker compose up -d
docker compose ps
docker logs npm-scanner

Erwartet im Log: [npm-scanner] log directories: …, [npm-newlog] watching … und Jail 'npm-scanner' started. Nach etwa 30 Sekunden steht der Container auf healthy.

6. Prüfen

docker exec npm-scanner fail2ban-client status npm-scanner
docker exec npm-scanner fail2ban-client get npm-scanner logpath

Nach der ersten Sperre hängt die Regel in DOCKER-USER:

iptables -S DOCKER-USER
iptables -S f2b-npm-scan

Betrieb

Gesperrte IPs docker exec npm-scanner fail2ban-client get npm-scanner banip --with-time
Entsperren docker exec npm-scanner fail2ban-client set npm-scanner unbanip <ip>
Von Hand sperren docker exec npm-scanner fail2ban-client set npm-scanner banip <ip>
Letzte Sperren docker logs npm-scanner 2>&1 | grep ' Ban ' | tail -20
Update docker compose pull && docker compose up -d

Mehr – Backup, eigene Jails, Fehlersuche, Rückbau: docs/operations.md.

Warum kein eigenes Docker-Netzwerk?

fail2ban muss Regeln in der Firewall des Hosts setzen. Deshalb läuft der Container mit network_mode: host und den Capabilities NET_ADMIN und NET_RAW. In einem Bridge-Netz würde er nur die Firewall seines eigenen Netz-Namespaces ändern. Der Container öffnet keine Ports und liest die NPM-Logs nur lesend.

Dokumentation

Konfiguration alle Variablen der .env, eigene Jails und Filter
Betrieb Logs, Updates, Backup, Fehlerbehebung, Rückbau
Sicherheit Rechte des Containers, Melden von Schwachstellen

Lizenz

MIT. Basiert auf crazymax/fail2ban (MIT) und fail2ban (GPL-2.0).


🏰 Website · 🐘 Mastodon · 🔒 Datenschutz · 💬 Support

© Thomas Werner Schwaighofer · retronerd.AT · MIT Lizenz

S
Description
fail2ban als Docker-Container für den Nginx Proxy Manager (NPM): sperrt IPs, die nach Schwachstellen scannen (/.env, /.git/, phpinfo, /vendor/phpunit …), direkt in der Firewall des Hosts.
Readme MIT
50 KiB
0 Stars 1 Watchers 0 Forks
Languages
Shell 84.9%
Dockerfile 7.9%
Go Template 6.1%
Smarty 1.1%