pfSense-Logs in Wazuh: Custom Decoder für fehlenden Hostnamen im BSD-Syslog-Format

Einleitung

pfSense-Firewall-Logs sind eine wertvolle Datenquelle für Wazuh, insbesondere für die Erkennung blockierter Verbindungen, Portscans, lateral movement und unerwünschter Remote-Zugriffe. In der Praxis scheitert die Verarbeitung jedoch manchmal schon vor dem eigentlichen Decoder: Wenn pfSense-Logs im BSD-Syslog-Format ohne Hostnamen gesendet werden, verschiebt sich die Vorverarbeitung in Wazuh.

Ausgangslage / Problemstellung

Ein Wazuh Manager empfängt pfSense-Logs über Rsyslog im BSD-Format nach RFC 3164. Ein Beispiel-Log sieht so aus:

Feb 11 18:15:43 filterlog[00000]: 8,,,1000000000,vmx1,match,block,in,4,0x88,,48,6840,0,none,6,tcp,48,1.2.3.4,5.6.7.8,65435,80,0,S,1000751876,,0,,mss;wscale;eol

In wazuh-logtest zeigt sich das Problem bereits in Phase 1:

hostname: 'filterlog[00000]:'
program_name: empty

Da der Standard-pfSense-Decoder in Wazuh auf program_name mit filterlog prüft, greift der Decoder nicht.

Technische Analyse

Das Log enthält zwischen Zeitstempel und Programmtag keinen Hostnamen:

Feb 11 18:15:43 filterlog[00000]:

Wazuh interpretiert deshalb filterlog[00000]: als Hostnamen. Das eigentliche Programfeld bleibt leer. Dadurch schlägt ein Decoder mit folgender Bedingung fehl:

<program_name>filterlog</program_name>

Das ist kein klassisches Regelproblem, sondern ein Pre-Decoding-Problem. Die Lösung besteht darin, einen alternativen Decoder zu erstellen, der nicht von program_name, sondern vom Inhalt des Rohlogs ausgeht.

Lösung / Best Practices

Ein eigener Decoder kann auf filterlog[PID] matchen und anschließend die relevanten CSV-Felder extrahieren:

<decoder name="pf-alt">
<prematch>filterlog[\d+]</prematch>
</decoder>

<decoder name="pf-alt-fields">
<parent>pf-alt</parent>
<regex>^\S+ \S*,\S*,\S*,(\S*),\S*,\S*,(\S*),</regex>
<order>id,action</order>
</decoder>

<decoder name="pf-alt-fields">
<parent>pf-alt</parent>
<regex offset="after_regex">\S*,\S*,\S*,\S*,\S*,\S*,\S*,\S*,\S*,(\S*),\S*,(\S*),(\S*),</regex>
<order>protocol,srcip,dstip</order>
</decoder>

<decoder name="pf-alt-fields">
<parent>pf-alt</parent>
<regex offset="after_regex">(\d*),(\d*),\S*</regex>
<order>srcport,dstport</order>
</decoder>

<decoder name="pf-alt-fields">
<parent>pf-alt</parent>
<regex offset="after_regex">datalength=(\S*)|(\d*)</regex>
<order>length</order>
</decoder>

Die Datei kann beispielsweise hier abgelegt werden:

/var/ossec/etc/decoders/pfsense.xml

Danach den Manager neu starten:

systemctl restart wazuh-manager

Die Funktion lässt sich mit wazuh-logtest prüfen:

echo 'Feb 11 18:15:43 filterlog[00000]: 8,,,1000000000,vmx1,match,block,in,4,0x88,,48,6840,0,none,6,tcp,48,1.2.3.4,5.6.7.8,65435,80,0,S,1000751876,,0,,mss;wscale;eol' | /var/ossec/bin/wazuh-logtest

Erwartete Felder sind unter anderem:

name: pf-alt
action: block
srcip: 1.2.3.4
dstip: 5.6.7.8
protocol: tcp
srcport: 65435
dstport: 80

Darauf aufbauend können eigene Regeln erstellt werden:

<group name="pfsense,">
<rule id="120000" level="0">
<decoded_as>pf-alt</decoded_as>
<description>pfSense firewall events grouped by custom decoder.</description>
</rule>

<rule id="120001" level="5">
<if_sid>120000</if_sid>
<field name="action">block</field>
<description>pfSense firewall block event.</description>
<group>firewall_block,pci_dss_1.4,gpg13_4.12,nist_800_53_SC.7,</group>
</rule>

<rule id="120002" level="7" frequency="18" timeframe="45" ignore="240">
<if_matched_sid>120001</if_matched_sid>
<same_source_ip />
<description>Multiple pfSense firewall block events from same source.</description>
<mitre>
<id>T1110</id>
</mitre>
<group>multiple_blocks,pci_dss_10.6.1,nist_800_53_AU.6,</group>
</rule>
</group>

Spezifische Regeln für SSH, RDP oder interne Blockierungen können anschließend ergänzt werden:

<group name="pfsense,custom_rules,">
<rule id="120003" level="5">
<if_sid>120001</if_sid>
<dstport>22</dstport>
<protocol>tcp</protocol>
<description>pfSense: SSH connection attempt blocked from $(srcip)</description>
<group>authentication_failed,pci_dss_11.4,</group>
</rule>

<rule id="120004" level="6">
<if_sid>120001</if_sid>
<srcip>172.16.0.0/12</srcip>
<srcip>192.168.0.0/16</srcip>
<description>pfSense: Internal flow blocked from $(srcip) to $(dstip)</description>
<group>lateral_movement,</group>
</rule>

<rule id="120005" level="5">
<if_sid>120001</if_sid>
<dstport>3389</dstport>
<protocol>tcp</protocol>
<description>pfSense: RDP attempt blocked from $(srcip)</description>
<group>rdp_attack,</group>
</rule>
</group>

Zum Testen können passende Logzeilen kontrolliert in die pfSense-Syslog-Datei geschrieben werden. Wenn Decoder und Regeln korrekt sind, erscheinen die Alerts kurz darauf im Dashboard.

Lessons Learned / Best Practices

Wenn program_name leer bleibt, sollte zuerst Phase 1 in wazuh-logtest geprüft werden. Viele Decoder-Probleme entstehen nicht durch falsche Regex, sondern durch ein nicht erwartetes Syslog-Format.

Für pfSense ist es sauberer, wenn der Syslog-Forwarder einen Hostnamen zwischen Timestamp und Programmtag liefert. Ist das nicht möglich, ist ein alternativer Decoder mit prematch auf filterlog[...] ein robuster Workaround.

Regeln sollten auf tatsächlich extrahierte Felder prüfen. Für das Feld action ist in Wazuh-Regeln meist ein expliziter Feldvergleich robuster als ein XML-Tag, das nicht in jeder Situation wie erwartet interpretiert wird:

<field name="action">block</field>

Fazit

Fehlende Hostnamen in pfSense-BSD-Syslog-Events können dazu führen, dass Wazuh den Programmnamen nicht erkennt und der Standarddecoder nicht greift. Ein Custom Decoder, der direkt auf filterlog[PID] matched, löst das Problem zuverlässig. Danach lassen sich pfSense-Block-Events sauber klassifizieren, korrelieren und im Wazuh Dashboard auswerten.

Quellen

Wazuh Dokumentation: Custom Decoders
https://documentation.wazuh.com/current/user-manual/ruleset/decoders/custom.html

Wazuh Dokumentation: Decoders XML Syntax
https://documentation.wazuh.com/current/user-manual/ruleset/ruleset-xml-syntax/decoders.html

Wazuh Dokumentation: Rules XML Syntax
https://documentation.wazuh.com/current/user-manual/ruleset/ruleset-xml-syntax/rules.html

Externer Praxisartikel zu pfSense-Syslogs und Wazuh
https://marceltc.com/sending-pfsense-syslogs-to-wazuh-siem/

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/C07CCCCGHHP/p1770832160036299