Skip to main content
RunBook Academy

OPNsenseXXXV · Performance and State TableIDS performance impact

IDS performance impact — what Suricata costs and how to keep it from breaking the firewall

Advanced⏱ ~15 minsuricatasysctlvmstattopprometheus

What you'll learn

  • Describe the Suricata modes on OPNsense and their CPU cost
  • Identify the ruleset factors that determine IDS performance
  • Tune Suricata for the deployment — alert-only, IPS, hyperscan, threading
  • Recognise the symptoms of IDS saturation — packet drops, alert backlog, latency
  • Distinguish IDS-saturation symptoms from firewall-rule or state-table symptoms

Prerequisites

Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14

Not yet marked complete on this device.

Suricata IDS on OPNsense is the most expensive optional feature. Every packet that traverses the firewall is mirrored to Suricata; Suricata runs a ruleset of tens of thousands of signatures against each packet; matched packets generate alerts or trigger drop actions. The cost can dominate the firewall’s CPU budget, drop packets at high traffic rates, and produce a queue of unprocessed packets that grows until the firewall itself becomes the bottleneck.

This lesson covers the Suricata modes on OPNsense, the ruleset factors that determine performance, the threading model, the symptoms of saturation, and the discipline of running IDS without breaking throughput.

The Suricata modes

OPNsense runs Suricata in three modes:

  • IDS mode (alert only). Suricata receives a copy of each packet via netmap, evaluates rules, and logs alerts. The original packet is forwarded by PF normally. The firewall’s throughput is unaffected — but every packet costs Suricata CPU.
  • IPS mode (inline). Suricata sits inline in the packet path. PF sends packets to Suricata via netmap; Suricata evaluates rules and decides whether to forward or drop. The firewall’s throughput is capped by Suricata’s packet-rate.
  • Legacy netmap IDS. Older configuration mode that uses netmap for packet capture. Largely superseded by the modern IPS/IDS modes.

The most common production setup is IDS mode — alert on suspicious traffic without affecting throughput. The trade-off is that IDS alerts are advisory; the firewall does not block based on them. For blocking traffic, IPS mode is required — but at the cost of throughput.

The ruleset factors

The Suricata ruleset is the dominant performance variable. A deployment with 1,000 enabled rules performs dramatically differently from one with 50,000 rules. The factors:

  • Number of rules. Every rule is evaluated per packet (with some short-circuiting when earlier rules match). A rule count of 30,000 to 50,000 is typical for the ETOpen ruleset.
  • Rule complexity. Rules with multiple patterns, multiple flags, or content modifiers (e.g. http_uri, tls_sni) cost more per evaluation than simple IP/port matches.
  • Flowbits. Rules that set or check flowbits create dependencies between rules. A rule that sets a flowbit that 50 other rules check forces those 50 rules to evaluate even if the flowbit is not set.
  • Preprocessor activity. Suricata’s protocol parsers (HTTP, TLS, DNS, SMB, etc.) reconstruct streams and may buffer data. High protocol diversity costs more.

The discipline is to start with a small, focused ruleset and add rules only when the deployment’s threat model requires them. The ETOpen ruleset is a good baseline; the ETPro ruleset is larger and more aggressive; the Proofpoint Emerging Threats ruleset is similar to ETOpen. Operators should review what they enable.

The threading model

Suricata uses multiple threads:

  • Management thread. Coordinates configuration, counters.
  • Packet acquisition threads. Read packets from netmap (one per interface).
  • Worker threads. Run the detection engine — evaluate rules against each packet.
  • Flow worker threads. Track flow state across packets.
  • Output threads. Write alerts, logs, and stats to disk.

The number of worker threads is configured in suricata.yaml as threading.detect-thread-ratio. The default is typically 1.5 × the number of CPU cores; the operator can tune this up or down.

Read-only / Safesuricata build info
$ suricata --build-info | grep -E 'Threads|Detect|Netmap|Hyperscan'
Threads:        yes
Detect thread ratio: 1.5
Hyperscan:      yes
Netmap:         yes
NFQueue:        yes

Illustrative output

The discipline:

  • Confirm Hyperscan is built in. The --build-info output should show Hyperscan: yes. Without Hyperscan, pattern matching is 5-10x slower.
  • Tune detect-thread-ratio for the deployment. A ratio of 1.5 uses 1.5 cores’ worth of worker threads; on a 4-core deployment, that’s 6 worker threads. Tune up for higher packet rates; tune down for lower memory.
  • Pin threads to cores with cpuset to avoid contention with PF and other daemons.

