Your router tells you a connection happened. Suricata IDS tells you what was in it. It is the piece most home labs skip, because getting a copy of the traffic feels harder than it is, and because everyone assumes it needs enterprise hardware. Neither is true.
What Suricata IDS gives you that a firewall does not
Suricata reads packets off an interface, reassembles flows, identifies the protocol regardless of port, and matches the decoded content against signatures. Two outputs matter. The first is alerts: a signature matched, here is the flow. The second, and the one people undervalue, is protocol metadata written to eve.json for every connection whether it alerted or not.
- Every DNS query and answer on the network
- TLS SNI, certificate subject and JA3 hashes, so you see the destination even when the payload is encrypted
- HTTP host, URI and user agent
- File hashes for anything transferred in the clear
That metadata is the hunting surface. Half the useful questions I ask of a home network — which device is beaconing to a domain registered last week, what is talking to a hosting provider at 3am — are answered from the flow records, not the alerts.
Installing Suricata and pointing it at real traffic
sudo add-apt-repository ppa:oisf/suricata-stable
sudo apt update && sudo apt install suricata jq
sudo systemctl stop suricata
The install is trivial. The real problem is that a switch only sends your monitoring box its own traffic. You have three options, in the order I would try them:
- Run Suricata on the router itself if it is OPNsense, pfSense or a Linux box you built. Simplest, zero extra hardware.
- A managed switch with port mirroring, sending the uplink port to a spare NIC on the sensor.
- A passive network tap between router and switch. Best fidelity, costs money, cannot be misconfigured into dropping traffic.
The minimum config
Two edits in /etc/suricata/suricata.yaml do almost all the work. Set your internal ranges, or every rule that keys on direction is meaningless, and bind AF_PACKET to the monitoring interface.
vars:
address-groups:
HOME_NET: "[192.168.1.0/24,192.168.30.0/24]"
EXTERNAL_NET: "!$HOME_NET"
af-packet:
- interface: enp3s0
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
use-mmap: yes
sudo suricata-update enable-source et/open
sudo suricata-update
sudo suricata -T -c /etc/suricata/suricata.yaml -i enp3s0
sudo systemctl enable --now suricata
The -T test run is not optional. A single malformed rule stops the service starting, and the failure message is far clearer from a test run than from journald.
A rule firing, with real output
There is a standard safe test. From a host behind the sensor, fetch the ETS test file and watch the alert appear:
curl -s http://testmynids.org/uid/index.html
sudo tail -f /var/log/suricata/eve.json | jq -c 'select(.event_type=="alert")'
{
"timestamp": "2026-09-14T21:22:07.441283+0100",
"src_ip": "192.168.1.42",
"dest_ip": "82.165.177.154",
"dest_port": 80,
"proto": "TCP",
"alert": {
"signature_id": 2100498,
"rev": 7,
"signature": "GPL ATTACK_RESPONSE id check returned root",
"category": "Potentially Bad Traffic",
"severity": 2
},
"http": { "hostname": "testmynids.org", "url": "/uid/index.html" }
}
Writing your own is straightforward once you have seen one fire. Drop this in /var/lib/suricata/rules/local.rules and add that file to rule-files in the YAML — it flags any device quietly bypassing your DNS server:
alert dns $HOME_NET any -> !192.168.1.1 any (msg:"LOCAL DNS bypassing internal resolver"; \
dns.query; sid:1000001; rev:1;)
When an alert is interesting, pull the flow and open it properly. Suricata can write a matching PCAP, and from there it is a Wireshark packet analysis job — the same skill, used to confirm a detection rather than to build an exploit.
Cutting the false positives
ET Open ships tens of thousands of rules and a good number of them will never be relevant to a house. Two files handle this. Disable whole categories in /etc/suricata/disable.conf, then re-run suricata-update:
# /etc/suricata/disable.conf
group:emerging-policy.rules
2013028
re:SURICATA STREAM
For a signature that is right in general but wrong for one host, suppress per-source in /etc/suricata/threshold.config rather than disabling it globally:
suppress gen_id 1, sig_id 2027865, track by_src, ip 192.168.1.10
threshold gen_id 1, sig_id 2100498, type limit, track by_src, count 1, seconds 300
Honest hardware requirements
- Two cores and 4 GB of RAM comfortably handle a 200–500 Mbit connection with the full ET Open set.
- Symmetric gigabit is where you start needing four fast cores and to care about
capture.kernel_dropsinstats.log. Drops mean you are lying to yourself about coverage. - A Pi 4 works on a slower line, but put
eve.jsonon an SSD, never the SD card. - Disk is the real cost. Full flow logging on a busy network is gigabytes a day; trim
eve-logtypes to alert, dns, tls, http and set up logrotate on day one.
My recommendation
Run it on the router if you can, in IDS mode rather than inline IPS to begin with. A dropped packet from a bad rule is a support call from the family; a missed alert is just an alert. Give it a fortnight of suppression tuning, and keep the flow metadata even after the alerts go quiet — that is the part you will still be using a year later.

Leave a Reply
You must be logged in to post a comment.