Skip to content
 
 

Latest commit

 

History

241 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Stackdog Security

Version License Rust Platform

STACKDOG

🛡️ Security platform for Docker Containers & Linux Servers

Stackdog Security is a Rust-based security platform that provides real-time threat detection, AI-powered anomaly detection, and automated response for containerized applications.

🔥 Key Features

  • 📊 Real-time Monitoring — eBPF-based syscall monitoring with minimal overhead (<5% CPU)
  • 🔍 Log Sniffing — Discover, read, and AI-summarize logs from containers and system files
  • 🧭 Detector Framework — Rust-native detector registry for web attack heuristics and outbound exfiltration indicators
  • 🤖 AI/ML Detection — Candle-powered anomaly detection + OpenAI/Ollama log analysis
  • 🚨 Alert System — Multi-channel notifications (Slack, email, webhook)
  • 🔒 Automated Response — nftables/iptables firewall, container quarantine
  • 📈 Threat Scoring — Configurable scoring with time-decay
  • 🎯 Signature Detection — 10+ built-in threat signatures
  • 📦 Log Archival — Deduplicate and compress logs with zstd, optionally purge originals

📖 Table of Contents


⬆️ Upgrading

Notes for anyone moving from v0.2.4 or earlier. Nothing here needs to be run by hand, but two changes alter behaviour you may be relying on.

IP banning is stricter about who it accuses

Earlier versions could ban addresses that were merely present in a log the analyzer was reading:

  • a finding whose sample line named no address caused every address in that batch to be banned;
  • descriptions containing frequent access, targeting, scanning, possible attack or rejected connection counted as grounds for a ban;
  • an auth-log line naming both client and server banned both;
  • browser versions in User-Agent strings (Chrome/122.0.0.0) parsed as addresses and were banned as 122.0.0.0.

Bans now follow only the evidence: the sample line, then the description. A finding that accuses nobody raises an alert and stops there.

Three settings are worth reviewing after upgrading:

Variable Default Why
STACKDOG_IP_BAN_ALLOWLIST empty Addresses never banned. Put load balancers, health checkers and this host's own public address here — banning them takes the service down.
STACKDOG_TRUSTED_PROXY_RANGES RFC1918 only A public-facing proxy is not covered by the defaults, so its own address is banned instead of the client behind it. Add it as <ip>/32.
STACKDOG_IP_BAN_MAX_PER_MINUTE 10 Ceiling on blocks per minute. A burst is more often a misread log than a crowd of attackers. 0 disables it.

To ban only on deterministic detectors and never on analyzer prose, set STACKDOG_IP_BAN_FROM_AI_FINDINGS=false.

The offense table is rewritten on first start

ip_offenses held one row per detection with offense_count stuck at 1, so the table grew with every hit and one ban left several rows behind — which is why a single expiry emitted several "Released IP ban" notifications.

The first start after upgrading collapses each (ip_address, source_type) group into one row carrying the tally and the earliest sighting, keeping a live block over a released one, then enforces the layout with a unique index. It runs once, automatically, and is skipped on later starts.

Back up the database first if its history matters to you:

docker exec <stackdog> sqlite3 /data/stackdog.db ".backup '/data/stackdog.pre-upgrade.db'"

Stackdog no longer reads its own logs

Running in Docker, it used to analyze its own output and report its own errors as findings. It now skips its own container. Detection works without configuration, but under network_mode: host the surest signal is a label:

labels:
  com.trydirect.stackdog.ignore: "true"

The same label excludes any other container you would rather not analyze.

The dashboard has its own image

trydirect/stackdog-ui:latest is published alongside the backend. Pointing a dashboard service at trydirect/stackdog:latest starts a second copy of the backend instead, listening on 5000 while port 3000 maps to nothing.

The API address is read from the environment at container start, so changing it is a restart rather than a rebuild:

stackdog-ui:
  image: trydirect/stackdog-ui:latest
  environment:
    STACKDOG_API_URL: http://<host>:5000/api
    STACKDOG_WS_URL: ws://<host>:5000/ws
  ports:
    - "3000:80"

Build args named REACT_APP_* never reached the bundle in earlier versions, so any address configured that way was silently ignored.

Alerts can link back to the dashboard

Set STACKDOG_UI_URL and every notification carries a link to the alert that fired. Left unset, notifications look as they did before.


🚀 Quick Start

