The Unifi Security Gateway has a nifty threat management module which uses Suricata for IDS/IPS - however, when enabling this you will drop down to 85Mbps on your WAN throughput as it needs to use a lot of resources to inspect the traffic and it cannot off-load to hardware modules.

This is a bit of a pain for me since I have 300Mbps and I'd like to keep that. Ideally, I'd upgrade to the Unifi Dream Machine Pro (since my network is mostly Unifi devices) which can handle it just fine, but this is a much larger device and has a higher price tag.

So, as the theme of my last few posts have been securing my home network I'd like to have something like this without sacrificing that much bandwidth.

A thought occurred: What if I can off-load the processing to a Raspberry Pi 4 with a good amount of RAM to at least get some functionality?

The Unifi switches I use support port mirroring and that sounds like a step in the right direction - I can let the USG happily go about its work while the Raspberry Pi is cc'd on all the traffic.

This won't let me do effective Intrusion Prevention, but I can do some Intrusion Detection at least. And I will only see the traffic that passes beyond the USG - not all that it blocks, but it's a start :)

A diagram

Configuring the Raspberry Pi Wi-Fi

Before you enable port mirroring, make sure the RPi has Wi-Fi enabled as you won't be able to connect to it on the LAN port once mirroring is enabled.

If you are using Raspbian, the simplest way is sudo raspi-config and go to System Options -> S1 Wireless LAN.

Installing Suricata

If  you install Suricata with the default package repositories, you will get version 4.x only - we want to get the good stuff so we add the official sources.

As root do:

echo "deb buster-backports main contrib non-free" > \
apt-get update
apt-get install suricata suricata-update -t buster-backports

This will install a barebones Suricata with outdated rules. Luckily, we also installed suricata-update which will handle that for us.

Run sudo suricata-update -D /etc/suricata to get the latest rules and add a crontab to update it regularly so you are kept up to speed on emerging threats.

You are now pretty much ready to go - except you will get a lot of noise and false positives.

Tweak your rules and don't go insane

By creating /etc/suricata/disable.conf we can decide which rules we don't want to listen to by adding signature id of the rule on a new line. This is a ongoing process - you will have to keep a keen eye on what alerts you get and which ones are just noise and update this file.

A Suricata rule can look like this:

alert pkthdr any any -> any any (msg:"SURICATA TCP invalid option length"; decode-event:tcp.invalid_optlen; classtype:protocol-command-decode; sid:2200035; rev:2;)

The id you want to use when disabling (or enabling - use the /etc/suricata/enable.conf file for that) is denoted by the sid key.

Once you've updated the file, run the suricata-update tool again.

Monitoring for alerts

Update: To enable HTTP monitoring with this setup, you might need to disable vlan-tracking in suricata.yaml:
    use-for-tracking: false

By default, all Suricata logs end up in /var/log/suricata and you can get a quick overview of the alerts by looking in the fast.log file which can look like this:

11/11/2020-06:00:18.087298  [**] [1:2200036:2] SURICATA TCP option invalid length [**] [Classification: Generic Protocol Command Decode] [Priority: 3] {TCP} 717.257.14.122:443 ->
11/11/2020-06:01:06.405258  [**] [1:2210045:2] SURICATA STREAM Packet with invalid ack [**] [Classification: Generic Protocol Command Decode] [Priority: 3] {TCP} -> 256.652.166.12:443

For more detailed data - look in the eve.json file which contains basically everything you want.

To easier filter on alerts - try this: tail -f /var/log/suricata/eve.json | jq 'select(.event_type=="alert")'

The same alert as in fast.log will then have a lot more data:

  "timestamp": "2020-11-10T14:26:39.407218+0000",
  "flow_id": 1633941440102616,
  "in_iface": "eth0",
  "event_type": "alert",
  "vlan": [
  "src_ip": "",
  "src_port": 63122,
  "dest_ip": "273.326.6.3",
  "dest_port": 443,
  "proto": "TCP",
  "flow": {
    "pkts_toserver": 11,
    "pkts_toclient": 0,
    "bytes_toserver": 1204,
    "bytes_toclient": 0,
    "start": "2020-11-10T14:26:39.327896+0000"
  "payload": "",
  "stream": 0,
  "alert": {
    "action": "allowed",
    "gid": 1,
    "signature_id": 2210046,
    "rev": 2,
    "signature": "SURICATA STREAM SHUTDOWN RST invalid ack",
    "category": "Generic Protocol Command Decode",
    "severity": 3

Because I already have a setup which sends syslog to Azure Sentinel, I want to send all the logs to syslog instead of a file.

You can do that by editing /etc/suricata/suricata.yaml and find the outputs section which contains eve-log and set it to something similar to below.

  # Extensible Event Format (nicknamed EVE) event log in JSON format
  - eve-log:
      enabled: yes
      filetype: syslog #regular|syslog|unix_dgram|unix_stream|redis
      #filename: eve.json
      #prefix: "@cee: " # prefix to prepend to each log entry
      # the following are valid when type: syslog above
      identity: "suricata"
      facility: local5
      level:  Alert ## possible levels: Emergency, Alert, Critical,
                   ## Error, Warning, Notice, Info, Debug

More information

Suricata has alot of configuration options - hit up the docs to see more.

Setting up port mirroring on the Unifi Switch

It is now time to set up port mirroring so that Suricata can process the traffic.

Using the Unifi Controller software, this is quite straight forward.

Go to "Devices" and click on the switch your USG is connected to.

The Raspberry Pi will need to be connected to the same switch.

Now, click "Edit" on the port your RPi is connected to.

Expand the "Profile Overrides" section and select the "Mirroring" operation. Then, in "Mirroring Port", set the port number of your USG and hit the ol' "Apply".

You won't be able to connect to your RPi on this port any longer, so make sure your Wi-Fi-connection is up.

In conclusion

Now you should have the logs and alerts in place - its up to you how to make use of it :)

For my part, I can now do fun alerting in Azure Sentinel:

You might find some inspiration in the other posts related to this: