# 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](https://github.com/crazy-max/docker-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 --features nesting=1,keyctl=1` ## Installation Alle Befehle als root. ### 1. Log-Ordner des NPM ermitteln ```bash docker ps --format '{{.Names}}\t{{.Image}}' | grep -i proxy ``` Den Containernamen einsetzen: ```bash docker inspect --format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{println}}{{end}}' ``` | Image | Container-Pfad | `NPM_LOG_DIR` | `NPM_LOG_DIR2` | |---|---|---|---| | `jc21/nginx-proxy-manager` | `/data` | `/logs` | leer | | `jlesage/nginx-proxy-manager` | `/config` | `/log` | `/logs` | Bei jlesage schreiben neu gespeicherte Hosts nach `logs/`, ältere nach `log/` – deshalb beide. Kontrolle – es müssen `proxy-host-*_access.log` erscheinen: ```bash ls /home/docker-projekte/nginx/data/log | grep proxy-host | head ``` ### 2. Projektordner anlegen ```bash 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 ```bash nano .env ``` Mindestens `NPM_LOG_DIR`, `NPM_LOG_DIR2` und **`WHITELIST`** (eigene öffentliche IP, LAN, VPN, Monitoring) setzen. Alle Variablen: [docs/configuration.md](docs/configuration.md). ### 4. Konfiguration prüfen (startet nichts) ```bash docker compose run --rm npm-scanner check ``` Erwartet: die erzeugte `jail.local` und am Ende `OK: configuration test is successful`. ### 5. Starten ```bash 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 ```bash 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`: ```bash 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 ` | | Von Hand sperren | `docker exec npm-scanner fail2ban-client set npm-scanner banip ` | | 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](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](docs/configuration.md) | alle Variablen der `.env`, eigene Jails und Filter | | [Betrieb](docs/operations.md) | Logs, Updates, Backup, Fehlerbehebung, Rückbau | | [Sicherheit](SECURITY.md) | Rechte des Containers, Melden von Schwachstellen | ## Lizenz [MIT](LICENSE). Basiert auf [crazymax/fail2ban](https://github.com/crazy-max/docker-fail2ban) (MIT) und [fail2ban](https://github.com/fail2ban/fail2ban) (GPL-2.0). ---

🏰 Website · 🐘 Mastodon · 🔒 Datenschutz · 💬 Support

© Thomas Werner Schwaighofer · retronerd.AT · MIT Lizenz