Install with curl (Linux)

curl -fsSL https://raw.githubusercontent.com/trydirect/stackdog/main/install.sh | sudo bash

Pin a specific version:

curl -fsSL https://raw.githubusercontent.com/trydirect/stackdog/main/install.sh | sudo bash -s -- --version v0.2.2

If your repository has no published stable release yet, use --version explicitly.

Run as Binary

# Clone repository
git clone https://github.com/trydirect/stackdog
cd stackdog

# Start the HTTP server (default)
cargo run

# Or explicitly
cargo run -- serve

Run with Docker

Use the published container image for the quickest way to explore the API. If you are validating a fresh branch or waiting for Docker Hub to pick up the latest CI build, prefer the local-image flow below so you know you are running your current checkout:

docker volume create stackdog-data

docker run --rm -it \
  --name stackdog \
  --network host \
  --cap-add=NET_ADMIN \
  -e APP_HOST=0.0.0.0 \
  -e APP_PORT=5000 \
  -e DATABASE_URL=/data/stackdog.db \
  -v stackdog-data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  trydirect/stackdog:latest

Note: --network host and --cap-add=NET_ADMIN are required for IP banning (iptables/nftables) to work. Without them, firewall rules from inside the container cannot affect host traffic.

Then open another shell and hit the API:

curl http://localhost:5000/api/security/status
curl http://localhost:5000/api/threats
curl http://localhost:5000/api/alerts

Mount the Docker socket when you want Docker-aware features such as container listing, live stats, mail abuse guard polling, Docker log discovery, and Docker-backed quarantine/release flows.

If you do not want Stackdog to access the Docker daemon, disable the mail guard:

STACKDOG_MAIL_GUARD_ENABLED=false

To try log sniffing inside Docker against host log files, mount them read-only and run the sniff subcommand instead of the default HTTP server:

docker run --rm -it \
  -e DATABASE_URL=/tmp/stackdog.db \
  -v /var/log:/host-logs:ro \
  trydirect/stackdog:latest \
  sniff --once --sources /host-logs/auth.log

If you want to test your current checkout instead of the latest published image:

docker build -f docker/backend/Dockerfile -t stackdog-local .

docker run --rm -it \
  --name stackdog-local \
  --network host \
  --cap-add=NET_ADMIN \
  -e APP_HOST=0.0.0.0 \
  -e APP_PORT=5000 \
  -e DATABASE_URL=/data/stackdog.db \
  -v stackdog-data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  stackdog-local

Run backend + UI with Docker Compose

To run stackdog serve and the web UI as two separate services from your current checkout:

docker compose -f docker-compose.app.yml up --build

This starts:

  • API at http://localhost:5000
  • UI at http://localhost:3000

The compose stack uses:

  • stackdog service — builds docker/backend/Dockerfile, runs stackdog serve, mounts /var/run/docker.sock, uses network_mode: host, and adds NET_ADMIN capability for IP banning
  • stackdog-ui service — builds the React app and serves it with Nginx
  • stackdog-data volume — persists the SQLite database between restarts

Prerequisite for IP banning: The network_mode: host and cap_add: NET_ADMIN settings are required so that iptables/nftables rules applied inside the container affect the host's network stack. Without them, IP ban firewall rules cannot reach host traffic.

To stop it:

docker compose -f docker-compose.app.yml down

Log Sniffing

# Discover and analyze logs (one-shot)
stackdog -- sniff --once

# Continuous monitoring with AI analysis
stackdog -- sniff --ai-provider openai

# Use Ollama (local LLM)
STACKDOG_AI_API_URL=http://localhost:11434/v1 cargo run -- sniff

# Consume mode: archive to zstd + purge originals
stackdog -- sniff --consume --output ./log-archive

# Add custom log sources
stackdog -- sniff --sources "/var/log/myapp.log,/opt/service/logs"

The built-in sniff pipeline now includes Rust-native detectors for:

  • web attack indicators such as SQL injection probes, path traversal probes, login brute force, and webshell-style requests
  • exfiltration-style indicators such as suspicious SMTP/attachment activity and large outbound transfer hints in logs
  • reverse shell behavior, sensitive file access, cloud metadata / SSRF access, exfiltration chains, and secret leakage in logs
  • Wazuh-inspired file integrity monitoring for explicit paths configured with STACKDOG_FIM_PATHS=/etc/ssh/sshd_config,/app/.env
  • Wazuh-inspired configuration assessment via STACKDOG_SCA_PATHS, package inventory heuristics via STACKDOG_PACKAGE_INVENTORY_PATHS, Docker posture audits, and improved RFC3164/RFC5424 syslog parsing

