Skip to content

Instantly share code, notes, and snippets.

@lnxd
Last active March 23, 2026 02:34
Show Gist options
  • Select an option

  • Save lnxd/45a034c10f5a22bacace089cf4cc4af6 to your computer and use it in GitHub Desktop.

Select an option

Save lnxd/45a034c10f5a22bacace089cf4cc4af6 to your computer and use it in GitHub Desktop.
UniFi Gateway IDS/IPS Memory Profiling results

UniFi Gateway IDS/IPS Memory Profiling

Overview

Comparative analysis of Suricata IDS/IPS memory consumption across two UniFi gateway models tested approximately two weeks apart. Focuses on per‑category memory impact, cgroup limits, fail‑closed behaviour on OOM, and the observed link between scheduled speed tests and memory spikes.

  • Per‑category memory impact for Emerging Threats rulesets
  • UDM‑SE (4 GB) vs UCG‑Ultra (3 GB) comparison
  • Production outages linked to auto speed‑test spikes
  • Cgroup resource limits and OOM behaviour
  • Methodology: 60–90 s stabilisation after each restart

Why?

Observed three separate Unifi gateways suffer from IPS crashes leading to network failure until hardware restart.

tl;dr

Under traffic spikes (e.g., speed tests), if the full IDS/IPS ruleset is enabled, the cgroup memory limit can be hit, causing the kernel to OOM-kill Suricata. Traffic is then dropped until the device is manually rebooted.

Test Configurations

UCG‑Ultra (Test 1)

  • Model: UniFi Cloud Gateway Ultra
  • RAM: 3 GB
  • Test Date: 6 Oct 2025
  • Firmware: 4.4.3
  • Suricata Version: 6.0.12

UDM‑SE (Test 2)

  • Model: UniFi Dream Machine Special Edition
  • RAM: 4 GB (3.9 GB usable)
  • Test Date: 17 Oct 2025
  • Firmware: 4.4.3
  • Suricata Version: 6.0.12

Critical Findings

Suricata Restart Behaviour

  • On 4.4.3 in my testing, every category change triggered a full Suricata restart (not a hot rule reload).
  • Old PID terminates, new PID spawns.
  • ~60–90 s required for initialisation and memory stabilisation; 30 s waits were insufficient for accurate measurements.

Memory Impact by Category

Category UDM‑SE delta UDM‑SE Total UCG‑Ultra delta Change
Baseline (empty) 52 MB
emerging‑malware +312 MB 364 MB +203.7 MB +108.3 MB
emerging‑webapps +98 MB 150 MB +94.0 MB +4.0 MB
emerging‑exploit +48 MB 100 MB +42.9 MB +5.1 MB
emerging‑mobile +27 MB 79 MB +21.1 MB +5.9 MB
emerging‑attackresponse +16 MB 68 MB +14.0 MB +2.0 MB
emerging‑webclient +19 MB 71 MB +13.6 MB +5.4 MB
emerging‑smtp +2 MB 54 MB +12.1 MB −10.1 MB
emerging‑sql +7 MB 59 MB +5.3 MB +1.7 MB
emerging‑activex +7 MB 59 MB +5.1 MB +1.9 MB
emerging‑useragent +5 MB 57 MB +3.2 MB +1.8 MB
emerging‑shellcode +4 MB 56 MB +2.0 MB +2.0 MB
emerging‑worm +3 MB 55 MB +1.6 MB +1.4 MB
emerging‑dns +3 MB 55 MB +0.3 MB +2.7 MB
emerging‑voip +3 MB 55 MB +0.3 MB +2.7 MB
emerging‑snmp +2 MB 54 MB +0.3 MB +1.7 MB

Change column = (UDM‑SE delta) − (UCG‑Ultra delta). Baseline row shows absolute totals only.

Swap usage remained constant.

Cgroup Resource Limits

Cgroup: /sys/fs/cgroup/idsIps/

Resource Limit File Behaviour
RAM (hard) 1.5 GiB memory.max OOM kill if exceeded
RAM (soft) 1.4 GiB memory.high Throttling if exceeded
Swap 250 MiB memory.swap.max Max swap allowed on UCG-Ultra, UDM-SE, UXG-Pro

