How to set up Suricata on Vyos 1.5 rolling

Hello Folks,

I’m kinda new in Vyos, playing with it for a few days. I have to admit I love it! It’s very similar to Junos for me where I’m coming from, so I think that’s just a beggining of a a jurney.

At home I used an Ubuntu system until now to do firewalling as well together with pppoe, inter Vlan routing, wireguard, etc.
However I’m migrating my home setup to a bigger machine, so I decided to move to something more advanced. I managed to set up a Vyos router in just a few hours, and it works like charm.

I just found out that suricata has direct support in the 1.5 rolling release, and I started to play with it. Unfortunately I’m not quite sure about the configuration of it, documentation is not fully clear to me. I found this: suricata — VyOS 1.5.x (circinus) documentation

Is there anyone maybe with a bit more detailed docu, or is there anyone who uses this feature already?

1 Like

I’ve been working with suricata in VyOS for the past couple of weeks, so I’ll give you my 2 cents. One thing to keep in mind is I’ve come back to VyOS from experimenting with OPNsense, which while I did run into a few issues that is forcing me to come back to VyOS, their suricata implementation is pretty easy and works well. My goal for suricata in VyOS is to duplicate what I was able to do with OPNsense.

First I’ve focused on 2 methods for using suricata in VyOS: a) using a container, and b) the “native” ‘set service suricata’ method. The container method is from this post (Vyos firewall artificial intelligence support), which does work, but I never completed the final piece configuration incorporating it with the firewall. The one piece that I couldn’t get working was I want to have the suricata alerts sent to the VyOS syslog (JournalD) from the container so I can send them to an NMS system. I just couldn’t figure it out, and I’m thinking maybe it’s because VyOS uses podman, which there is a way to launch a container with podman and use a journald logging mechanism, but I couldn’t figure out how to do that with the ‘set container’ commands. I will point out that the default configuration in the container is to only run suricata in “IDS Mode”, and I want to get it running in “IPS Mode” as I have good hardware to handle the load. I’m sure it could be configured that way in the container, but not being able to figure out how to send alerts from the container is a show-stopper for me.

The second method is the “native” ‘set service suricata’ commands, which does work well, but again it’s in “IDS Mode” by default. Everything I want to do with syslog though works solid, so this is the way I’m going to use it. In order to get it working, I used below as my config which most of this may be overkill, but I just wanted to make sure it’s working, I basically duplicated the “vars:” and “port-groups” section of the /etc/suricata/suricata.yaml file to make sure everything is covered. BTW when you run the ‘set service suricata’ commands, a separate config file is generated and used in ‘/run/suricata/suricata.yaml’.

$ sudo ps -ef | grep -i suricata
root 756211 1 2 00:01 ? 00:20:15 /usr/bin/suricata -D --af-packet -c /run/suricata/suricata.yaml --pidfile /run/suricata/suricata.pid

my config:
set service suricata address-group home-net address ‘10.0.0.0/8’
set service suricata address-group external-net group ‘!home-net’

set service suricata address-group http-servers group ‘home-net’
set service suricata address-group smtp-servers group ‘home-net’
set service suricata address-group sql-servers group ‘home-net’
set service suricata address-group dns-servers group ‘home-net’
set service suricata address-group telnet-servers group ‘home-net’
set service suricata address-group aim-servers group ‘external-net’
set service suricata address-group dc-servers group ‘home-net’

set service suricata interface ‘eth2’ (internet interface)

set service suricata log eve filetype ‘syslog’
set service suricata log eve type ‘alert’
set service suricata log eve type ‘drop’

set service suricata port-group all-ports port ‘1-65535’
set service suricata port-group http-ports port ‘80’
set service suricata port-group shellcode-ports port ‘!80’
set service suricata port-group oracle-ports port ‘1521’
set service suricata port-group ssh-ports port ‘22’
set service suricata port-group file-data-ports group ‘http-ports’
set service suricata port-group file-data-ports port ‘110’
set service suricata port-group file-data-ports port ‘143’
set service suricata port-group ftp-ports port ‘21’
set service suricata port-group geneve-ports port ‘6081’
set service suricata port-group teredo-ports port ‘3544’
set service suricata port-group vxlan-ports port ‘4789’

Once you commit a config like this, then run ‘update suricata’ which under the covers is running ‘/usr/bin/suricata-update’ (standard update utility that comes with suricata). This brings down the .rules files, which by default are the ET/open (free) rules, which are a great place to start. Keep in mind that if you want to include additional rule sources, or create your own, you will need to manipulate the /run/suricata/suricata.yaml file directly as there doesn’t seem to be a way to do that in the ‘set service suricata’ commands? If you go that route, I would recommend running ‘/usr/bin/suricata-update’ with a ‘-v’ so you can really see what’s going on. That utility also allows you to add additional rule sources which again don’t appear to be in the VyOS CLI.

Another thing to mention is the version of suricata in the latest-and-greatest VyOS ISO file is 6.0.10, which 7.0.8 is out, and actually that’s what’s in OPNSense. I’ve noticed the alerts in 6.0.10 are a little noisy compared to what I experienced in 7.0.8 so I don’t know if that’s a version thing or what. I’m currently working on a method to update to 7.0.8 of suricata, and also enable “IPS mode” as that’s where I really want to be at. I think what OPNsense does for “IPS Mode” is use their own scripts to manipulate the .rules files themselves and change the first word which is the action. If this idea works then the final configuration would be this:

a) configure “native” suricata to run in IPS Mode
b) run a standard ‘/usr/bin/suricata-update’ minimally once a day
c) programmatically update the action in the ‘/var/lib/suricata/rules/suricata.rules’ file that ‘/usr/bin/suricata-update’ generates
d) reload the rules on-the-fly using the mechanism suricata provides

One final thing to point out is the downside to this approach. Once a VyOS upgrade is done, everything done outside of the CLI commands will be lost. I’m OK with that as I use redundant hardware to introduce new versions of VyOS, and script the whole config with the new version. It’s so easy to do that with VyOS!!

Hopefully this helps.

2 Likes

Thank you very much for the detailed explanation! I also want to run an IPS not “just” an IDP. I built up a small lab in eve-ng to test it out before I activate it in my home. Then I can use that lab later as well for testing new releases.

Maybe just one question. In this section:

set service suricata address-group http-servers group ‘home-net’
set service suricata address-group smtp-servers group ‘home-net’
set service suricata address-group sql-servers group ‘home-net’
set service suricata address-group dns-servers group ‘home-net’
set service suricata address-group telnet-servers group ‘home-net’
set service suricata address-group aim-servers group ‘external-net’
set service suricata address-group dc-servers group ‘home-net’

you have the “http-servers” group for example with direct host addresses and that’s how you link it to the group “home-net”?

Feel free to create a PR and extend the template file vyos-1x/data/templates/ids/suricata.j2 at current · vyos/vyos-1x · GitHub
It reads config as a dictionary and search defines in Jinja2.
Regarding suricata version we use the latest available for Debian bookworm package Debian -- Details of package suricata in bookworm

1 Like

Yep exactly. I’m still in the “testing” phase with this, and basically duplicated the majority of the vars: and port-groups: section of the suricata.yaml file that comes out-of-the-box. It’s probably a bit overkill, but it’s working.

/etc/suricata/suricata.yaml file:
vars:
HOME_NET: “[192.168.0.0/16,10.0.0.0/8,172.16.0.0/12]”
#HOME_NET: “[192.168.0.0/16]”
#HOME_NET: “[10.0.0.0/8]”
#HOME_NET: “[172.16.0.0/12]”
#HOME_NET: “any”

EXTERNAL_NET: "!$HOME_NET"
#EXTERNAL_NET: "any"

HTTP_SERVERS: "$HOME_NET"
SMTP_SERVERS: "$HOME_NET"
SQL_SERVERS: "$HOME_NET"
DNS_SERVERS: "$HOME_NET"
TELNET_SERVERS: "$HOME_NET"
AIM_SERVERS: "$EXTERNAL_NET"
DC_SERVERS: "$HOME_NET"
DNP3_SERVER: "$HOME_NET"
DNP3_CLIENT: "$HOME_NET"
MODBUS_CLIENT: "$HOME_NET"
MODBUS_SERVER: "$HOME_NET"
ENIP_CLIENT: "$HOME_NET"
ENIP_SERVER: "$HOME_NET"

port-groups:
HTTP_PORTS: “80”
SHELLCODE_PORTS: “!80”
ORACLE_PORTS: 1521
SSH_PORTS: 22
DNP3_PORTS: 20000
MODBUS_PORTS: 502
FILE_DATA_PORTS: “[$HTTP_PORTS,110,143]”
FTP_PORTS: 21
GENEVE_PORTS: 6081
VXLAN_PORTS: 4789
TEREDO_PORTS: 3544