Use as Library

Add to your Cargo.toml:

[dependencies]
stackdog = "0.2"

Basic usage:

use stackdog::{RuleEngine, AlertManager, ThreatScorer};

let mut engine = RuleEngine::new();
let mut alerts = AlertManager::new()?;
let scorer = ThreatScorer::new();

// Process security events
for event in events {
    let score = scorer.calculate_score(&event);
    if score.is_high_or_higher() {
        alerts.generate_alert(...)?;
    }
}

Docker Development

# Run the published image
docker run --rm -it -p 5000:5000 trydirect/stackdog:latest

# Or, for the most reliable test of your current code, build and run your checkout
docker build -f docker/backend/Dockerfile -t stackdog-local .
docker run --rm -it -p 5000:5000 stackdog-local

# Or run backend + UI together
docker compose -f docker-compose.app.yml up --build

🏗️ Architecture

┌─────────────────────────────────────────────────────────────────┐
│                     Stackdog Security Core                      │
├─────────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐  │
│  │  Collectors │  │   ML/AI     │  │   Response Engine       │  │
│  │             │  │   Engine    │  │                         │  │
│  │ • eBPF      │  │             │  │ • nftables/iptables     │  │
│  │ • Auditd    │  │ • Anomaly   │  │ • Container quarantine  │  │
│  │ • Docker    │  │   Detection │  │ • Auto-response         │  │
│  │   Events    │  │ • Scoring   │  │ • Alerting              │  │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────┐  │
│  │  Log Sniffing                                             │  │
│  │  • Auto-discovery (system logs, Docker, custom paths)     │  │
│  │  • AI summarization (OpenAI/Ollama/Candle)                │  │
│  │  • zstd compression, dedup, log purge                     │  │
│  └───────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

Components

Component Description Status
Events Security event types & validation ✅ Complete
Rules Rule engine & signature detection ✅ Complete
Alerting Alert management & notifications ✅ Complete
Firewall nftables/iptables integration ✅ Complete
Collectors eBPF syscall monitoring ✅ Infrastructure
Log Sniffing Log discovery, AI analysis, archival ✅ Complete
ML Candle-based anomaly detection ⏳ Planned

🎯 Features

1. Event Collection

use stackdog::{SyscallEvent, SyscallType};

let event = SyscallEvent::builder()
    .pid(1234)
    .uid(1000)
    .syscall_type(SyscallType::Execve)
    .container_id(Some("abc123".to_string()))
    .build();

Supported Events:

  • Syscall events (execve, connect, openat, ptrace, etc.)
  • Network events
  • Container lifecycle events
  • Alert events

2. Rule Engine

use stackdog::RuleEngine;
use stackdog::rules::builtin::{SyscallBlocklistRule, ProcessExecutionRule};

let mut engine = RuleEngine::new();
engine.register_rule(Box::new(SyscallBlocklistRule::new(
    vec![SyscallType::Ptrace, SyscallType::Setuid]
)));

let results = engine.evaluate(&event);

Built-in Rules:

  • Syscall allowlist/blocklist
  • Process execution monitoring
  • Network connection tracking
  • File access monitoring

3. Signature Detection

use stackdog::SignatureDatabase;

let db = SignatureDatabase::new();
println!("Loaded {} signatures", db.signature_count());

let matches = db.detect(&event);
for sig in matches {
    println!("Threat: {} (Severity: {})", sig.name(), sig.severity());
}

Built-in Signatures (10+):

  • 🪙 Crypto miner detection
  • 🏃 Container escape attempts
  • 🌐 Network scanners
  • 🔐 Privilege escalation
  • 📤 Data exfiltration

4. Threat Scoring

use stackdog::ThreatScorer;

let scorer = ThreatScorer::new();
let score = scorer.calculate_score(&event);

if score.is_critical() {
    println!("Critical threat detected! Score: {}", score.value());
}

Severity Levels:

  • Info (0-19)
  • Low (20-39)
  • Medium (40-69)
  • High (70-89)
  • Critical (90-100)

5. Alert System

use stackdog::AlertManager;

let mut manager = AlertManager::new()?;