Total budget: 1,786 MiB (1,536 MiB RAM + 250 MiB swap)
Current usage: ~444 MiB RAM (~25% of budget)
Swap usage: 0 MiB (observed, swappiness=10)

Memory Spike During Speed Tests

Manual tests on UDM‑SE at 100/20 and 350/32 Mbps showed zero memory spike over ~2.4 minutes (291 samples @ 0.5 s). Suricata RSS remained ~443 MB. Current WAN speeds did not create enough concurrent flows to stress memory.

Why spikes occur (theory):

  • Speed tests potentially open hundreds of parallel connections.
  • Each flow consumes a table entry, TCP reassembly buffers, protocol state, and pattern‑matching state per rule.
  • Memory scales with throughput × active_rules × concurrent_flows.

OOM Kill Sequence (Observed)

  1. Cgroup limit reached (~1,786 MiB budget) → memory exhaustion.
  2. Kernel OOM killer sends SIGKILL to Suricata.
  3. Suricata did not auto‑restart in my tests.
  4. NFQUEUE path fails closed: queue fills and drops new packets.
  5. Recovery required a gateway restart (power cycle in my case).

Check OOM events: cat /sys/fs/cgroup/idsIps/memory.events | grep oom_kill

Fail Mode: Fail‑Closed (Observed)

  • Normal: Internet → WAN → nfqueue → Suricata → verdict → LAN
  • When Suricata exits: Internet → WAN → nfqueue → [no consumer] → queue fills → drop
  • Did not observe --queue-bypass enabled. NFQUEUE length appeared ~1024 packets by default.

Memory Components (Model)

Component Baseline High‑Throughput Config Limit
Rule signatures 440 MB 440 MB Static
Flow tracking Minimal +400–1,200 MB 32 MB (exceeded under load in testing)
Stream reassembly Minimal +50–200 MB 16 MB (exceeded under load in testing)
Pattern buffers Minimal +30–100 MB 32 MB (exceeded under load in testing)
Total 440 MB 930–1,840 MB Scales with WAN speed

Config: /usr/share/ubios-udapi-server/ips/config/suricata_ubios_high.yaml
Note: The configured memcaps (~80 MB total) were exceeded under load in testing.

Proposed Solutions

Option 1: Disable Auto Speed Test to prevent regular crashes

Immediate mitigation with no IPS changes; manual tests remain possible. Extremely high sustained throughput can still exhaust memory, and I have not verified whether results are used by "Smart Queues" feature.

Option 2: Reduce IPS Categories

Disabling heavier categories (e.g., emerging‑webapps ~−98 MB, emerging‑mobile ~−27 MB) reduced steady‑state RSS. With 9 categories, baseline measured ~440 MB, leaving ~1.28 GiB of headroom for flow spikes.

Rule Update Mechanisms (Observed)

Signature Rules (Emerging Threats Categories)

  • On UDM‑SE and UXG‑Pro running 4.4.3 (observed Oct 2025), signature files appeared bundled with firmware.
  • I did not observe a separate updater or cloud‑based “real‑time” rule updates on my (non-CyberSecure) devices.
  • Location: /usr/share/ubios-udapi-server/ips/rules/*.rules (86+ files)

IP Reputation Lists (Alien/Tor)

  • Update scripts are present but were not scheduled by default on my devices immediately after enabling IPS; unfortunately I did not test before toggling.
  • Manual updates had no measurable memory impact (RSS ~441–442 MB), and no Suricata restart/reload was observed (simple ipset file swap).
  • Scripts:
    • /usr/share/ubios-udapi-server/ips/bin/ips-update.sh (manual)
    • /usr/share/ubios-udapi-server/ips/bin/ips-update-service.sh (scheduler)

Additional notes

Results reflect my own 2 (+ borrowed UXG-Pro) devices and test conditions only.

Interestingly on the UXG-Pro, definition updates were attempted overnight but failed repeatedly.

I considered testing simulated 2.5 gbps throughput to definitively prove a memory issue, but don't have the time.

License

Author: Alex Findlay
License: MIT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment