Suricata IDS/IPS: Network Threat Detection for Your Homelab
Most homelab security setups stop at a firewall. Rules block known-bad traffic, everything else passes through. But a firewall doesn't tell you what's happening on your network — it only enforces rules you wrote in advance.
Photo by Brian McGowan on Unsplash
Suricata adds a different layer: it watches all network traffic and compares it against a ruleset of known threat patterns. It can detect port scans, malware beaconing, exploitation attempts, and protocol anomalies — and optionally block them before they reach their target.
IDS vs IPS Mode
Suricata runs in two modes:
- IDS (Intrusion Detection System): Passive monitoring. Reads a copy of traffic (via port mirroring or AF_PACKET) and generates alerts. No packets are blocked. Zero impact on network throughput.
- IPS (Intrusion Prevention System): Inline mode. Traffic passes through Suricata before reaching the destination. Can drop malicious packets. Adds some latency; hardware matters.
For most homelabs, IDS mode is the right starting point. You get visibility without the risk of blocking legitimate traffic.
Installation on Debian/Ubuntu
# Add Suricata repository
add-apt-repository ppa:oisf/suricata-stable
apt update
apt install -y suricata suricata-update
# Verify installation
suricata --build-info
Configure the network interface in /etc/suricata/suricata.yaml:
af-packet:
- interface: eth0
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
use-mmap: yes
tpacket-v3: yes
Replace eth0 with the interface you want to monitor. If you're using a port mirror, point Suricata at the mirror interface.
Running with Docker
For Proxmox or a dedicated VM:
services:
suricata:
image: jasonish/suricata:latest
container_name: suricata
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
- SYS_NICE
volumes:
- ./suricata:/etc/suricata
- suricata_logs:/var/log/suricata
- suricata_run:/var/run/suricata
command: -i eth0
restart: unless-stopped
volumes:
suricata_logs:
suricata_run:
network_mode: host is required for Suricata to capture raw traffic. The NET_RAW and NET_ADMIN capabilities are needed for packet capture.
Like what you're reading? Subscribe to HomeLab Starter — free weekly guides in your inbox.
Rule Management with suricata-update
Suricata doesn't ship rules — you pull them separately using suricata-update:
# Update rules from default sources (ET Open)
suricata-update
# Add additional free rulesets
suricata-update add-source ptresearch/attackdetection
suricata-update add-source sslbl/ssl-fp-blacklist
suricata-update add-source etnetera/aggressive
# Update all sources
suricata-update --reload-command "kill -USR2 $(cat /var/run/suricata.pid)"
The Emerging Threats (ET) Open ruleset is free and covers the most common threats — lateral movement, malware C2, scanning tools, exploit kits. It's a good starting point without subscription costs.
Set up a daily cron job:
# /etc/cron.daily/suricata-update
#!/bin/bash
suricata-update
kill -USR2 $(cat /var/run/suricata.pid) 2>/dev/null
EVE JSON Logging
Suricata's most useful output format is EVE JSON — every alert, flow, DNS query, HTTP request, and TLS handshake logged as structured JSON. This integrates with every modern log analysis tool.
Configure in suricata.yaml:
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: /var/log/suricata/eve.json
types:
- alert
- http:
extended: yes
- dns
- tls:
extended: yes
- flow
- stats:
interval: 10
Sample alert output:
{
"timestamp": "2026-03-04T04:15:22.123456+0000",
"event_type": "alert",
"src_ip": "192.168.1.105",
"src_port": 54321,
"dest_ip": "10.0.0.5",
"dest_port": 445,
"proto": "TCP",
"alert": {
"action": "allowed",
"gid": 1,
"signature_id": 2027893,
"rev": 1,
"signature": "ET SCAN Nmap Scripting Engine User-Agent Detected (Nmap Scripting Engine)",
"category": "Network Scan",
"severity": 2
}
}
Integration with Grafana and Loki
Pipe EVE JSON into Loki for search and Grafana for dashboards:
# Promtail config to scrape Suricata logs
scrape_configs:
- job_name: suricata
static_configs:
- targets:
- localhost
labels:
job: suricata
__path__: /var/log/suricata/eve.json
pipeline_stages:
- json:
expressions:
event_type: event_type
src_ip: src_ip
category: alert.category
- labels:
event_type:
category:
In Grafana, query Loki:
{job="suricata", event_type="alert"} | json | category != ""
Build panels showing:
- Alert rate over time by category
- Top source IPs generating alerts
- Most triggered signatures
- DNS queries by type
Tuning: Reducing False Positives
Out of the box, you'll see alerts from normal traffic — Windows Update, browser OCSP checks, cloud sync tools. Suppress known-good traffic:
# suricata.yaml — suppress list
suppress:
- gen-id: 1
sig-id: 2210052
track: by_src
ip: 192.168.1.0/24
Or use threshold settings:
# threshold.conf
suppress gen_id 1, sig_id 2210052, track by_src, ip 192.168.1.0/24
threshold gen_id 1, sig_id 2220000, type threshold, track by_src, count 5, seconds 60
The goal is to suppress high-volume low-value signatures while keeping the alerts you actually want to see.
IPS Mode with NFQ
To switch to inline IPS mode using netfilter queue:
# Route traffic through NFQ
iptables -I FORWARD -j NFQUEUE --queue-bypass
iptables -I INPUT -j NFQUEUE --queue-bypass
iptables -I OUTPUT -j NFQUEUE --queue-bypass
Start Suricata in NFQ mode:
suricata -c /etc/suricata/suricata.yaml -q 0
In IPS mode, Suricata rules with drop action actively block matching traffic. Start with all rules in alert mode, then selectively move high-confidence signatures to drop after validating they don't cause false positives.
Suricata on OPNsense
If you run OPNsense as your firewall, Suricata is available as a built-in plugin:
- Plugins → os-suricata — install from the plugin catalog
- Configure under Services → Intrusion Detection
- Enable EVE logging and select rulesets (Emerging Threats included)
- Choose IDS or IPS mode per interface
OPNsense's integration handles the interface binding, rule management, and log rotation automatically. This is the lowest-friction path if you're already using OPNsense.
