UniFi UDM Pro in Wazuh 4.12.0 integrieren: Logs sauber ablegen, Decoder stabil bauen, Regeln zuverlässig matchen

Einleitung

UniFi UDM Pro (inkl. IDS/IPS-Daemon) produziert Syslog-Events, die in Wazuh oft zunächst nur als generische Syslog-Meldungen landen. Ohne passende Decoder fehlen strukturierte Felder wie srcip, dstip, dstport oder protocol – und damit auch die Basis für belastbare Regeln und Threat-Hunting-Queries. In diesem Beitrag geht es darum, UDM-Logs in eine eigene Logdatei (z. B. UDMPrologs.log) zu schreiben, sie per localfile einzulesen und einen Decoder so zu gestalten, dass er auch bei leicht variierenden Logformaten stabil funktioniert.


Ausgangslage / Problemstellung

Beispiel-Log (relevanter Teil):
ubnt-idsips-daemon[1973]: ... Warn: get dst iface failed, srcIp:192.168.x.x, srcPort:..., dstIp:..., dstPort:..., protocol:UDP, err:Not found ...

Symptome:

  • Events kommen an (Syslog/UDP/TCP), werden aber nicht als UDM-Event erkannt
  • Custom Decoder „matcht nicht“
  • Regeln, die auf dstport/protocol prüfen, feuern nicht

Warum der Decoder im Thread oft nicht greift (typische Ursachen):

  1. Maskierte Ports im Beispiel (srcPort:***, dstPort:**) → Regex erwartet \d+ und kann nicht matchen.
  2. Der Log enthält zusätzliche Prefix-Teile (Timestamp, Warn:, Freitext), wodurch ein „zu strenger“ Regex schnell scheitert.
  3. Regeln sind teils auf falsche Vorbedingungen gebaut (<if_sid>100501</if_sid>/Regex mit PROTO=), die im UDM-Log gar nicht vorkommen.

Technische Analyse

Wazuh klassifiziert Syslog in Stufen:

  1. Predecoder extrahiert u. a. hostname, program_name, timestamp
  2. Decoder matcht auf program_name und extrahiert strukturierte Felder aus full_log
  3. Rules können danach direkt auf statische Felder wie <protocol>, <dstport>, <srcip> prüfen – ohne zusätzliche Regex-Spaghetti

Für UDM-Logs ist es daher best practice, den Decoder an program_name=ubnt-idsips-daemon zu binden und dann mit einem robusten Regex die Key/Value-Segmente (srcIp:, dstIp:, dstPort: etc.) zu parsen.


Lösung / Best Practices

1) UDM-Logs in eine eigene Datei UDMPrologs.log schreiben und via localfile einlesen

Der stabilste Weg ist: Rsyslog nimmt Remote-Syslog an, schreibt UDM-Events in eine eigene Datei, Wazuh liest diese Datei per localfile.

Beispiel rsyslog (Relay oder direkt auf dem Wazuh-Server), Datei: /etc/rsyslog.d/30-udm.conf

# UDM Pro Events in eigenes File
if ($programname == "ubnt-idsips-daemon") then {
  action(type="omfile" file="/var/log/UDMPrologs.log")
  stop
}

Dateirechte:

touch /var/log/UDMPrologs.log
chown syslog:adm /var/log/UDMPrologs.log
chmod 640 /var/log/UDMPrologs.log
systemctl restart rsyslog

Wazuh Manager: localfile-Eintrag in /var/ossec/etc/ossec.conf

<localfile>
  <log_format>syslog</log_format>
  <location>/var/log/UDMPrologs.log</location>
</localfile>

Danach:

systemctl restart wazuh-manager

Damit entkoppelst du Syslog-Transport/Noise sauber vom Wazuh-Parsing und kannst gezielt nur UDM-Events debuggen.


2) Decoder robust machen (nicht zu streng, Ports optional tolerant)

Lege eine Datei z. B. /var/ossec/etc/decoders/udm_decoders.xml an:

