Feature directory:
specs/001-unifi-log-ingestion/Status: Draft Backlog: VED-002 (document/validate the UniFi connector workflow), VED-005 (define the first supportable router/firewall ingestion path — resolved: UniFi via hybrid syslog + optional REST) Created: 2026-07-03
Make UniFi gateways the first router/firewall data source Vedetta can honestly call
"supported." Users point their UniFi Network application's SIEM/syslog export at the
Vedetta collector (UDP 5140, already listening); firewall events arrive as normalized
firewall_log events in the existing events pipeline, tagged source:unifi, tuned so
the new source adds signal without flooding the dashboard. The existing REST connector
groundwork in backend/internal/firewall/ is finished as an optional, off-by-default
enrichment path (client inventory + IPS events that UniFi does not reliably export via
syslog). The user-visible outcome: a UniFi owner follows a one-page setup guide, and
within minutes sees firewall blocks correlated with their device inventory — without a
noisy wall of WAN scan drops.
docs/roadmap.md"Planned next" names router/firewall log aggregation with UniFi first;research/09-implementation-roadmap.mdcalls UniFi "high-value because UniFi is the most common prosumer/SMB network stack."docs/backlog.mdVED-005 asks for the first supportable ingestion path and VED-002 asks to validate/document the existing UniFi connector groundwork. This spec resolves both with one decision: hybrid — syslog/CEF push is the supported event path; the REST connector is optional inventory enrichment.research/deep-dive-firewall-connectors.md(primary research): UniFi exports CEF via its SIEM integration but does not reliably forward IPS/IDS detections to syslog; those are only available via the controller REST API. It also documents the connector interface already present inbackend/internal/firewall/.research/02-log-aggregation.md: Fluent Bit is the right collector (450 KB binary, ~2 MB RAM, fits the Pi 4 budget); the UDP 5140 syslog input and the HTTP output to/api/v1/ingestalready exist incollector/config/fluent-bit.conf.- The historical blocker is gone:
POST /api/v1/ingestis implemented and working (single object, array, and Fluent Bit[timestamp, record]pairs; validation; enrichment; batchInsertEvents).GET /api/v1/events,/stats,/timeline, the sequential migration runner (17 migrations), and the daily retention enforcer all exist. The pipeline is ready for its first external log source. - Local analysis (
analysis-notes/03-unifi-ingestion.md, gitignored) confirms the sequencing: pipeline unblock is done, UniFi is the natural next data source, and SNR re-tuning is the main new work.
- As a homelab user with a UniFi gateway, I want to forward my gateway's syslog to Vedetta so that firewall blocks and client events show up alongside DNS events without installing anything on the gateway.
- As a small business operator, I want Vedetta to tell me when a device on my IoT VLAN has outbound traffic blocked by the firewall so that I can spot compromised or misconfigured devices — and I don't want thousands of routine WAN scan drops burying that signal.
- As a UniFi owner who also wants inventory context, I want to optionally connect Vedetta to my controller with a read-only API key so that firewall events are enriched with client names, connection type, and network/VLAN — while Vedetta stays fully functional if I never do this.
- As a Vedetta contributor, I want the UniFi path documented end to end (what is supported, what is experimental) so that the next connector (pfSense/OPNsense, OpenWrt) can follow the same shape.
- FR-1: Vedetta MUST ingest UniFi syslog output on the existing collector UDP 5140
input, in both formats UniFi produces: CEF (modern UniFi OS "SIEM Server" export) and
legacy iptables-style kernel log lines (USG/EdgeOS-style
[RULESET-N-A]messages). - FR-2: Firewall messages MUST be normalized to the existing
FirewallEventshape (action, protocol, src/dst IP and port, interface, direction, rule) and stored asevent_type = "firewall_log"events viaPOST /api/v1/ingest— structured fields in the eventmetadataJSON andtags, no neweventscolumns (see plan.md). - FR-3: Every UniFi-derived event MUST carry the tag
source:unifiso queries, suppression rules, and the UI can filter by origin. Action tags (fw:block,fw:allow, etc.) and direction/interface context MUST be queryable via tags or metadata. - FR-4: Non-firewall UniFi syslog lines (AP chatter, DHCP renewals, stp/kernel noise) MUST be dropped or aggregated at the collector — they never reach the events table as individual rows.
- FR-5: SNR tuning MUST ship with the feature: default suppression/whitelist rules for
WAN inbound scan drops and known-benign block patterns (seeded via a new migration,
is_default = TRUE, user-disableable), plus scoring context that boosts blocked outbound traffic from LAN/IoT devices (see plan.md SNR section). - FR-6: The REST connector (
backend/internal/firewall/unifi.go) MUST be completed to the point of "documented experimental": configurable off-by-default, API-key auth (X-API-KEY) in addition to the existing username/password login, client inventory sync into the device registry, and IPS event polling. It is enrichment, not the primary event path. - FR-7: A setup guide (
docs/connectors/unifi.md) MUST document: enabling UniFi SIEM/syslog export toward the collector, which log categories to enable, expected event volume, the optional REST connector setup, and what is supported vs experimental. This closes VED-002. - FR-8:
POST /api/v1/ingestMUST support optional bearer-token authentication (ingest scope) so a syslog source on the LAN cannot trivially inject forged events; default behavior stays backward compatible with the existing collector deployment (see plan.md "Auth" and Constitution note below). - FR-9: Malformed or unparseable syslog lines MUST NOT create events; they are counted (collector-side metric/log) and a sample is logged for parser improvement.
- NFR-1: Pi 4 hardware floor — the added collector parsing (Lua CEF/iptables transform) and ingest volume MUST fit the idle budget (<200 MB RAM, <5% CPU core paths). A collector-side throttle caps sustained firewall event throughput (default 2,000 events/min) so a WAN scan flood degrades to sampling, not to OOM or SD-card thrash.
- NFR-2: Works with Core + native sensor only — UniFi ingestion is additive. No new required dependency: without a UniFi device, nothing changes; with one, only syslog export configuration on the UniFi side is needed (no agent on the gateway).
- NFR-3: Storage: at ~1,000–10,000 firewall events/day post-suppression (per
research/02-log-aggregation.mdvolume estimates) the 90-day retention window stays within the existing SQLite sizing envelope (~≤1 GB total). - NFR-4: Backward compatibility: no changes to existing event fields or tags; new tags are additive; sensors and the collector upgrade independently of Core.
| Constraint | Applies? | How this feature complies |
|---|---|---|
| L2 native sensor split | Yes (peripherally) | No change to the sensor. UniFi ingestion flows through the Docker-side collector + Core only; L2 visibility still comes from the native sensor. No Docker-collapse proposals. |
| Pi-hole optional | Yes | UniFi is another optional input beside Pi-hole/AdGuard/native capture. Vedetta delivers full value with neither; the collector's Pi-hole tail input is untouched. |
| Passive-first | Yes | Syslog push is passive receipt of logs the gateway already emits — zero gateway cooperation beyond one settings toggle, no active scanning. The REST poll is optional, read-only, and off by default. |
| V1 scope (no LAN scan/exploit) | Yes | Log ingestion only. No active vulnerability assessment, no exploit verification, no full LAN scanning. Scope cuts listed below. |
| SNR re-tune for new sources | Yes | Core of this spec: default suppression rules, WAN-scan-noise aggregation, context scoring, and a recorded SNR validation pass are REQUIRED before UniFi is labeled "supported" (FR-5, plan.md SNR Tuning Plan). |
| Privacy / opt-in telemetry | Yes | All data stays local. Firewall events follow the existing PII posture (source_hash HMAC, local-only raw IPs). Nothing UniFi-derived feeds telemetry/threat-network (both still stubs). |
| Environment data handling | Yes | All examples in this spec directory use RFC 5737 IPs, 00:00:5E:00:53:xx MACs, and placeholder hostnames. Live captures used to validate the parser are written to gitignored analysis-notes/ only (tasks.md T1.2). |
| One data source at a time | Yes | UniFi lands as a complete, tuned workflow (ingest → normalize → suppress → document → validate) before pfSense/OPNsense or OpenWrt start. |
| New sequential migration only | Yes | One new migration 018_unifi_firewall_defaults.sql; no committed migration is edited. |
This is the first source since DNS that can emit thousands of events/day, and most of them are noise by default. New noise patterns and the tuning work they demand:
| Noise pattern | Volume risk | Tuning shipped with this feature |
|---|---|---|
| WAN inbound default-drop (internet background radiation, scanners hitting 203.0.113.x WAN IP) | Very high (can be 10k+/day) | Collector-side aggregation: individual WAN-inbound drops are not stored as rows; a periodic rollup event (tags: ["source:unifi","wan_scan_noise"], counts in metadata) is stored instead. Default whitelist rule keeps rollups at score 0. |
| Legitimate blocked IoT outbound (cameras/TVs phoning home to disallowed destinations, expected on segmented networks) | Medium | Default suppression by (device, dst, rule) recurrence: first occurrence scores as signal (new_fw_block tag); repeats within a window are deduplicated/score-decayed. User can whitelist per device+destination. |
| Broadcast/multicast and inter-VLAN chatter blocks (mDNS, SSDP across segments) | Medium | Default whitelist rules for well-known multicast/broadcast destination patterns (category: firewall), seeded is_default = TRUE in migration 018. |
| Client connect/disconnect and AP/system CEF categories | Medium | Not stored as firewall events. Dropped at the collector in V1 (out of scope below) — only firewall/security categories pass. |
| Admin/self-inflicted noise (Vedetta's own nmap discovery tripping gateway rules) | Low | Default whitelist rule matching the Core/sensor host source IP pattern for firewall_log events, documented in the setup guide. |
Signal this source adds: blocked outbound from risk-flagged devices (correlates with
risk_category from migration 016), first-seen firewall blocks per device, IPS events
(via optional REST path), port-forward-related exposure context, and cross-source
correlation (DNS query → firewall block for the same device).
The source is NOT called "supported" until the SNR validation loop in plan.md runs on simulated + live traffic and the results are recorded (tasks.md Phase 5 + Final Gate).
- pfSense/OPNsense, OpenWrt, MikroTik connectors — one data source at a time; the filterlog research is done but lands in a later spec.
- UniFi client connect/disconnect and AP event ingestion — different noise class and different value proposition (presence tracking); revisit after firewall events are tuned.
- DPI/application stats and network-health polling — dashboard/metrics work, not
security events; the REST connector's
GetFirewallState/health surface beyond basic connectivity checks stays experimental. - Firewall rule/config drift detection — needs stored rule-state history; deferred until the connector path matures.
- Acting on the firewall (blocking clients via UniFi API) — Vedetta is watch-only in V1; write access to the gateway is a hard scope cut.
- TCP/TLS syslog transport — UDP 5140 only in V1 (matches existing collector input); TLS syslog needs cert management UX that isn't justified yet.
- Multi-site / multi-controller UniFi — single controller/gateway assumed; multi-site tagging is a follow-up.
- CEF ingestion from non-UniFi vendors — the Lua transform is written for UniFi's dialect; generic CEF support is not claimed.
- Exact CEF device-event IDs and extension keys per UniFi Network version — the
contract (
contracts/unifi-syslog-cef.md) documents the expected mapping from vendor docs/research; T1.2 validates against a live capture (sanitized before anything lands in tracked files) and updates the contract. - Whether modern UniFi OS gateways still emit the legacy iptables-style lines when "syslog" (non-SIEM) export is enabled — determines how much weight the fallback parser needs.
- Rollup window for WAN scan noise (initial: 15 min) — validate against live volume in Phase 5 before freezing the default.
- Should ingest-token enforcement become the default in the next release once the
collector ships with token support? (Tracked in
docs/auth-hardening-plan.md.)