A SIEM-style firewall for one machine: capture traffic, apply firewall rules, detect attacks, block the attacker, and watch it all on a live dashboard.
capture ──► rules ──► detection ──► enforcement ──► SQLite ──► live dashboard
(Scapy: (IPs, (port scans, (dry-run, or (events, (Flask + Socket.IO:
interface CIDRs, SYN floods, iptables on alerts) charts, search,
or PCAP) ports, repeat Linux) alerts, rule editor)
protocols) offenders...)
-
Captures IPv4 and IPv6 traffic live from an interface, or replays a PCAP file (no privileges needed), with Scapy.
-
Applies firewall rules from
rules.json: blocked addresses and CIDR ranges, destination ports, protocols, and an allowlist. Rules are edited live from the dashboard and validated before they are saved. -
Detects five patterns over sliding time windows:
Detection Fires when Severity Port scan one source reaches 15 destination ports on a host within 10 s high SYN flood 200 connection attempts (SYN without ACK) reach a host within 5 s; attributed to a source only if it sent most of them high Repeated blocks one source is blocked 5 times within 60 s medium Frequent source one source sends over 500 packets within 60 s low Rare protocol a protocol is under 1% of the last 200+ packets low Each alert is suppressed per source for a cooldown, so a sustained attack gives one alert, not thousands. Every threshold is in
rules.json. -
Enforces blocks at the host firewall: in
dry-runmode (the default) it records what it would block; iniptablesmode (Linux) it adds a DROP rule once per address. Only a blocked-address rule or an attack detection blocks a source: a packet that merely hits a blocked port or protocol is logged as BLOCKED without cutting off the whole host. Loopback and allowlisted addresses are never blocked. -
Records every packet event and alert in SQLite (WAL mode), with UTC timestamps so time charts are right in every timezone.
-
Shows it on a live dashboard: protocol/action distribution, events over time (per second, minute or hour), top sources and destinations, an alert table with the response taken, a searchable event log, a rules editor, light and dark themes, and JSON export.
git clone https://github.com/JampaniKomal/PacketSentinal && cd PacketSentinal
pip install -e .
packetsentinel demodemo writes a synthetic capture (two minutes of web, DNS and SSH traffic, a
ping, an address on the block list, a port scan and a spoofed SYN flood) and
analyses it:
1817 packets from 39 sources in 2.28s; 12 matched a block rule
protocols: TCP 1654, UDP 160, ICMP 3
3 alert(s):
14:13:48 MEDIUM repeated_blocks 1.2.3.4 blocked 5 times in 60s
14:14:06 HIGH port_scan 203.0.113.66 15 ports on 192.168.56.10 in 10s (e.g. 21, 25, 80, 443, 995, 1000)
14:14:40 HIGH syn_flood 200 SYNs to 192.168.56.10 in 5s, distributed across 30 sources
enforcement (dry-run): 2 address(es) would be blocked
1.2.3.4 Blocked IP 1.2.3.4
203.0.113.66 15 ports on 192.168.56.10 in 10s (e.g. 21, 25, 80, 443, 995, 1000)
The pinging host matched the ICMP rule but was not blocked, and none of the 30 spoofed flood sources were blocked either, since blocking them would not stop the flood.
packetsentinel run --demo # choose "Demo" in Scan Target, press Start
sudo packetsentinel run # live capture (choose an interface in the dashboard)
sudo packetsentinel run --iface eth0 --enforce iptablesOpen http://127.0.0.1:5000. Live capture needs root on Linux and macOS, or an Administrator terminal with Npcap on Windows.
packetsentinel analyze capture.pcap # summary, alerts, what would be blocked
packetsentinel analyze capture.pcap --json # the same as JSONrules.json is created with defaults the first time run starts:
{
"blocked_ips": ["1.2.3.4", "12.10.3.42"],
"blocked_ports": [23, 4444],
"blocked_protocols": ["ICMP"],
"allowlist": [],
"detection": { "port_scan_ports": 15, "port_scan_window_seconds": 10, "syn_flood_syns": 200, "...": "..." },
"enforcement": { "mode": "dry-run", "block_on": ["blocked_ip", "port_scan", "syn_flood"] }
}Put your gateway and anything else you must never lose in allowlist before
switching to iptables mode.
- The dashboard has no authentication and controls a process with capture
privileges, so it binds to 127.0.0.1.
--host 0.0.0.0prints a warning; put it behind an authenticating reverse proxy if you need remote access. - PacketSentinel sees packets after the kernel has accepted them. Blocking stops later traffic from a source; it is a response, not an inline filter.
- Blocks added in
iptablesmode stay until you remove them (iptables -D INPUT -s <ip> -j DROP), and are listed in the JSON export.
packetsentinel/
events.py packet events from Scapy packets (protocol names, ports, TCP flags)
rules.py rules.json: matching (CIDR aware), validation, atomic saves
detection.py sliding-window detectors and alert cooldowns
enforcement.py dry-run and iptables enforcement with safety checks
store.py SQLite storage and dashboard queries
engine.py the pipeline, live capture and PCAP replay
web.py Flask + Socket.IO dashboard server
traffic.py synthetic attack capture for the demo and tests
cli.py the packetsentinel command
dashboard/ dashboard template and styles
tests/ rules, detectors, enforcement, storage, an end-to-end replay, the dashboard
PacketSentinel began in July 2025 as "Python SIEM Firewall": a Scapy sniffer
applying rules.json, iptables blocking, SQLite logs and a Flask dashboard
with Chart.js and DataTables, plus a detector for frequent sources, rare
protocols and repeated blocks. Within the week the dashboard went live over
Socket.IO, and in December 2025 the project was renamed PacketSentinel.
Version 2 (2026) made it a package with tests and CI, and fixed what v1 got
wrong:
- The detector was never wired in (its thresholds sat unused in
rules.json, and a 2026 clean-up deleted it as dead code), and it looked for the actionBLOCKwhile events were logged asBLOCKED. It is back, running on every packet over time windows. - The port-scan and SYN-flood detection the README described didn't exist.
- A single packet matching the ICMP protocol rule blocked its sender's whole address, which could include your own gateway.
- Every protocol other than TCP and ICMP was logged as UDP.
- The events-over-time chart compared local timestamps with SQLite's UTC clock, so it was wrong outside UTC.
- It could only be tried with root on a live interface; PCAP replay and the demo now make it testable anywhere.
MIT. See LICENSE.