Published on January 20, 2025
In Wazuh, custom rules help you monitor specific events or logs and
raise alerts that matter to you. The default rule set is quite broad,
and sometimes a built-in rule (like ID 40700 in the systemd group)
triggers before your own rule does. Below, we’ll walk through how to
create a custom rule, test it, and chain it correctly using
<if_sid>
if another rule is firing first.
Let’s start by creating a simple custom rule. Suppose you have a
service named myService that writes logs to
/var/log/syslog
(or another standard location). We want
to generate an alert whenever myService logs a
particular message.
In your Wazuh Manager, edit the file that contains local rules (often /var/ossec/etc/rules/local_rules.xml or similar path):
<group name="custom_rules_example,">
<rule id="100010" level="5">
<program_name>myService</program_name>
<regex>SOMETHING INTERESTING</regex>
<description>User defined rule for myService</description>
<group>custom_rules_example</group>
<status>enabled</status>
</rule>
</group>
This rule looks for any syslog message whose program_name
is myService
and whose content includes the text
SOMETHING INTERESTING.
Once you’ve saved your rule, you can test it by using the
wazuh-logtest
tool (or a similar log test utility),
typing a log line that matches your conditions. For example:
Dec 25 20:45:02 MyHost myService[1234]: SOMETHING INTERESTING
If everything is set up properly, the tool will show that your custom
rule (ID 100010
) was triggered. This confirms your
rule’s syntax and logic are correct. Be sure to restart the Wazuh
Manager for real alerts to be generated.
Sometimes you’ll notice a different rule fires first and prevents yours from appearing in alerts. Look at the alerts or the output of your log testing tool. If you see a default rule ID (for example, 40700) always triggered on the same log, that’s your overlapping rule. Wazuh usually prints the ID of whichever rule is taking precedence in its logs.
If you find such a rule, note its ID—this will be used for chaining in the next step.
Now you have the id of the guilty rule. To fix this, you can chain your custom
rule to the default rule by using
<if_sid>40700</if_sid>
.
Here’s an example of that approach:
<group name="custom_rules_example,">
<rule id="100010" level="5">
<if_sid>40700</if_sid>
<regex>myService</regex>
<description>Chained custom rule for myService</description>
<group>custom_rules_example</group>
<status>enabled</status>
</rule>
</group>
The <if_sid>
tag ensures that your rule is only
evaluated if rule 40700 already matched the log.
This lets you refine or narrow down alerts for a service that’s
grouped under systemd events.
<if_sid>
to ensure your custom rule still fires.