/run/suricata/suricata.yaml file using ‘set service suricata’ commands:
vars:
HOME_NET: “[10.0.0.0/8]”
EXTERNAL_NET: “[!$HOME_NET]”
AIM_SERVERS: “[$EXTERNAL_NET]”
DC_SERVERS: “[$HOME_NET]”
DNS_SERVERS: “[$HOME_NET]”
HTTP_SERVERS: “[$HOME_NET]”
SMTP_SERVERS: “[$HOME_NET]”
SQL_SERVERS: “[$HOME_NET]”
TELNET_SERVERS: “[$HOME_NET]”

port-groups:
ALL_PORTS: “[1:65535]”
HTTP_PORTS: “[80]”
FILE_DATA_PORTS: “[110,143,$HTTP_PORTS]”
FTP_PORTS: “[21]”
GENEVE_PORTS: “[6081]”
ORACLE_PORTS: “[1521]”
SHELLCODE_PORTS: “[!80]”
SSH_PORTS: “[22]”
TEREDO_PORTS: “[3544]”
VXLAN_PORTS: “[4789]”

Thanks for the comments to both of you! I think I managed to make it work in IPS mode by changing from --af-packet mode to -d 0 in the file /etc/systemd/system/suricata.service.d/10-override.conf.

# ExecStart=/usr/bin/suricata -D --af-packet -c /run/suricata/suricata.yaml --pidfile /run/suricata/suricata.pid
ExecStart=/usr/bin/suricata -D -q 0 -c /run/suricata/suricata.yaml --pidfile /run/suricata/suricata.pid

Then I edited the firewall ruleset, to put the traffic I want to measure to queue 0.
After that I changed a couple of rules in the rulebase from action “alert” to “drop” for testing.

So far it seems to be working, however the mode cannot be changed directly over the suricata.yaml, but in the override.conf file.

I keep digging and testing, keep you posted on the results.

I’m still playing with Suricata here, and found a weird issue today. I’m not able to update suricata anymore, I got the following error:
12/3/2025 – 18:51:03 - – Fetching https://rules.emergingthreats.net/open/suricata-6.0.10/emerging.rules.tar.gz.
99% - 4784128/4809018
12/3/2025 – 18:51:34 - – Failed to copy file: The read operation timed out

Anyone has any idea?

Out of disk space?

How is your testing?

I think I found the problem based on this.

I use the Suricata in NFQUEUE mode already, when I do the update, the packets get queued as well, that causes the issue. I just turned on the queuing for the update traffic, it works fine.

I’m still working on a PR with the suricata.yaml config, however it might take some time. :slight_smile:

Thanks for the quick response!

I got a bit distracted on other things past few days, but I’m back to testing IPS mode with suricata.

I spent more time looking at how OPNsense implements IPS mode, and they are using the netmap mode in suricata which afaik is somewhat “out-of-the-box” for FreeBSD. The 2 Ethernet drivers that I’m using in my hardware support netmap, but I believe it has to be compiled into the drivers that come with VyOS.

Does anybody have any knowledge of adding netmap support to drivers in VyOS has been looked at or being considered?

@lmolgeim - can you share an example of your firewall ruleset to send to queue 0? I’ve also made changes to the service definition file to move from “–af-packet”, although I’m doing it a little different and testing a config that doesn’t use VyOS CLI for the suricata configuration until I get this all worked out. I’m planning on programmatically modifying the suricata.rules files to change a majority of the rules to “drop”, so end-to-end this is kind of outside what is done in the VyOS CLI.

Hi @taylorcb

I did the following:

  1. In /etc/systemd/system/suricata.service.d/10-override.conf file I made the following change:
# ExecStart=/usr/bin/suricata -D --af-packet -c /run/suricata/suricata.yaml --pidfile /run/suricata/suricata.pid
ExecStart=/usr/bin/suricata -D -q 0 -c /run/suricata/suricata.yaml --pidfile /run/suricata/suricata.pid

So that means, it will listen on queue 0 if I’m not mistaken.

  1. Then I updated the file /run/suricata/suricata.yaml. Search for “nfq:” and uncomment the mode: accept.
nfq:                  
  mode: accept                              
#  repeat-mark: 1    
#  repeat-mask: 1         
#  bypass-mark: 1         
#  bypass-mask: 1           
#  route-queue: 2    
#  batchcount: 20         
#  fail-open: yes

As I use log eve syslog not json, I had to add a few more lines here:

outputs:                                                                                                        
  # Extensible Event Format (nicknamed EVE) event log in JSON format                                            
  - eve-log:                                                                                                    
      enabled: yes                                                                                              
      level: info                                                                                               
      facility: local5                                                                                          
      filetype: syslog #regular|syslog|unix_dgram|unix_stream|redis                                             
      filename: eve.json                                                                                        
                                                                                                                
      types:                                                                                                    
        - alert:                                                                                                
            tagged-packets: yes                                                                                 
        - anomaly:                                                                                              
            enabled: yes

I think facility 7 is logged into terminal by default, so I simly set up “facility: local5” and "level: info ". I also modified syslog config, so it’s not stored locally, but sent to splunk only.

The next modification of this file is to uncomment and set up a treshold file at the bottom of the configuration:

# classification-file: /etc/suricata/classification.config                                                      
classification-file: /var/lib/suricata/rules/classification.config                                              
reference-config-file: /etc/suricata/reference.config                                                           
threshold-file: /etc/suricata/threshold.config

That’s needed for me to reduce the amount of false positives.

IMPORTANT NOTE: The file /run/suricata/suricata.yaml gets updated every time you commit something in the “service suricata” part of the config. So for now I use a separated file what I copy over when it’s needed. I’m planning to perpare a PR as previously recommended, but I didn’t have the time yet to do it + my testing is not finished.

When the files were updated, and suricata was running I did the following with the FW. Every traffic I want to monitor I put into the queue 0. Let’s say for example I have a rule to allow SSH traffic from DMZ to a specific host. Instead of " action accept" I use “action queue” and “queue 0”:

[edit firewall ipv4 name DMZ]
 rule 10 {
     action queue
     description "--- Allow SSH from specific DMZ hosts ---"
     destination {
         address 192.168.1.100
         port 22
     }
     protocol tcp
     queue 0
     source {
         group {
             network-group SSH-from-DMZ-to-TRUST
         }
     }
 }

Then suricata will start working on the queued traffic.

What I’m working on now: I want to modify some rules, to do a drop instead of alert, and also create new rules on my own, and put them into a file, what will override the action of a current rule. For example I noticed someone scans my server, I got many alerts, but no drops for that rule:
alert tcp any ![22,25,53,80,88,143,443,445,465,587,853,993,1194,8080,51820] -> any ![22,25,53,80,88,143,443,445,465,587,853,993,1194,8080,51820] (msg:"POSSBL PORT SCAN (NMAP -sA)"; flags:A; flow:stateless; window:1024; threshold:type threshold, track by_dst, count 20, seconds 70; classtype:attempted-recon; sid:3400004; priority:2; rev:5;)

I’m thinking to reduce the threshold of that rule over the previously allowed /etc/suricata/threshold.config file.
Or better I’d like to set up a static rule what drops that kind of traffic immediately.
I’m thinking about 2 possible ways:

  1. Add a local.rules file to the default rules folder (/etc/suricata/rules/local.rules).
    I tried that one first, and did an “update suricata” VYOS command. That reads in all default suricata rules from /etc/suricata/rules folder, but for some reason it didn’t read my file, only the following:
17/3/2025 -- 12:25:36 - <Info> -- Remote checksum has not changed. Not fetching.
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/app-layer-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/decoder-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/dhcp-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/dnp3-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/dns-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/files.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/http-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/ipsec-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/kerberos-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/modbus-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/nfs-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/ntp-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/smb-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/smtp-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/stream-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Loading distribution rule file /etc/suricata/rules/tls-events.rules
17/3/2025 -- 12:25:36 - <Info> -- Ignoring file rules/emerging-deleted.rules
  1. Add a new rules file (eg. /var/lib/suricata/rules/local.rules ) to the suricata.yaml file, and put it on the top so the traffic is being blocked. With that I’m not finished yet, I need a bit more time to test it. But what I see for now that the rule is there in both files, one is dropping the other is alerting, not sure which one will be used first.

I started testing how to implement my changes and make a PR. However I’m not so experienced yet on that field, I might need some help if you have time to support me a bit.
Let’s just take one example for the sake of simplicity. In that case I want add “threshold-file:” over my configuration to suricata.
First of all I update the “suricata.j2” file, with this:

{% if suricata.threshold is vyos_defined %}
threshold-file: "{{ suricata.threshold }}"
{% endif %}

Then I try to create the necessary “node.def” files in the proper structure. I created the folder “/opt/vyatta/share/vyatta-cfg/templates/service/suricata/threshold-file” then inside the “node.def” file.
The file looks like that:

type: txt
help: Threshold file (default: none)
val_help: filename; File name of suricata threshold file. Can be used to update specific rules. 
val_help: /path; Absolute file path

I see then the config option becomes available.

But then I’m not able to commit it, it stuck in commit forever.

Do you maybe have some kind of docu how to start contributing there? I’m seriously interested in the suricata part, I’d have many other options to make config easier and more straightforward.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.