Preface: this is the poor’s man way of hooking up Suricata IDS to Mikrotik any router.
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:

  1. disabling fasttrack connections in RouterOS firewall’s filter table forward chain.
  2. Setting up a few firewall rules in RouterOS’s mangle table to sniff and redirect traffic to the suricata host.
  3. 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

Notice the ExecStart:

$ 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 /etc/suricata/suricata.yaml file.

.:. RouterOS configuration

First thing required is to disable fasttrack connections for establisted and related connections.
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 mangle rules:

$ ssh user@mikrotik

/ip/firewall/mangle/add chain=forward action=sniff-tzsp sniff-target=[[suricata_host]] sniff-target-port=[suricata_port] in-interface=ether1 log=no log-prefix=""
/ip/firewall/mangle/add chain=forward 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 [suricata_host] on [suricata_port].
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 /var/log/suricata.
fast.log is what will contain the alerts, suricata.log is useful to check that everything is working as expected.