Hello Rukender,
The following decoders and rule should fit you use case. Feel free to rename any field that has a different header name.
Decoders (Place it on /var/ossec/etc/rules/local_rules.xml)
<decoder name="haproxy1">
<parent>haproxy</parent>
<regex>(\S+):(\S+) [(\S+)] (\S+) (\S+)/(\S+) (\d+/\d+/\d+/\d+/\d+) (\S+) (\S+)</regex>
<order>client_ip, client_port, accept_date, frontend_name, backend_name, server_name, timer, status_code, response_lenght</order>
</decoder>
<decoder name="haproxy1">
<parent>haproxy</parent>
<regex offset="after_regex">- - (\S+) (\d+/\d+/\d+/\d+/\d+) (\d+/\d+)</regex>
<order>state, connections, queue</order>
</decoder>
<decoder name="haproxy1">
<parent>haproxy</parent>
<regex offset="after_regex">{(\.*)} "(\.*)"</regex>
<order>headers ,http_request</order>
</decoder>
Rule (You should place it on /var/ossec/etc/rules/local_rules.xml)
<rule id="100002" level="3">
<decoded_as>haproxy</decoded_as>
<description>Haproxy logs</description>
</rule>
Example alert using the ossec-logtest binary
^C[root@puppet vagrant]# /var/ossec/bin/ossec-logtest
2020/10/20 14:52:07 ossec-testrule: INFO: Started (pid: 24664).
ossec-testrule: Type one log per line.
Oct 20 02:29:21 localhost haproxy[12083]: 3.3.3.3:55116 [20/Oct/2020:02:29:21.400] www-https~ tm_cluster/tm 0/0/0/9/9 200 537 - - ---- 32/32/0/0/0 0/0 {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85 1 Safari/537|https://<url>} "GET /api/tm/v1/account/login/ssostatus/?app=<appname> HTTP/1.1"
**Phase 1: Completed pre-decoding.
full event: 'Oct 20 02:29:21 localhost haproxy[12083]: 3.3.3.3:55116 [20/Oct/2020:02:29:21.400] www-https~ tm_cluster/tm 0/0/0/9/9 200 537 - - ---- 32/32/0/0/0 0/0 {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85 1 Safari/537|https://<url>} "GET /api/tm/v1/account/login/ssostatus/?app=<appname> HTTP/1.1"'
timestamp: 'Oct 20 02:29:21'
hostname: 'localhost'
program_name: 'haproxy'
log: '3.3.3.3:55116 [20/Oct/2020:02:29:21.400] www-https~ tm_cluster/tm 0/0/0/9/9 200 537 - - ---- 32/32/0/0/0 0/0 {Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85 1 Safari/537|https://<url>} "GET /api/tm/v1/account/login/ssostatus/?app=<appname> HTTP/1.1"'
**Phase 2: Completed decoding.
decoder: 'haproxy'
client_ip: '3.3.3.3'
client_port: '55116'
accept_date: '20/Oct/2020:02:29:21.400'
frontend_name: 'www-https~'
backend_name: 'tm_cluster'
server_name: 'tm'
timer: '0/0/0/9/9'
status_code: '200'
response_lenght: '537'
state: '----'
connections: '32/32/0/0/0'
queue: '0/0'
headers: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85 1 Safari/537|https://<url>'
http_request: 'GET /api/tm/v1/account/login/ssostatus/?app=<appname> HTTP/1.1'
**Phase 3: Completed filtering (rules).
Rule id: '100002'
Level: '5'
Description: 'Haproxy logs'
**Alert to be generated.
Let me know if it works. Greetings,
JP
Hello again Rukender,
Thank you so much for your help.
Yes, it is working fine.
I’m glad it helps!
As we have decoder for HAproxy, we need not to write decoder again for any new rule related to HAproxy?
That’s it, for any logs having the HAproxy format, the decoder should work. Also you could add any rules pointing to the root HAproxy rule included in my previous message. i.e:
<rule id="100003" level="3">
<if_sid>100002</if_sid>
<field name="status_code">404</field>
<description>HTTP request returned 404 error</description>
</rule>
There are some other log event in HAproxy for login event etc for which I want to write rules to get the alert in Wazuh. So, if I just add new rule in /var/ossec/etc/rules/local_rules.xml after the rule you shared will work?
Yes, new rules in /var/ossec/etc/rules/local_rules.xml should work. Keep in mind that you should build the new rules from the 100001 that triggers on any HAproxy event. That’s why I include the if_sid option in the example above <if_sid>100002</if_sid>.
Count on me if you have further questions when writing the new rules.
Greetings,
JP
Greetings,
JP
Hey Rukende,
I have a question about writing the decoder: what is the program_name in decoder -- this name should be present in my logs event or I can give any name.
Syslog logs print the program name and its PID in each log line following the program_name[PID] syntax. i.e: Dec 10 01:02:02 host sshd[1234]: Failed none for root from 1.1.1.1 port 1066 Wazuh extracts the program name during the pre-decoding stage and it can be checked from a rule using the option. In conclusion, the program_name in your decoder should match the name present in your logs.
Any tips you want to give me for writing decoder.
With the current decoders, you should be able to process the HAproxy logs and extract all the values inside. I think the next step should be creating rules pointing to the base rule base. The new rules should check the HAproxy logs values searching for unexpected values. i.e:
<rule id="100003" level="3">
<if_sid>100002</if_sid>
<field name="status_code">500</field>
<description>HTTP request returned 500 error</description>
</rule>
Let me know more details about your use case so we can guess useful rules.
Greetings,
JP