Compare commits

...

3 Commits

Author SHA1 Message Date
46dae1acfa README: MikroTik-Bouncer verliert Address-List-Eintraege (Workaround dokumentiert)
Gemessen: nur 11.597 von 25.564 aktiven Decisions standen tatsaechlich auf dem
Router (45,4 %), darunter 30 von 58 eigenen Bans. Ursache ist der Cache des
Bouncers: Eintraege laufen per Timeout auf dem Router ab, der Cache meldet
weiterhin 'already present' und legt sie nie neu an.

Kein Versionsproblem - :latest ist digest-identisch mit v0.7.3 (neuestes
Release, Apr 2025). Workaround ist ein taeglicher Neustart per cron
(30 4 * * *), der die Liste komplett neu synchronisiert: 11.597 -> 25.037
in ~60 s, danach keine Requests mehr von bereits gelisteten IPs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 19:57:45 +02:00
26b810509f README: Stack dokumentiert, Verweis auf TraefikConfig-Repo
Die Traefik-Konfiguration unter /srv/TRAEFIK/etc/traefik ist jetzt in einem
eigenen Repo (lutz/TraefikConfig) versioniert; hier steht, wie die beiden
Repos zusammenspielen und was wo liegt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 17:11:49 +02:00
ecca92f3ed crowdsec: version-control Synology syslog pipeline and ban profiles
Since Jul 12 the stack ingests Synology DSM syslog (fids/fids2 -> Log
Center -> 192.168.0.142:5514/udp), but only the published port was in the
working tree and the actual config lived exclusively in the crowdsec-config
named volume -- a volume reset would have silently dropped the Synology
detection and the escalating ban policy.

Moved into the repo and bind-mounted (single source of truth; the shadowed
copies were removed from the volume):
- crowdsec/acquis-synology.yaml -> acquis.d/synology.yaml (syslog listener)
- crowdsec/parsers/famfihome-synology-connection.yaml -> s01-parse/
  (local parser for DSM 7 "Connection" failed sign-ins -> synology-dsm-bf)
- crowdsec/profiles.yaml (escalating ban (count+1)*12h, capped at 168h)

Also commits the previously untracked 5514:514/udp port mapping.

Verified after recreate: syslog listener bound on :514, lines arriving from
192.168.0.234, traefik access.log tail active, local parser loaded, cscli
explain on a DSM sign-in failure still reaches crowdsecurity/synology-dsm-bf,
26 active decisions preserved, both bouncers pulling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 16:59:46 +02:00
5 changed files with 176 additions and 0 deletions

101
README.md Normal file
View File

@@ -0,0 +1,101 @@
# Traefik-Stack (pi5-1)
Compose-Stack fuer den Reverse Proxy und die davor haengende CrowdSec-Abwehr.
| Service | Image | Aufgabe |
|---|---|---|
| `traefik` | `traefik:v3.7` | Reverse Proxy, TLS-Terminierung, ACME |
| `crowdsec` | `crowdsecurity/crowdsec:v1.7.8` | Erkennung aus Traefik-Access-Log + Synology-Syslog |
| `crowdsec-mikrotik-bouncer` | `ghcr.io/funkolab/cs-mikrotik-bouncer` | spiegelt Decisions als Drop-Regel auf die AX3 (Edge) |
Zusaetzlich haengt der **Traefik-Bouncer-Plugin** (`crowdsec@file`-Middleware)
direkt im Request-Pfad; die MikroTik-Seite blockt zusaetzlich auf Firewall-Ebene,
also auch VPN und SSH.
## Zwei Repos
Die **statische und dynamische Traefik-Konfiguration liegt NICHT hier**, sondern
unter `/srv/TRAEFIK/etc/traefik` (root-owned, in den Container als `/etc/traefik`
gemountet) und wird von einem eigenen Repo versioniert:
> **[`~/Projects/TraefikConfig`](http://192.168.0.234:8765/lutz/TraefikConfig)**
> `traefik.yml`, `traefik.d/*`, TLS-Inventar, Sync-/Deploy-Skripte, Disaster Recovery
Hier im Repo liegt alles, was den *Stack* beschreibt:
```
docker-compose.yml Services, Ports, Volumes
crowdsec/acquis.yaml Acquisition: Traefik-Access-Log
crowdsec/acquis-synology.yaml Acquisition: Syslog-Listener (fids/fids2)
crowdsec/parsers/famfihome-synology-connection.yaml lokaler Parser: DSM-7-Anmeldefehler
crowdsec/profiles.yaml eskalierende Ban-Dauer (count+1)*12h, max 168h
crowdsec/famfi-ca-bundle.pem OpenBAO-CA (fuer RouterOS api-ssl)
scripts/sync-synology-certs.sh holt die Synology-LE-Certs nach Traefik
```
Alles unter `crowdsec/` wird per Bind-Mount ins Image gelegt, damit es ein
Zuruecksetzen der Named Volumes ueberlebt die Dateien lagen frueher nur im
`crowdsec-config`-Volume und waren damit nicht gesichert.
## Bedienung
```bash
docker compose up -d # Stack starten
docker compose up -d crowdsec # nur CrowdSec neu erzeugen (nach Config-Aenderung)
docker exec crowdsec cscli metrics show acquisition # kommen Logs an?
docker exec crowdsec cscli decisions list # aktuelle Bans
docker exec crowdsec cscli bouncers list # ziehen die Bouncer?
```
Datenquellen pruefen: Traefik schreibt sein Access-Log ins geteilte Volume
`traefik-logs`, CrowdSec liest es read-only. Die Synologies senden per
DSM *Log Center → Log Sending* an `192.168.0.142:5514/udp`.
## Bekanntes Problem: MikroTik-Bouncer verliert Eintraege
**Symptom:** Gebannte IPs erreichen Traefik trotzdem noch, teils tagelang.
**Ursache:** Der Bouncer schreibt jeden Eintrag der Address-List `crowdsec` MIT
Timeout. Laeuft der Timeout auf dem Router ab, glaubt sein In-Memory-Cache
weiterhin, die Adresse sei vorhanden ("Address <IP> already present") und legt
sie nie neu an. Die Liste schrumpft dadurch kontinuierlich.
Gemessen am 2026-08-09: nur **11.597 von 25.564** aktiven Decisions waren
tatsaechlich auf dem Router (45,4 %) - auch 30 von 58 eigenen Bans fehlten.
In den zwei Stunden davor kamen 386 von 390 Requests von IPs, die gebannt
waren, aber nicht in der Liste standen.
**Kein Versionsproblem:** `:latest` ist identisch mit **v0.7.3** (neuestes
Release, Apr 2025, upstream seitdem still). Ein Update behebt es nicht.
**Workaround** (cron, Benutzer lutz): ein Neustart baut den Cache neu auf und
synchronisiert die komplette Decision-Liste (11.597 -> 25.037 in ~60 s,
danach 100 % der IPv4-Decisions durchgesetzt).
```
30 4 * * * /usr/bin/docker restart crowdsec-mikrotik-bouncer >/dev/null 2>&1
```
Der Schwund betraegt rund 130 Eintraege/Stunde (~12 %/Tag), der taegliche
Neustart begrenzt die Abdeckung also nach unten auf ca. 88 %. IPv6-Decisions
werden generell nicht uebertragen (`MIKROTIK_IPV6: "false"`).
Nachpruefen laesst sich das ueber die RouterOS-API (api-ssl 8729, CA-Bundle
`crowdsec/famfi-ca-bundle.pem`, SNI `mt-az.famfi.home`): Address-List-Eintraege
mit `list=crowdsec` zaehlen und gegen `cscli decisions list` halten. Die
Drop-Regel selbst (`/ip firewall raw`, chain=prerouting, in-interface-list=WAN)
ist in Ordnung - davor steht nur ein Whitelist-Accept mit RFC1918-Adressen.
## Secrets
`.mikrotik.env` (RouterOS-Passwort + Bouncer-API-Key) ist git-ignoriert und
root-only. Der LAPI-Key der Traefik-Middleware liegt in
`/srv/TRAEFIK/etc/traefik/traefik.d/crowdsec.yml` und ist ebenfalls bewusst
nicht versioniert siehe TraefikConfig-README.
## Verwandt
- `~/Projects/TraefikConfig` Traefik-Konfiguration (`/srv`), Restore-Prozedur
- `~/Projects/OpenBAO` PKI und Credential-Helper
- `~/Projects/ClaudeAdmin` 4-stuendlicher Healthcheck ueber den Stack

View File

@@ -0,0 +1,13 @@
# CrowdSec acquisition: Syslog-Listener fuer die Synology-NAS (fids/fids2)
# Gemountet nach /etc/crowdsec/acquis.d/synology.yaml (siehe docker-compose.yml)
#
# Die Synologies senden per DSM "Log Center -> Log Sending" an
# 192.168.0.142:5514/udp; Docker mappt das auf Port 514 im Container.
# Das Label "syslog" aktiviert s00-raw/crowdsecurity/syslog-logs; darauf
# setzen crowdsecurity/synology-dsm (+ der lokale Parser
# parsers/famfihome-synology-connection.yaml) auf.
source: syslog
listen_addr: 0.0.0.0
listen_port: 514
labels:
type: syslog

View File

@@ -0,0 +1,24 @@
# Lokaler CrowdSec-Parser (kein Hub-Item).
# Gemountet nach /etc/crowdsec/parsers/s01-parse/famfihome-synology-connection.yaml
# (siehe docker-compose.yml). Ergaenzt crowdsecurity/synology-dsm-logs um das
# "Connection"-Programm des DSM-7-Log-Centers; speist crowdsecurity/synology-dsm-bf.
name: famfihome/synology-connection-logs
description: "Synology Log Center 'Connection' events (DSM 7 sign-in failures)"
filter: "evt.Parsed.program == 'Connection'"
onsuccess: next_stage
pattern_syntax:
IPv4_WA: '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
IP_WA: '(?:%{IPV6}|%{IPv4_WA})'
nodes:
- grok:
pattern: 'User \[%{DATA:user}\] from \[%{IP_WA:src_ip}\] failed to sign in to \[%{DATA:service}\] via \[%{DATA:method}\]'
apply_on: message
statics:
- meta: log_type
value: synology-dsm_failed_auth
- meta: service
value: synology-dsm
- meta: source_ip
expression: "evt.Parsed.src_ip"
- meta: user
expression: "evt.Parsed.user"

30
crowdsec/profiles.yaml Normal file
View File

@@ -0,0 +1,30 @@
name: default_ip_remediation
#debug: true
filters:
- Alert.Remediation == true && Alert.GetScope() == "Ip"
decisions:
- type: ban
duration: 12h
# Escalating ban: 1st 12h; repeat offenders (while still listed) 24h, 36h ...; capped at 168h (7d)
duration_expr: Sprintf('%dh', min((GetDecisionsCount(Alert.GetValue()) + 1) * 12, 168))
# notifications:
# - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.yaml before enabling this.
# - splunk_default # Set the splunk url and token in /etc/crowdsec/notifications/splunk.yaml before enabling this.
# - http_default # Set the required http parameters in /etc/crowdsec/notifications/http.yaml before enabling this.
# - email_default # Set the required email parameters in /etc/crowdsec/notifications/email.yaml before enabling this.
on_success: break
---
name: default_range_remediation
#debug: true
filters:
- Alert.Remediation == true && Alert.GetScope() == "Range"
decisions:
- type: ban
duration: 12h
duration_expr: Sprintf('%dh', min((GetDecisionsCount(Alert.GetValue()) + 1) * 12, 168))
# notifications:
# - slack_default # Set the webhook in /etc/crowdsec/notifications/slack.yaml before enabling this.
# - splunk_default # Set the splunk url and token in /etc/crowdsec/notifications/splunk.yaml before enabling this.
# - http_default # Set the required http parameters in /etc/crowdsec/notifications/http.yaml before enabling this.
# - email_default # Set the required email parameters in /etc/crowdsec/notifications/email.yaml before enabling this.
on_success: break

View File

@@ -48,8 +48,16 @@ services:
- crowdsec-db:/var/lib/crowdsec/data
- traefik-logs:/var/log/traefik:ro # liest Traefiks Access-Log
- ./crowdsec/acquis.yaml:/etc/crowdsec/acquis.d/traefik.yaml:ro,Z
# Syslog-Quelle Synology (fids/fids2) + lokaler Parser dazu. Beides liegt
# im Repo (nicht nur im crowdsec-config-Volume), damit es ein Volume-Reset
# ueberlebt.
- ./crowdsec/acquis-synology.yaml:/etc/crowdsec/acquis.d/synology.yaml:ro,Z
- ./crowdsec/parsers/famfihome-synology-connection.yaml:/etc/crowdsec/parsers/s01-parse/famfihome-synology-connection.yaml:ro,Z
# Eskalierende Ban-Dauer ((count+1)*12h, max 168h) - haendisch gepflegt
- ./crowdsec/profiles.yaml:/etc/crowdsec/profiles.yaml:ro,Z
ports:
- "192.168.0.142:6060:6060" # Prometheus-Metriken (CrowdSec) fuer 192.168.0.23
- "192.168.0.142:5514:514/udp" # Syslog von den Synologies (DSM Log Center)
# MikroTik-Bouncer: spiegelt CrowdSec-Decisions in eine RouterOS-Firewall-
# Address-List ("crowdsec") auf der AX3 -> Edge-Drop (alle Ports, auch VPN/SSH).