Einleitung (Einordnung, Relevanz für Security/SIEM/Wazuh)
In vielen Wazuh-Deployments landen Applikations- und Container-Logs als Datei-Rotation in Sammelverzeichnissen wie /var/log/docker-logs/. Der typische Ansatz ist ein breites Wildcard-Pattern (*.log) für maximale Abdeckung. Spätestens wenn einzelne Dateien Multiline-Stacktraces oder Batch-Events enthalten, wird das jedoch heikel: Diese Files müssen anders geparst werden (z. B. multi-line-regex), dürfen also nicht gleichzeitig über den generischen syslog-Reader eingelesen werden. Genau hier stößt man in der Praxis auf ein häufig missverstandenes Detail: Das Zusammenspiel aus location-Wildcard und mehreren <exclude>-Zeilen verhält sich nicht in jeder Konstellation so, wie man es intuitiv erwartet.
Ausgangslage / Problemstellung (Zusammenfassung, Symptome, Umgebung)
Die Ausgangskonfiguration folgt einem üblichen Muster:
- Regel 1: Sammle alles aus
/var/log/docker-logs/*.logalssyslog. - Regel 2 & 3: Parse zwei spezielle Dateien (
mjid.log,webs_other.log) alsmulti-line-regex.
Dazu werden in Regel 1 Ausschlüsse gesetzt, damit die beiden Spezialdateien nicht doppelt ingestiert werden:
<localfile>
<log_format>syslog</log_format>
<location>/var/log/docker-logs/*.log</location>
<exclude>/var/log/docker-logs/mj*</exclude>
<exclude>/var/log/docker-logs/webs_other.log</exclude>
</localfile>
Symptom:
- Sobald das
*.log-Wildcard aktiv ist, funktionieren die Multiline-Regeln nicht zuverlässig (oder es kommt zu Doppel-Parsing/Fehlklassifikation). - Entfernt man das
*.log, greifen die Multiline-Reader wie erwartet.
Technische Analyse (Ursachen, betroffene Komponenten, Architekturbezug, Stolpersteine)
1) Warum Multiline „kaputt wirkt“, wenn das Wildcard aktiv ist
Wazuh liest Dateien über File Monitoring / Logcollector. Bei überlappenden <localfile>-Definitionen kann eine Datei aus mehreren Gründen nicht so verarbeitet werden, wie geplant:
- Doppelte Erfassung: Die Datei wird einmal als
syslogund zusätzlich alsmulti-line-regexgelesen. Das ist besonders bei Multiline fatal, weil ein „falscher“ Reader (syslog) Zeilen fragmentiert, während der Multiline-Reader eigentlich einen Start-Trigger und dann das Zusammenführen benötigt. - Race/State-Effekte: Je nach Reihenfolge und internem State (Offset/Position) kann die „erste“ Definition die Datei bereits verarbeitet und Offsets gesetzt haben, bevor der zweite Reader sauber greift.
- Inkompatible Semantik: Multiline funktioniert zuverlässig nur, wenn die Datei exklusiv über den Multiline-Reader verarbeitet wird.
2) Das eigentliche Kernproblem: <exclude> ist nicht gleich <exclude>
In der Praxis zeigt sich ein differenziertes Verhalten:
- Mehrere
<exclude>-Zeilen können funktionieren, wenn die Ausschlüsse exakte Dateipfade sind (ohne Wildcards). - Mit Wildcard-Excludes (z. B.
mj*) kann es passieren, dass nur ein Pattern greift oder die gesamte Exclusion-Logik nicht deterministisch wirkt.
Das erklärt die Beobachtung:
excludemitmj*+ ein weitererexclude→ problematisch.- Zwei
excludeohne Wildcards (z. B.mjid.logundwebs_other.logals exakte Pfade) → funktioniert.
Diese Nuance ist wichtig: Es ist nicht „nur eine Exclude-Zeile erlaubt“, sondern eher „Wildcard-Excludes sind in Kombination/Mehrzahl nicht zuverlässig“.
3) Architekturbezug: Warum Wazuh das nicht „automatisch“ korrekt entscheidet
Wazuh ist bei <localfile>-Definitionen nicht als „Policy-Engine“ gedacht, die Konflikte auflöst. Es nimmt Konfigurationen wörtlich und arbeitet sie ab. Sobald ein File in mehreren lokalen File-Inputs auftaucht, muss der Betreiber sicherstellen, dass:
- jeder Logstrom eindeutig einem Reader zugeordnet ist,
- Multiline-Dateien nicht parallel über generische Wildcards abgedeckt werden,
- und Excludes nicht auf nicht-deterministische Musterkombinationen setzen.
Lösung / Best Practices (konkrete Schritte, Konfigurationen, Reihenfolge, Side-Effects)
Best Practice 1: Exakte Excludes statt Wildcard-Excludes verwenden
Wenn es wirklich nur zwei Dateien sind: keine Wildcards im Exclude. Damit bleibt das Verhalten stabil und nachvollziehbar.
<localfile>
<log_format>syslog</log_format>
<location>/var/log/docker-logs/*.log</location>
<exclude>/var/log/docker-logs/mjid.log</exclude>
<exclude>/var/log/docker-logs/webs_other.log</exclude>
</localfile>
<localfile>
<log_format>multi-line-regex</log_format>
<location>/var/log/docker-logs/mjid.log</location>
<multiline_regex type="pcre2" match="start" replace="wspace">\d\d\d\d-\d\d-\d\d</multiline_regex>
</localfile>
<localfile>
<log_format>multi-line-regex</log_format>
<location>/var/log/docker-logs/webs_other.log</location>
<multiline_regex type="pcre2" match="start" replace="wspace">^Traceback</multiline_regex>
</localfile>
Warum das gut ist:
- Keine Pattern-Mehrdeutigkeit.
- Multiline-Dateien sind exklusiv dem Multiline-Reader zugeordnet.
- Das generische
*.logdeckt weiterhin alles andere ab.
Best Practice 2: Multiline-Logs konsequent umbenennen oder separieren
Wenn künftig mehr Multiline-Dateien hinzukommen (und du nicht jede einzeln im Exclude pflegen willst), ist eine strukturelle Trennung meist die sauberste Lösung:
Option A: Namenskonvention
- Alle Multiline-Files bekommen ein Prefix, z. B.
ml_*.log - Dann reicht ein einziges Exclude-Pattern (wenn Wildcards stabil greifen) oder du drehst das Prinzip um:
Beispiel:
- Sammelregel:
/var/log/docker-logs/*.log - Multiline in separatem Namensraum:
/var/log/docker-logs/ml_*.log - Exclude nur:
/var/log/docker-logs/ml_*.log
Option B: Separates Verzeichnis
- Standardlogs:
/var/log/docker-logs/*.log - Multiline:
/var/log/docker-logs-multiline/*.log
Dann gibt es gar keine Überschneidung mehr, und die Config bleibt wartbar.
Best Practice 3: Wildcard im location enger schneiden, statt Excludes komplex zu machen
Wenn du alle „normalen“ Logs an einem Merkmal erkennst (Suffix, Prefix, Unterordner), ist es oft besser, das location-Pattern so zu wählen, dass Multiline-Dateien gar nicht erst gematcht werden.
Beispiel-Idee:
- Normale Logs:
*_sys.log - Multiline:
*_ml.log
Dann:
location>*_sys.log</location>für sysloglocation>*_ml.log</location>für multiline
Side-Effects, die du einplanen solltest
- Doppel-Ingestion produziert häufig „komische“ Alerts: Parsen als syslog kann Felder/Decoder triggern, die bei Multiline nicht passen.
- Offsets/Read-State: Nach Umstellung kann es sein, dass Dateien erneut eingelesen werden (je nach Logcollector-State). In produktiven Umgebungen ein Wartungsfenster/Monitoring einplanen.
Lessons Learned / Best Practices (präventive Maßnahmen, Betrieb, Skalierung)
- Eindeutigkeit schlägt Eleganz: Lieber klare, nicht überlappende
<localfile>-Definitionen als „ein Pattern für alles“ mit vielen Ausnahmen. - Wildcard-Excludes sparsam einsetzen: Besonders dann, wenn mehrere Excludes kombiniert werden müssen oder du deterministisches Verhalten brauchst.
- Log-Design gehört zur Security-Pipeline: Schon beim Container/Applikations-Logging feste Regeln für Multiline vs. Singleline definieren (Dateinamen oder Verzeichnisstruktur).
- Multiline ist ein Spezialfall: Behandle Multiline-Dateien immer als „first-class citizens“ mit exklusiven Readern und möglichst ohne Überschneidungen mit Sammelregeln.
Fazit (knappe Zusammenfassung mit Mehrwert)
Wenn Multiline-Dateien in Wazuh parallel von einer generischen Wildcard-Regel (*.log als syslog) erfasst werden, ist Fehlverhalten vorprogrammiert: Multiline wird fragmentiert, Zustände überschneiden sich, und Excludes mit Wildcards können in Kombination unzuverlässig wirken. Stabil wird es, wenn du Multiline-Dateien entweder (a) mit exakten Excludes ohne Wildcards aus der Sammelregel herausnimmst oder (b) Multiline-Logs über Namenskonventionen bzw. separate Verzeichnisse vollständig von den „normalen“ Logs trennst. Das reduziert Komplexität, verhindert Doppel-Ingestion und macht deine agent.conf langfristig wartbar.
Mehr zu Wazuh …
https://wazuh.com/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program
Mehr zum Wazuh Ambassador Program …
https://wazuh.com/ambassadors-program/?utm_source=ambassadors&utm_medium=referral&utm_campaign=ambassadors+program
https://wazuh.slack.com/archives/C0A933R8E/p1770200656015799