Symptoms of IDS saturation

The signatures of Suricata saturation:

  • Packet drops reported by Suricata. The capture.kernel_drops counter in Suricata’s stats is non-zero.
  • Alert backlog. The alert_queue is full; alerts are dropped before being written.
  • High CPU on Suricata threads. The worker threads are at 100% WCPU in top.
  • Latency in PF forwarding. In IPS mode, packets queue while Suricata processes; latency rises.
  • Lower-than-expected throughput. In IPS mode, the firewall’s pps is well below the expected rate.

The capture.kernel_drops counter is the canary:

Read-only / Safesuricata stats
$ curl -s http://127.0.0.1:9911/ 2>/dev/null | grep -E 'capture|kernel_drop|alert_queue' | head -10
"capture.kernel_packets": 12345678,
"capture.kernel_drops": 12345,
"capture.kernel_ifdrops": 0,
"alert_queue.maxsize": 65536,
"alert_queue.current": 1234,
"alert_queue.dropped": 0

Illustrative output

Tuning for performance

The levers:

  • Reduce the ruleset. Disable unused rules. The ETOpen ruleset has categories; the operator should disable categories irrelevant to the deployment.
  • Tune detect-thread-ratio. More threads = more parallelism but more memory.
  • Use hyperscan. Confirm it is built in. Some custom rules use PCRE; hyperscan does not accelerate PCRE — convert to hyperscan-compatible patterns where possible.
  • Reduce logging. Every alert is written to disk; verbose logging on a busy network saturates disk I/O. Tune to log only what the operator will read.
  • Use AF_PACKET or netmap efficiently. In OPNsense, netmap is the default; confirm the ring sizes are tuned for the packet rate.
  • Tune flow timeouts. Short flow timeouts reduce memory pressure; long timeouts increase state.

Distinguishing from other symptoms

The operator must distinguish IDS saturation from other saturation symptoms:

SymptomCause
Suricata kernel_drops risingIDS saturation
Suricata CPU at 100%, PF CPU moderateIDS saturation
PF CPU at 100%, Suricata moderatePacket-rate saturation on PF
All CPU at moderate levels, bps lowLink saturation or upstream issue
All CPU moderate, latency highState table exhaustion or DNS issue

The cross-reference between Suricata stats and PF performance is the key. A deployment with rising Suricata drops and steady PF performance is IDS-bound; one with rising PF idrops and steady Suricata is PF-bound.

The deployment pattern

A typical production deployment:

  1. Start with a small ruleset. Enable ETOpen categories relevant to the deployment (e.g. emerging-dos, emerging-web-server, emerging-malware). Disable the rest.
  2. Run in IDS mode initially. Confirm throughput is acceptable before switching to IPS.
  3. Monitor the canary metrics. Graph capture.kernel_drops, alert_queue.dropped, and Suricata CPU.
  4. Tune as the workload grows. Add rules when the threat model requires them; tune threading when packet rate grows.
  5. Switch to IPS only when blocking is required. Have a rollback plan in case the IPS introduces problems.

Summary

  • Suricata IDS runs as a parallel process receiving mirrored packets via netmap; its CPU cost is the dominant performance variable.
  • The ruleset (size, complexity, PCRE use) determines per-packet cost.
  • Hyperscan accelerates pattern matching 5-10x; confirm it is built in.
  • The canary metrics are capture.kernel_drops and alert_queue.dropped — non-zero indicates saturation.
  • IDS mode is the default because a Suricata crash in IDS mode drops alerts only; a crash in IPS mode drops the entire firewall.
  • Tune the ruleset, threading, and logging; measure with the actual workload.

Knowledge check · 4 questions

  1. Q1. Suricata is running in IDS mode on an OPNsense firewall. The capture.kernel_drops counter is rising. PF CPU is moderate. What is the most likely diagnosis?

  2. Q2. Running Suricata in IPS mode is safer than IDS mode because it blocks malicious traffic inline.

  3. Q3. Which of the following are tuning levers for Suricata performance? Select all that apply.

  4. Q4. A signature uses PCRE with backreferences. Suricata is built with Hyperscan. What happens?

Passing score: 75%. Answers are checked in this browser.