<decoders>

  <!-- Basis: bindet an den Syslog program_name -->
  <decoder name="udm-idsips-base">
    <program_name>ubnt-idsips-daemon</program_name>
  </decoder>

  <!-- Details: extrahiert Key/Value aus dem Message-Teil -->
  <decoder name="udm-idsips-kv">
    <parent>udm-idsips-base</parent>

    <!-- prematch reduziert False Positives -->
    <prematch>srcIp:|dstIp:|protocol:</prematch>

    <!-- toleranter Regex: Ports können digits sein; err kann Kommas/Brackets enthalten -->
    <regex>srcIp:([0-9.]+),\s*srcPort:([0-9]+|\*+),\s*dstIp:([0-9.]+),\s*dstPort:([0-9]+|\*+),\s*protocol:([A-Za-z0-9_-]+),\s*err:(.*)$</regex>

    <order>srcip,srcport,dstip,dstport,protocol,extra_data</order>
  </decoder>

</decoders>

Warum diese Anpassungen helfen:

  • ([0-9]+|\*+) erlaubt reale Ports und maskierte Beispiele (***) im Test
  • prematch sorgt dafür, dass der Decoder nur dann versucht zu parsen, wenn typische Marker vorhanden sind
  • err:(.*)$ nimmt den Rest der Zeile, auch wenn Kommas/Listen enthalten sind

Rechte setzen:

chown wazuh:wazuh /var/ossec/etc/decoders/udm_decoders.xml
chmod 660 /var/ossec/etc/decoders/udm_decoders.xml
systemctl restart wazuh-manager

3) Regeln korrekt auf die extrahierten Felder aufbauen

Erstelle z. B. /var/ossec/etc/rules/udm_rules.xml:

<group name="udm_pro,unifi,">

  <!-- Gruppierungsregel: alles was als UDM erkannt wird -->
  <rule id="100355" level="3">
    <decoded_as>udm-idsips-base</decoded_as>
    <description>UniFi UDM Pro IDS/IPS Event</description>
  </rule>

  <!-- Beispiel: Sensible Zielports 22/3389, TCP oder UDP -->
  <rule id="100356" level="10">
    <if_sid>100355</if_sid>
    <protocol>TCP|UDP</protocol>

    <!-- dstport ist ein statisches Feld; pcre2 für sauberes Matching -->
    <dstport type="pcre2">^(22|3389)$</dstport>

    <description>UDM Pro: Zugriff auf sensiblen Port $(dstport) von $(srcip) nach $(dstip)</description>
    <group>authentication_attempt,network,</group>
  </rule>

</group>

Danach:

chown wazuh:wazuh /var/ossec/etc/rules/udm_rules.xml
chmod 660 /var/ossec/etc/rules/udm_rules.xml
systemctl restart wazuh-manager

4) Decoder/Regeln testen (ohne Raten)

Für schnelle Validierung (und um exakt zu sehen, warum ein Decoder nicht matcht):

/var/ossec/bin/wazuh-logtest

Dort den Original-Log aus /var/log/UDMPrologs.log einfügen (nicht die indexierte Darstellung aus dem Dashboard). Wenn du maskierte Ports testest, muss der Regex das tolerieren – für den produktiven Real-Log sind Ports i. d. R. numerisch.


Lessons Learned / Best Practices

  • Immer den Raw-Log testen, den Wazuh wirklich parst (full_log/Dateiinhalt), nicht die im Dashboard angezeigte, ggf. gekürzte Darstellung.
  • Regex nicht zu eng: UDM-Logs variieren zwischen Firmware-Versionen; tolerante K/V-Parser sind stabiler als „perfekte“ Regex.
  • Ports/Protokolle als statische Felder nutzen: In Wazuh-Regeln sind <protocol>, <dstport>, <srcip> dafür da, direkt zu matchen – das ist wartungsärmer als große <regex>-Blöcke.
  • Separate Datei + localfile erleichtert Betrieb**:** du kannst UDM-Parsing isoliert debuggen und die Pipeline sauber kontrollieren.

Fazit

Wenn ein UDM-Decoder „nicht funktioniert“, liegt es in der Praxis fast immer an einem zu strengen Regex (z. B. Ports als \d+, obwohl im Test *** steht) oder daran, dass die Logs nicht sauber isoliert werden. Mit einer dedizierten Logdatei UDMPrologs.log, localfile-Ingest und einem toleranten K/V-Decoder bekommst du stabile Feldextraktion – und kannst darauf Regeln für sensible Zielports, Protokolle und Fehlermuster zuverlässig aufbauen.

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/p1765948285664639