let alert = manager.generate_alert(
    AlertType::ThreatDetected,
    AlertSeverity::High,
    "Suspicious activity detected".to_string(),
    Some(event),
)?;

manager.acknowledge_alert(&alert.id())?;

Notification Channels:

  • Console (logging)
  • Slack webhooks
  • Email (SMTP)
  • Generic webhooks

6. Firewall & Response

use stackdog::{QuarantineManager, ResponseAction, ResponseType};

// Quarantine container
let mut quarantine = QuarantineManager::new()?;
quarantine.quarantine("container_abc123")?;

// Automated response
let action = ResponseAction::new(
    ResponseType::BlockIP("192.168.1.100".to_string()),
    "Block malicious IP".to_string(),
);

Response Actions:

  • Block IP addresses
  • Block ports
  • Quarantine containers
  • Kill processes
  • Send alerts
  • Custom commands

7. Log Sniffing & AI Analysis

# Discover all log sources and analyze with AI
stackdog sniff --once --ai-provider openai

# Continuous daemon with local Ollama
stackdog sniff --interval 60 --ai-provider openai

# Consume: archive (zstd) + purge originals to free disk
stackdog sniff --consume --output ./archive

# Add custom sources alongside auto-discovered ones
stackdog sniff --sources "/app/logs/api.log,/app/logs/worker.log"

Capabilities:

  • 🔍 Auto-discovers system logs, Docker container logs, and custom paths
  • 🤖 AI summarization via OpenAI, Ollama, or local pattern analysis
  • 📦 Deduplicates and compresses logs with zstd
  • 🗑️ Optional --consume mode: archives then purges originals
  • 📊 Incremental reading — tracks byte offsets, never re-reads old entries
  • 🚨 Anomaly alerts routed to configured notification channels

REST API:

# List discovered sources
curl http://localhost:5000/api/logs/sources

# Add a custom source
curl -X POST http://localhost:5000/api/logs/sources \
  -H 'Content-Type: application/json' \
  -d '{"path": "/var/log/myapp.log", "name": "My App"}'

# View AI summaries
curl http://localhost:5000/api/logs/summaries?source_id=myapp

📦 Installation

Prerequisites

  • Rust 1.75+ (install)
  • SQLite3 + libsqlite3-dev
  • Linux kernel 4.19+ (for eBPF features)
  • Clang/LLVM (for eBPF compilation)

Install Dependencies

Ubuntu/Debian:

apt-get install libsqlite3-dev libssl-dev clang llvm pkg-config

macOS:

brew install sqlite openssl llvm

Fedora/RHEL:

dnf install sqlite-devel openssl-devel clang llvm

Build from Source

git clone https://github.com/trydirect/stackdog
cd stackdog
cargo build --release

Run Tests

# Run all tests
cargo test --lib

# Run specific module tests
cargo test --lib -- events::
cargo test --lib -- rules::
cargo test --lib -- alerting::
cargo test --lib -- sniff::

💡 Usage Examples

Example 1: Detect Suspicious Syscalls

use stackdog::{RuleEngine, SyscallEvent, SyscallType};
use stackdog::rules::builtin::SyscallBlocklistRule;

let mut engine = RuleEngine::new();
engine.register_rule(Box::new(SyscallBlocklistRule::new(
    vec![SyscallType::Ptrace, SyscallType::Setuid]
)));

let event = SyscallEvent::new(
    1234, 1000, SyscallType::Ptrace, Utc::now()
);

let results = engine.evaluate(&event);
if results.iter().any(|r| r.is_match()) {
    println!("⚠️ Suspicious syscall detected!");
}

Example 2: Container Quarantine

use stackdog::QuarantineManager;

let mut quarantine = QuarantineManager::new()?;

// Quarantine compromised container
quarantine.quarantine("container_abc123")?;

// Check quarantine status
let state = quarantine.get_state("container_abc123");
println!("Container state: {:?}", state);

// Release after investigation
quarantine.release("container_abc123")?;

Example 3: Multi-Event Pattern Detection

use stackdog::{SignatureMatcher, PatternMatch, SyscallType};

let mut matcher = SignatureMatcher::new();

// Detect: execve followed by ptrace (suspicious)
matcher.add_pattern(
    PatternMatch::new()
        .with_syscall(SyscallType::Execve)
        .then_syscall(SyscallType::Ptrace)
        .within_seconds(60)
);

