Preface: this is the poor’s man way of hooking up Suricata IDS to
Better ways would be using port mirroring or putting Suricata host directly in front of the router.
My goal was to have all network traffic coming and going from internet
mirrored into the suricata virtual machine.
Network schema is the following:
(internet) <-> routeros <-> debian_hypervisor <-> (linux bridge) <-> Suricata_VM
There are few ways of doing this, the one which is in my opinion the lesser evil involves:
fasttrack connectionsin RouterOS firewall’s
filter table forward chain.
- Setting up a few firewall rules in RouterOS’s
mangle tableto sniff and redirect traffic to the suricata host.
- Instruct Suricata to digest traffic coming from the router.
.:. Suricata system setup
I had to compile Suricata from source, the version included in my OS’s
repositories has a weird bug that causes it to use a lot of CPU even while
doing virtually nothing.
Compiling is easy, so no big deal:
$ apt install make gcc pkg-config libjansson libpcap libpcre2 libmagic zlib libyaml libgeoip liblua5.1 libhiredis libevent libpcre3-dev libyaml-dev libjansson-dev libpcap-dev libcap-ng-dev libnspr4-dev libnss3-dev libmagic-devi libmaxminddb-devl iblz4-devi rustc cargo zlib1g-dev wireshark-commons $ wget https://www.openinfosecfoundation.org/download/suricata-6.0.9.tar.gz $ tar -xvf suricata-6.0.9.tar.gz $ cd suricata-6.0.9 $ ./configure --enable-geoip $ make -j8 $ make install
Create a user for suricata, add the required privs and setup the systemd service file:
$ dpkg-reconfigure wireshark-common $ useradd -m suricata $ usermod -a -G wireshark suricata $ mkdir /var/run/suricata $ chown suricata: /var/run/suricata $ visudo ... suricata ALL=(ALL) NOPASSWD: /usr/local/bin/suricata -r /dev/stdin -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata/suricata.pid suricata ALL=(ALL) NOPASSWD: /usr/bin/mkdir -p /var/run/suricata suricata ALL=(ALL) NOPASSWD: /usr/bin/rm -f /var/run/suricata/suricata.pid ... $ cat /etc/systemd/system/suricata.service ... [Unit] Description=Suricata IDS/IDP daemon - mk After=network.target network-online.target Requires=network-online.target Documentation=man:suricata(8) man:suricatasc(8) Documentation=https://suricata-ids.org/docs/ [Service] User=suricata Group=suricata Type=forking #Environment=LD_PRELOAD=/usr/lib/libtcmalloc_minimal.so.4 PIDFile=/var/run/suricata/suricata.pid ExecStart=/usr/bin/sh -c '/opt/scripts/suricata.sh &' [Install] WantedBy=multi-user.target
$ cat /opt/scripts/suricata.sh ... #!/bin/bash sudo mkdir -p /var/run/suricata sudo rm -f /var/run/suricata/suricata.pid cd /var/log/suricata /usr/bin/tshark -i any -f "udp port 37008" -n -d udp.port==37008,tzsp -w - | sudo /usr/local/bin/suricata -r /dev/stdin -c /etc/suricata/suricata.yaml --pidfile /var/run/suricata/suricata.pid
What it does is have wireshark decode the TZSP stream coming from the router on port UDP 37008 and pipe it into suricata’s process standard input; from there Suricata takes over and starts analyzing the traffic.
NOTE: it might be required to tweak Suricata configuration, but this is beside
the point of this blogpost; see
.:. RouterOS configuration
First thing required is to disable
fasttrack connections for establisted and
This is required because fasttracked connections take a privileged path which bypasses quite a few things, mangle firewall rules included.
Note that disabling
fasttrack connections means that CPU has to do quite a
bit of added work; before proceeding I would definitely check CPU’s load
average while running iperf from-the-internet and locally in LAN.
$ ssh user@mikrotik # Identify the fasttrack rule, number 9 in my case [user@mikrotik] > /ip/firewall/filter/print ... 9 X ;;; defconf: fasttrack chain=forward action=fasttrack-connection hw-offload=yes connection-state=established,related log=no log-prefix="" ... # Disable the rule [user@mikrotik] > /ip/firewall/filter/disable numbers=9 # Reboot the router to have the setting applied [user@mikrotik] > /system/reboot
Once the router is rebooted, ssh into it again and create the
$ ssh user@mikrotik /ip/firewall/mangle/add chain=postrouting action=sniff-tzsp sniff-target=[[suricata_host]] sniff-target-port=[suricata_port] in-interface=ether1 log=no log-prefix="" /ip/firewall/mangle/add chain=prerouting action=sniff-tzsp sniff-target=[[suricata_host]] sniff-target-port=[suricata_port] out-interface=ether1 log=no log-prefix=""
What the rules do is forward traffic going in an out of the WAN interface
(ether1 in my case) to
To check that traffic is actally flowing use tcpdump or wireshark:
tcpdump -nni any port [suricata_port]
.:. How do I check if Suricata found something?
Setup a cronjob to update the suricata rules every once in a while (run it manually the first time):
$ cat /etc/cron.d/suricata_rules ... 4 */4 * * * root /usr/local/bin/suricata-update -o /etc/suricata/rules >> /var/log/suricata/rules_update.log 2>&1
Let it do its thing for a few hours, then go have a look at the content of
fast.log is what will contain the alerts,
suricata.log is useful to check
that everything is working as expected.