Mikrotik RouterOS WAN traffic sniff Suricata IDS
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:
- disabling
fasttrack connections
in RouterOS firewall’sfilter table forward chain
. - Setting up a few firewall rules in RouterOS’s
mangle table
to 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
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=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 [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.