let result = matcher.match_sequence(&events);
if result.is_match() {
    println!("⚠️ Suspicious pattern detected!");
}

More Examples

See examples/usage_examples.rs for complete working examples.

Run examples:

cargo run --example usage_examples

📚 Documentation

Document Description
DEVELOPMENT.md Complete development plan (18 weeks)
TESTING.md Testing guide and infrastructure
TODO.md Task tracking and roadmap
CHANGELOG.md Version history
CONTRIBUTING.md Contribution guidelines
STATUS.md Current implementation status

API Documentation

# Generate docs
cargo doc --open

# View online (after release)
# https://docs.rs/stackdog

🛠️ Development

Project Structure

stackdog/
├── src/
│   ├── cli.rs           # Clap CLI (serve/sniff subcommands)
│   ├── events/          # Event types & validation
│   ├── rules/           # Rule engine & signatures
│   ├── alerting/        # Alerts & notifications
│   ├── firewall/        # nftables/iptables
│   ├── collectors/      # eBPF collectors
│   ├── sniff/           # Log sniffing & AI analysis
│   │   ├── config.rs    # SniffConfig (env + CLI)
│   │   ├── discovery.rs # Log source auto-discovery
│   │   ├── reader.rs    # File/Docker/Journald readers
│   │   ├── analyzer.rs  # AI summarization (OpenAI + pattern)
│   │   ├── consumer.rs  # zstd compression, dedup, purge
│   │   └── reporter.rs  # Alert routing
│   ├── api/             # REST API endpoints
│   ├── database/        # SQLite + repositories
│   ├── ml/              # ML infrastructure
│   └── config/          # Configuration
├── examples/            # Usage examples
├── tests/               # Integration tests
├── benches/             # Performance benchmarks
├── ebpf/                # eBPF programs
└── docs/                # Documentation

Development Workflow

# 1. Clone and setup
git clone https://github.com/trydirect/stackdog
cd stackdog
cp .env.sample .env

# 2. Build
cargo build

# 3. Run tests
cargo test --lib

# 4. Run example
cargo run --example usage_examples

# 5. Check code quality
cargo fmt --all -- --check
cargo clippy --all

Running on Linux

For full eBPF and firewall functionality:

# Requires root for eBPF
sudo cargo test --lib -- firewall::

# Check eBPF support
bpftool version
uname -r  # Should be 4.19+

🤝 Contributing

We welcome contributions! See CONTRIBUTING.md for guidelines.

Quick Start for Contributors

# Fork and clone
git clone https://github.com/YOUR_USERNAME/stackdog
cd stackdog

# Create branch
git checkout -b feature/my-feature

# Make changes, run tests
cargo test --lib

# Commit and push
git commit -m "Add my feature"
git push origin feature/my-feature

Good First Issues

Look for issues labeled:

  • 🟢 good first issue - Easy tasks for newcomers
  • 🟡 help wanted - Need community help
  • 🔵 documentation - Improve docs

📊 Project Status

Current Phase: Phase 2 - Detection & Response

Phase Status Progress
Phase 1: Foundation ✅ Complete 100%
Phase 2: Detection & Response 🚧 In Progress 60%
Phase 3: ML & Automation ⏳ Pending 0%
Phase 4: Web Dashboard ⏳ Pending 0%

Completed Tasks

  • ✅ Project structure (TASK-001)
  • ✅ Event types (TASK-002)
  • ✅ eBPF infrastructure (TASK-003)
  • ✅ Event enrichment (TASK-004)
  • ✅ Rule engine (TASK-005)
  • ✅ Signature detection (TASK-006)
  • ✅ Alert system (TASK-007)
  • ✅ Firewall integration (TASK-008)
  • ✅ Log sniffing & AI analysis (TASK-009)

Upcoming Tasks

  • ⏳ ML anomaly detection (TASK-010)
  • ⏳ Web dashboard (TASK-011)
  • ⏳ Kubernetes support (BACKLOG)

📜 License

This project is licensed under the MIT License.

Copyright (c) 2026 Vasili Pascal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software...

🙏 Acknowledgments

Inspired By

  • Falco - Cloud-native runtime security
  • Sysdig - System visibility

Technologies


📬 Contact


Built with ❤️ using Rust

About

Security platform for Docker Containers & Linux Servers in Rust

Resources

Code of conduct

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages