Configuring Suricata-update to run on a dedicated host

I’m setting up Suricata-update to run on a dedicated host to update the rules for multiple Suricata systems (it could be 10’s to 100’s of systems). It automatically detects the Suricata version running on all of the Suricata host and then runs Suricata-update once for each version (using the --suricata-version argument). Then I push the appropriate version of the suricata.rules file to each Suricata host and reload the rules.

The problem I’m running into is, I cannot get Suricata-update to load the suricata config (suricata-conf) without the full Suricata program loaded on the dedicated Suricata-update host. I tried to add all of the disabled protocols from the Suricata config to the disable.conf file but there is no documented way to disable rules based on protocol.

So the question is, how do I get the Suricata config to load without installing Suricata or how do I copy all of the settings from the Suricata config to the relevant enable.conf or disable.conf files?

Currently the answer to that question is you don’t. Suricata-Update calls suricata -c <config> --dump-config to get at the Suricata configuration, rather than parsing the YAML directly. Parsing the YAML isn’t as simple as just loading it with the Python YAML module if there are any sort of includes. So this ensures that Suricata-Update sees the same configuration that Suricata sees.

Internally there is a “protocol” rule matcher, but that is not exposed to disable.conf, etc. Your best bet for now would a regex like:

re: ^alert\s+modbus

which should have the same result.

I read through all the source python and noticed how it parsed the dump-config but could not figure out how to use the ‘disable_matchers’ with ‘proto’. It would be a good feature to expose this to disable.conf files.

The regex works for me. Would that format work for all of the protocols?

I need to disable the following:
rdp
modbus
dnp3
enip
sip

Yes, that should work for all of them.

What about the ja3 files? Some of the documentation says you can use re:ja3_hash to disable them. However, when you disable them with the Surciata-conf, 128 rules get disabled. When I use the regex, only 115 rules get disabled.

The JA3 support in Suricata-Update came before Suricata more gracefully handled the ja3 keyword when there wasn’t support for it. So you don’t really need to disable these rules. But if you do, you’ll want to match on the keywords:

  • ja3.hash
  • ja3.string
  • ja3s.string

Those combined disable 127 rules. It looks like it’s still missing one. I’m doing a diff now.

Maybs ja3s.hash as well. Suricata-Update just parses the keywords and disables any rule with a keyword that starts with ja3 rather than having a complete list of possible keywords.

I looked at the Suricata-Update code and it’s looking for any rule name the begins with “ja3”. I changed the disable.conf rule to match it re: \s+ja3

This still only logged 127 rules disabled. However, when I grep the suricata.rules file, there are 128 disabled rules that match the regex.

Could use be be disabled in the source ruleset?

Hello James,

I would like to understand how did you configure Suricata-update to run on a dedicated host to update the rules for multiple Suricata systems (10 systems for me)
is there any specific configuration for suricata-update config file for this?
Note, i have same suticata version running on all 1 systems

I have an Ansible Role that:

  1. Reaches out to all the sensors in an inventory file and collect the version of Suricata running on them and build a version list.
  2. Run Suricata-update once for each unique version in the list and store the suricata.rules file in a folder with the version number.
  3. Then push the appropriate suricata.rules file to each sensor.
  4. Restart the Suricata service on each sensor.

One fact about the above approach is the ruleset will get pushed to each sensor and the service gets restarted even if the ruleset did not change.

However, I’m considering a different approach. Instead of configuring the central Suricata-update host to push the new rulesets, just have it store the new rulesets in a folder that is accessible via a URL. That would allow the remote sensors to run Suricata-update locally and pull the ruleset from the central Suricata-update host. It would use the built-in intelligence of Suricata-update to only restart the service if needed.

It would look like this. The central Suricata-update host would:

  1. Reach out to all the sensors in an inventory file and collect the version of Suricata running on them and build a version list. (You could skip this step with a manually configured list of versions)
  2. Run Suricata-update once for each unique version in the list and store the suricata.rules file in a folder with the version number. This would happen first, for example, a cron job would run a 1:00 AM (The folder would need to already be reachable via a unique URL)
  3. Each remote sensor would be configured to pull from a custom source with a URL that would point to the location the central Suricata-update host stores the rulesets.
  4. Each remote sensor would run Suricata-update with a cron job any time after 1:00 AM and pull the rulesets on their own.

If you want to look at the Ansible Role I have feel free. It’s main purpose is to manage Corelight Sensors that have Zeek and Suricata running on them. The physical appliances cannot run Suricata-update so I will still have to push the rulesets to them with an API (Corelight-client). The Corelight software sensors run on any Linux host so Suricata-update can easily be included.

https://github.com/corelight/Corelight-Ansible-Roles/tree/main/roles/suricata_update_config

You don’t have to restart Suricata, you can send USR2 signal or use the suricatasc socket control to trigger just a rule reload without restarting Suricata itself.

I actually use the USR2 signal. Still the downside of my current solution is that it sends the signal regardless of the ruleset that’s loaded.