SentinelX
A self-hosted intrusion detection and prevention platform in Python — 13 detectors, a bounded YAML rule language, explained 0–100 risk scores, and firewall enforcement that stays off until an administrator types a confirmation phrase.
- 13
- Detectors
- 1,876
- Tests collected
- 4
- Firewall adapters
- 14
- Synthetic attack scenarios
- Role
- Author
- Year
- 2026
- Status
- Open source
- Type
- Network intrusion detection & prevention
01Overview
SentinelX captures network traffic, live or from PCAP files, decodes it, and detects scans, brute force, floods, DNS abuse and custom rule matches. Every detection carries its evidence, the thresholds it crossed and a risk score broken down by factor. Related detections are correlated into incidents, and, only when enabled, the attacker is blocked or rate-limited through the host firewall.
It is built for people who look after one host or a small network: homelabs, small offices without a security team, training labs and analysts triaging captures. It is deliberately not a replacement for Suricata or Zeek on high-speed links, and the README says so.
I designed and built it alone. The backend is a Python modular monolith of 119 source files, with a Next.js dashboard, a Typer CLI and a Docker Compose stack beside it.
02The problem
Most small networks have no intrusion detection at all, because the serious tools assume a security team to tune them and read a raw alert feed. An alert that says only "port scan" gives a generalist nothing to act on, and a tool that blocks addresses on its own can lock its operator out of the machine it is protecting.
So the constraints were: every alert must explain itself, prevention must be off by default and hard to switch on by accident, and the tool must be honest about what the host it runs on can actually do, rather than failing silently when it lacks a privilege.
03Architecture
- 01
One pipeline for live, replay, benchmark and test
Capture → decoder → per-source feature extractor → detection engine → risk engine → correlation → response engine → safety guard → firewall. A single composition root wires it to storage, Redis and the event bus, and the API server, the CLI, the PCAP Lab and the benchmark harness all run the same assembly. A detection that fires on a replay went through the same code it would on the wire.
- 02
Own decoder and capture backends
struct-based decoders for Ethernet, Linux cooked capture, raw IP and loopback framing; IPv4, IPv6, ARP, TCP, UDP and ICMP; and DNS, HTTP request metadata and TLS ClientHello (SNI, ALPN). Capture uses AF_PACKET on Linux and libpcap through Scapy elsewhere, and SentinelX reads pcap and pcapng itself. Malformed packets are counted, never fatal.
- 03
Detectors, rules and baselines
Eleven behavioural detectors — vertical and horizontal port scans, UDP scans, brute force, SYN, connection-rate, ICMP and HTTP floods, DNS anomalies, denylisted sources and TCP flag anomalies — plus a statistical baseline detector and an optional Isolation Forest model. Custom rules are YAML, parsed by a bounded recursive-descent parser rather than evaluated as code, and each rule carries its own embedded tests.
- 04
Explained risk and correlated incidents
Each detection's score adds weighted contributions from severity, confidence, frequency, source history, correlation, threat intelligence and previous responses, capped to 0–100, with every contribution stored and shown. Seven kill-chain patterns — reconnaissance followed by a credential attack, reconnaissance with service disruption, possible exfiltration and others — group detections from one source into incidents.
- 05
Guarded response
Detect-only, manual-approval and automatic modes, with dry run on top. Firewall adapters exist for nftables, iptables, pf and Windows Firewall. A safety guard refuses to block loopback, allowlisted, management and host addresses, operators who signed in recently, and any prefix that contains a protected address.
- 06
Platform around the core
A FastAPI REST API of 65 HTTP routes plus a WebSocket event stream, SQLAlchemy over PostgreSQL (SQLite for evaluation) with Alembic migrations across 12 tables, Redis for shared state, Prometheus metrics, and a Next.js 16 dashboard. A Docker Compose stack runs postgres, redis, migrate, api, dashboard and an nginx proxy, with an optional host-network sensor profile.
04Key decisions
Off by default, and loud about it
A new installation runs detect-only, dry run on, with a null firewall backend. Turning prevention on at runtime requires typing ENABLE PREVENTION, and the change is audited. A missing or unusable firewall refuses every change rather than reporting it as done. The failure I most wanted to rule out was a security tool quietly doing something to traffic that nobody asked for.
Probe the host instead of assuming it
Capture and firewall support are decided by actually opening a raw socket, checking capability bits and running each firewall tool's read-only listing command. Each result comes with a reason and a remedy. A permission error or an invalid BPF filter is reported as it is, never hidden by quietly falling back to another backend.
An additive score over a learned one
Every point of a risk score traces to a named, re-weightable factor. It cannot model interactions between factors the way a learned model could, but an operator can see why a host scored 91, and that is what the tool is for.
Test it against real attacks, not just fixtures
A demo script attacks the Docker stack from four containers with nmap, hping3, DNS tunnelling queries and an HTTP flood. Earlier runs found real defects — targets blamed for their own replies, a SYN flood on an open port missed, SentinelX's own database traffic looking like brute force — and each fix has a regression test. On the final run the kernel's nftables counter recorded 3,084 dropped packets from the blocked attacker.
05Stack
- Python 3.12+
- FastAPI
- Pydantic
- SQLAlchemy + Alembic
- PostgreSQL
- SQLite
- Redis
- Scapy
- Typer
- Prometheus
- Next.js 16
- React 19
- TypeScript
- Tailwind CSS
- Docker
- nginx
- nftables