Suricata Custom Ruleset will not Load into `suricata.rules`

I am running Suricata in IDS (af-packet) mode on Ubuntu 20.04.5 LTS (Focal Fossa) and deployed as the root user:

NAME="Ubuntu"
VERSION="20.04.5 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.5 LTS"
VERSION_ID="20.04"

Following the Suricata “Adding your own Rules” Doc, I have added a very basic (for complexity ease when troubleshooting) alerting-rule with first available sid:1000000 from custom rules range:

########### Test Rules #############
alert ssh any any -> xxx.xxx.60.6 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000000;)

The .rules file for the local rules has sufficient permissions and matches suricata.rules, owned by root:

ls -halt /var/lib/suricata/rules/
total 22M
-rw-r--r-- 1 root root 3.2K Oct 17 00:00 classification.config
drwxr-x--- 2 root root 4.0K Oct 17 00:00 .
-rw-r--r-- 1 root root  22M Oct 17 00:00 suricata.rules
-rw-r--r-- 1 root root  210 Oct 13 21:45 local.rules

Ensured that the rules are added to Suricata suricata.yaml config and processed is restarted:

cat /etc/suricata/suricata.yaml | grep "rule-files" -A 5 -B 5
##

#default-rule-path: /var/lib/suricata/rules

default-rule-path: /etc/suricata/rules
rule-files:
  - suricata.rules
  - /var/lib/suricata/rules/local.rules
  - /etc/suricata/rules/*.rules

AFAIK, the custom ruleset should be loaded into the suricata.rules file? Therefore, I am running the following verification subject to what I am reporting:

cat /var/lib/suricata/rules/suricata.rules | grep sid:1000000

I can test traffic and verify with tcpdump, matching the rule but never see a signature match in fast.log (which is logging other signature-matching traffic):

cat /var/log/suricata/fast.log | grep 1000000

I see no errors following statup of the service that would indicate an error present:

systemctl status suricata.service
● suricata.service - LSB: Next Generation IDS/IPS
     Loaded: loaded (/etc/init.d/suricata; generated)
     Active: active (running) since Mon 2022-10-17 13:11:39 UTC; 8h ago
       Docs: man:systemd-sysv-generator(8)
    Process: 2184275 ExecStart=/etc/init.d/suricata start (code=exited, status=0/SUCCESS)
      Tasks: 78 (limit: 618963)
     Memory: 25.2G
     CGroup: /system.slice/suricata.service
             └─2184295 /usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata.pid --af-packet -D -v>

Oct 17 13:11:39 sec3 systemd[1]: Starting LSB: Next Generation IDS/IPS...
Oct 17 13:11:39 sec3 suricata[2184275]: Starting suricata in IDS (af-packet) mode... done.
Oct 17 13:11:39 sec3 systemd[1]: Started LSB: Next Generation IDS/IPS.

Can somebody help me with somewhere I may be silly here?

TYIA!

Can you paste your suricata.log output, there you should see how many rule files and rules have been loaded.

Hey @Andreas_Herz
Thanks for your response! /var/log/suricata/suricata.log is pretty hefty, PLMK if you need anything else for observation and if you have any ideas at all?

I see it error on my custom rule at line 6 with SC_ERR_INVALID_SIGNATURE

19/10/2022 -- 03:29:40 - <Config> - IP reputation disabled
19/10/2022 -- 03:29:40 - <Config> - Loading rule file: /var/lib/suricata/rules/suricata.rules
19/10/2022 -- 03:29:45 - <Config> - Loading rule file: /var/lib/suricata/rules/local.rules
19/10/2022 -- 03:29:45 - <Error> - [ERRCODE: SC_ERR_INVALID_RULE_ARGUMENT(270)] - no rule options.
19/10/2022 -- 03:29:45 - <Error> - [ERRCODE: SC_ERR_INVALID_SIGNATURE(39)] - error parsing signature "content:"Ads"; nocase; classtype:policy-violation; sid:1; rev:1;)" from file /var/lib/suricata/rules/local.rules at line 6
19/10/2022 -- 03:29:45 - <Config> - Loading rule file: /etc/suricata/rules/app-layer-events.rules
19/10/2022 -- 03:29:45 - <Error> - [ERRCODE: SC_ERR_DUPLICATE_SIG(176)] - Duplicate signature "alert ip any any -> any any (msg:"SURICATA Applayer Mismatch protocol both directions"; flow:established; app-layer-event:applayer_mismatch_protocol_both_directions; flowint:applayer.anomaly.count,+,1; classtype:protocol-command-decode; sid:2260000; rev:1;)"

I don’t understand why, I got the rule example from this DigitalOcean KB

########### Test Rules #############

alert ssh any any -> xxx.xxx.60.6 !22 (msg:"SSH TRAFFIC on non-SSH port"; flow:to_client, not_established; classtype: misc-attack; target: dest_ip; sid:1000000;)

alert http any any -> any any (msg:"Do not read gossip during work";
content:"Ads"; nocase; classtype:policy-violation; sid:1; rev:1;)

The only other logs relating to rule loading failures are for suricata.update-related ET rules. (Interestingly all also with SC_ERR_INVALID_SIGNATURE(39)] error message)

Found the issue for my other rules, I assume Suricata does not accept wildcards? /etc/suricata/rules/*.rules

19/10/2022 – 03:29:45 - - No rules loaded from /etc/suricata/rules/*.rules.
19/10/2022 – 03:29:45 - - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /etc/suricata/rules/ioc-dataset.rules.
19/10/2022 – 03:29:45 - - No rules loaded from /etc/suricata/rules/ioc-dataset.rules…
19/10/2022 – 03:29:45 - - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /etc/suricata/rules/crypto-currency-rules.rules
19/10/2022 – 03:29:45 - - No rules loaded from /etc/suricata/rules/crypto-currency-rules.rules.

From my /etc/suricata/suricata.yaml config file:

## Configure Suricata to load Suricata-Update managed rules.
##

default-rule-path: /var/lib/suricata/rules

rule-files:
  - suricata.rules
  - /var/lib/suricata/rules/local.rules
  - /etc/suricata/rules/*.rules
  - /etc/suricata/rules/ioc-dataset.rules.
  - /etc/suricata/rules/crypto-currency-rules.rules
##

A modern Suricata install will set default-rule-path to /var/lib/suricata/rules, what isn’t that clear is that this directory is really for suricata-update, and not for the user to put files in. So what I recommend is to put your custom rules in /etc/suricata/rules/local.rules or whatever, and reference these files directly in your suricata.yaml. So you end up with something like:

default-rule-path: /var/lib/suricata/rules

rule-files:
  - suricata.rules
  - /etc/suricata/rules/local.rules

This does keep them out of view of suricata-update, so you’ll have to signal suricata yourself to reload the rules after an update of your local.rules. There are ways to have suricata-update pull in your custom rule files to be included in /var/lib/suricata/rules/suricata.rules if you want that. See the example configuration file for how this can be done: suricata-update - Update — suricata-update 1.3.0dev0 documentation

Thanks @ish ! I see and almost interpreted the same after I read the comment ## Configure Suricata to load Suricata-Update managed rules. over and over to myself :upside_down_face:

Within suricata.yaml:

  • Understood, so default-rule-path relates to the suricata-update and not custom files.
  • To confirm, the “rule-files:”, are these also relating to Suricata update, or my custom rules no matter the path specified? I.E, I could place these in a completely random directory and reference them here?

As per my current suricata.yaml config:

default-rule-path: /var/lib/suricata/rules

rule-files:
  - suricata.rules
  - /var/lib/suricata/rules/local.rules
  - /etc/suricata/rules/*.rules
  - /etc/suricata/rules/ioc-dataset.rules
  - /etc/suricata/rules/crypto-currency-rules.rules
  • I assume suricata.yaml does not accept wildcards? /etc/suricata/rules/*.rules
rule-files:
  - /etc/suricata/rules/*.rules
  • As you said, I need to move - /var/lib/suricata/rules/local.rules to /etc/suricata/rules/local.rules and update the config path

I have no update.yaml file specified. If I execute suricata-update I see the following in the logs:

20/10/2022 -- 15:20:54 - <Info> -- Using data-directory /var/lib/suricata.
20/10/2022 -- 15:20:54 - <Info> -- Using Suricata configuration /etc/suricata/suricata.yaml
20/10/2022 -- 15:20:54 - <Info> -- Using /etc/suricata/rules for Suricata provided rules.
20/10/2022 -- 15:20:54 - <Info> -- Found Suricata version 6.0.8 at /usr/bin/suricata.
20/10/2022 -- 15:20:54 - <Info> -- Loading /etc/suricata/suricata.yaml
..
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/app-layer-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/decoder-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/dhcp-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/dnp3-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/dns-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/files.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/http-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/ipsec-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/kerberos-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/modbus-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/nfs-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/ntp-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/smb-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/smtp-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/stream-events.rules
20/10/2022 -- 15:20:55 - <Info> -- Loading distribution rule file /etc/suricata/rules/tls-events.rules

I assume from the logs that its loading the Suricata provided rules from /etc/suricata/rules

20/10/2022 -- 15:20:54 - <Info> -- Using Suricata configuration /etc/suricata/suricata.yaml
20/10/2022 -- 15:20:54 - <Info> -- Using /etc/suricata/rules for Suricata provided rules.

its writing the files to /var/lib/suricata/rules based on the configuration above.

20/10/2022 -- 15:20:59 - <Info> -- Writing rules to /var/lib/suricata/rules/suricata.rules: total: 42209; enabled: 34608; added: 0; removed 0; modified: 430
20/10/2022 -- 15:20:59 - <Info> -- Writing /var/lib/suricata/rules/classification.config

All my ET-threats and suricata-update rules are dated on the date of my initial Suricata deployment.

ls -halt /etc/suricata/rules/
total 140K
drwxr-xr-x 3 root root 4.0K Oct 19 23:16 ..
drwxr-xr-x 2 root root 4.0K Oct 12 09:09 .
-rw-r--r-- 1 root root  21K Sep 27 18:01 decoder-events.rules
-rw-r--r-- 1 root root 2.1K Sep 27 18:01 http2-events.rules
-rw-r--r-- 1 root root  14K Sep 27 18:01 http-events.rules
...

If Suricata is updating these rules, would I not expect to see the modified dates of these files to be the day that suricata-update runs, or am I missing something else here?

You’ll probably want this to be:

default-rule-path: /var/lib/suricata/rules

rule-files:
  - suricata.rules
  - /etc/suricata/rules/local.rules
  - /etc/suricata/rules/ioc-dataset.rules
  - /etc/suricata/rules/crypto-currency-rules.rules

What suricata-update does is:

  • Load rules that are provided by the engine from /etc/suricata/rules/, it knows which ones these are so limits the loading to this. This is a temporary measure, as in 7.0 the engine will no longer be installing rules there, instead the engine will install to /usr/share/suricata/rules (distribution depending) and suricata-update will pull the rules from there.
  • These no rule files end up merged in /var/lib/suricata/rules/suricata.rules along with any other rules that suricata-updated downloaded.

So the above configuration snippet is only telling Suricata about the rule files that you maintain manually.

While this works, for the reasons above you might want to avoid it for now, it could resulti in double inclusion of rules. As many of those rules will already exist in /var/lib/suricata/rules/suricata.rules.

This looks correct. These rule files in particular are provided by the Suricata package itself. They may get updated when Suricata is updated.

I’m not sure how you manage your ET rules, but if possible just let Suricata-Update manage them. They get downloaded and merged into /var/lib/suricata/rules/suricata.rules. So should always be up to date. If you see individual ET provided rule files on your system they may be an artifact of an old install? But were not placed there by Suricata or Suricata-Update, at least not with versions since 6.0.

The docs could probably be better about that, and the next Suricata major release will not drop engine provided rules in /etc. They are there more as an artifact of how Suricata used to install rules. In fact a fresh install of Suricata 6.0.x does not install any rules in /etc, this comes from the apt package, and we do have tickets to remove this behaviour in the next major release when it comes to packaging as well.

If still having issues, perhaps describe what you are trying to achieve, and I can probably propose the best way to get there.

Hey @ish
Thanks so much for your help.
I was being super dumb, thanks for pointing that out… I should wildcard anything in a custom dir not /etc/suricata/rules as I am causing myself DUP errors and since amending the config now looks a lot cleaner!

Fixed up my local.rules

# ls -halt /var/log/suricata/suricata.log
-rw-r--r-- 1 root root 67K Oct 20 16:50 /var/log/suricata/suricata.log

cat /var/log/suricata/suricata.log | grep "/etc/suricata/rules/local.rules" -B 5 -A 5
20/10/2022 -- 16:55:06 - <Perf> - using shared mpm ctx' for icmpv6.hdr
20/10/2022 -- 16:55:06 - <Perf> - using shared mpm ctx' for ipv4.hdr
20/10/2022 -- 16:55:06 - <Perf> - using shared mpm ctx' for ipv6.hdr
20/10/2022 -- 16:55:06 - <Config> - IP reputation disabled
20/10/2022 -- 16:55:06 - <Config> - Loading rule file: /var/lib/suricata/rules/suricata.rules
20/10/2022 -- 16:55:11 - <Config> - Loading rule file: /etc/suricata/rules/local.rules
20/10/2022 -- 16:55:11 - <Warning> - [ERRCODE: SC_ERR_NO_RULES(42)] - No rule files match the pattern /etc/suricata/rules/ads-ioc-dataset.rules

I see no errors, so I assume it loaded and my custom rules were successful.

I am experiencing unrelated issues using bonded interfaces in Multiple interfaces on the same machine](Multiple interfaces on the same machine - #13 by ADudeWhoSurfs)

Therefore, my stats are failing too which is a pain

# suricatasc -c ruleset-stats /usr/local/var/run/suricata/suricata-command.socket
Unable to connect to socket /usr/local/var/run/suricata/suricata-command.socket: [Errno 2] No such file or directory

Also learning a bunch so really appreciate your patience and all of your expertise.