A self-learning, Rust-native network and host security monitoring platform with a terminal UI, REST API, and distributed agent support.
╔══════════════════════════════════════════════════════╗
║ blue-meanie v0.1.0 [SIM] Threat: ██░░░░ 12% ║
╠══════════════════════════════════════════════════════╣
║ Dashboard │ Alerts │ Incidents │ Flows │ Hosts │ ... ║
╠══════════════════════════════════════════════════════╣
║ Ev/s: 412 Alerts: 7 Incidents: 2 Flows: 1841 ║
╚══════════════════════════════════════════════════════╝
- Live capture — pcap on any interface; falls back to simulator when unprivileged
- Host monitoring — process spawns, file access, SSH key changes, login failures, cron modifications
- YAML rule engine — stateless pattern matching + stateful detectors (port scan, brute force, large transfer); hot-reload via SIGHUP with deduplication window
- Threat intelligence — IOC store (IP / domain / JA3) with Bloom filter fast-path; local + HTTP feed loading; GeoIP enrichment via MaxMind GeoLite2
- ML anomaly detection — EWMA baseline + z-score; GRU(5→48→1) neural flow classifier trained online from analyst feedback; safetensors model persistence
- Incident correlation — clusters alerts by src IP / hostname / ATT&CK technique; 12-stage kill-chain progression; composite risk scoring
- Automated response — YAML playbook engine; iptables/ip6tables firewall blocking; HTTP webhook sink
- REST API — full CRUD over alerts, incidents, rules, and verdicts; Prometheus
/metrics; optional bearer-token auth and TLS - Distributed mode — TCP NDJSON forwarding from sensor agents to central aggregator
- ratatui TUI — 7-tab dashboard (Dashboard, Alerts, Incidents, Flows, Hosts, Intel, Rules)
- 62 unit tests across all core crates
blue-meanie (workspace)
├── bm-core Event types, EventBus (tokio broadcast), Config schema
├── bm-capture pcap / eBPF network capture + host monitor (procmon, fsmon, syslog)
├── bm-pipeline Flow tracker, DNS + TLS protocol parsing
├── bm-detect YAML rule engine, stateful detectors, incident correlator
├── bm-intel IOC store, threat feed loader, GeoIP enrichment
├── bm-learn EWMA baselines, GRU neural classifier, analyst feedback loop
├── bm-respond Playbook engine, firewall blocking, webhook delivery
├── bm-storage sled hot store with configurable TTL-based retention
└── bm-tui ratatui TUI, REST API server, CLI entry point
All components communicate through a central EventBus (tokio broadcast, 16k capacity). No shared mutable state crosses crate boundaries — only Arc-wrapped stat handles.
# Build (requires Rust 1.75+)
cargo build --release
# Run with simulator (no root required)
./target/release/blue-meanie monitor --simulate
# Run with live capture (requires CAP_NET_RAW)
sudo ./target/release/blue-meanie monitor -i eth0
# Headless REST API server only
./target/release/blue-meanie serve --bind 127.0.0.1:7356 --simulate
# Validate config
./target/release/blue-meanie check-config -c config/default.toml
# Print system status as JSON
./target/release/blue-meanie status -c config/default.tomlblue-meanie [OPTIONS] <COMMAND>
Commands:
monitor Start the interactive TUI (default)
aggregate Receive alerts from remote agents and display in TUI
serve Headless REST API server (no TUI)
status Print JSON status and exit
check-config Validate configuration and exit
monitor options:
-i, --interface <IF> Network interface [default: any]
-s, --simulate Force simulator mode
--api-bind <ADDR> Enable REST API (e.g. 127.0.0.1:7356)
--tls-cert <PATH> PEM certificate for API TLS
--tls-key <PATH> PEM private key for API TLS
serve options:
--bind <ADDR> Listen address [default: 127.0.0.1:7356]
-s, --simulate
--tls-cert / --tls-key
Global:
-c, --config <PATH> Config file [default: built-in defaults]
Copy and edit config/default.toml:
[capture]
interfaces = ["eth0"]
host_events = true
[detection]
rules_dir = "rules"
anomaly_threshold = 0.85
dedup_window_secs = 60 # suppress duplicate (src_ip, rule) alerts within window
[storage]
data_dir = "/var/lib/blue-meanie"
hot_retention_hours = 24 # alerts older than this are purged every 15 minutes
[intel]
enabled = true
# geoip_db_path = "/var/lib/blue-meanie/GeoLite2-City.mmdb"
# asn_db_path = "/var/lib/blue-meanie/GeoLite2-ASN.mmdb"
[response]
automation_level = "observe" # observe | alert | contain | eliminate
playbooks_dir = "playbooks"
firewall_backend = "iptables" # iptables | nftables | none
[api]
enabled = true
bind = "127.0.0.1:7356"
# key = "change-me"
# tls_cert = "/etc/blue-meanie/tls/cert.pem"
# tls_key = "/etc/blue-meanie/tls/key.pem"
[forward]
enabled = false
endpoint = "aggregator-host:7355"Rules live in rules/ as YAML files and are hot-reloaded on SIGHUP:
rules:
- id: NET-001
name: Outbound SSH
description: Detect outbound connections on port 22
severity: medium
tactic: LateralMovement
technique: T1021.004
detector:
kind: network_flow
dst_port: 22
- id: HOST-001
name: Port Scan
severity: high
tactic: Reconnaissance
detector:
kind: port_scan
threshold: 20
window_secs: 30Supported detector kinds: network_flow, file_access, process_spawn, ssh_key_change, port_scan, brute_force, large_transfer.
Playbooks live in playbooks/ and are evaluated against every alert:
name: Block Malicious IP
trigger:
min_severity: high
tags: [ioc]
steps:
- kind: firewall_block_ip
target: "{src_ip}"
- kind: webhook
url: "https://hooks.example.com/alert"
- kind: log
message: "Blocked {src_ip} — rule {rule_id}"All endpoints require X-API-Key: <key> or Authorization: Bearer <key> when [api] key is set. /health is always unauthenticated.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness probe |
GET |
/metrics |
Prometheus text format |
GET |
/api/v1/status |
System summary JSON |
GET |
/api/v1/alerts |
Query stored alerts (?since=1h&severity=high&rule_id=X&limit=200) |
POST |
/api/v1/alerts/{id}/verdict |
Submit analyst verdict (true_positive, false_positive, suppressed) |
GET |
/api/v1/incidents |
Active/resolved incidents (?status=active&limit=50) |
GET |
/api/v1/rules |
Loaded rules with hit counts |
POST |
/api/v1/rules/{id}/toggle |
Enable/disable a rule on disk (SIGHUP to reload) |
Alert responses include src_country, src_asn_org, dst_country, dst_asn_org when GeoIP databases are configured.
# Generate a self-signed cert for testing
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
blue-meanie serve --tls-cert cert.pem --tls-key key.pemDownload free MaxMind GeoLite2 databases (requires a free account at maxmind.com):
GeoLite2-City.mmdb → country name + ISO code
GeoLite2-ASN.mmdb → AS number + organisation
Set paths in config/default.toml under [intel]. The TUI Alerts tab and REST API responses will then show 1.2.3.4 [US/Cloudflare, Inc.] next to each IP.
Sensor agents forward alerts to a central aggregator:
[forward]
enabled = true
endpoint = "siem.internal:7355"
secret = "shared-secret"Aggregator receives from all agents and runs the full detection stack:
blue-meanie aggregate --bind 0.0.0.0:7355sudo ./packaging/install.sh
sudo systemctl enable --now blue-meanie
# Hot-reload rules + playbooks without restart
sudo systemctl reload blue-meanie # sends SIGHUP# Build
cargo build
# Run all tests (62 tests across 5 crates)
cargo test
# Run with logging
RUST_LOG=info cargo run -- monitor --simulate| Crate | Tests | What's covered |
|---|---|---|
bm-core |
3 | AlertSeverity ordering, Alert JSON round-trip |
bm-detect |
29 | All rule types, port scan/brute-force thresholds, dedup suppression, kill-chain mapping + scoring |
bm-intel |
19 | IP classification boundaries, IOC store CRUD + hit counter, GeoInfo label formatting |
bm-storage |
3 | Alert persistence, TTL purge removes old / preserves fresh |
bm-tui |
8 | parse_since (h/m/d), parse_severity (all variants + case) |
MIT