Skip to content

Latest commit

 

History

History
536 lines (394 loc) · 15.1 KB

USAGE.md

File metadata and controls

536 lines (394 loc) · 15.1 KB

Usage Guide

Day-to-day operation of Heimdall. Covers the deployment lifecycle from learning through enforcement, CLI commands, TUI dashboard, process tagging, SIEM integration, and troubleshooting.

Table of Contents


Deployment Lifecycle

Heimdall is designed to be deployed in phases. Do not skip steps.

Phase 1: Learning (Days 1-30+)

The daemon observes all filesystem writes and builds per-process, per-directory baselines. No alerts are generated. No processes are affected.

# Confirm you're in learning mode
heimdall mode
# → Current mode: LEARNING

# Watch events flow in (optional, just to verify it's working)
heimdall watch

What's happening: Every write event builds an entry in the SQLite baseline database. The EMA (Exponential Moving Average) needs at least min_samples (default: 100) observations per process/directory pair before the baseline is considered valid. For most hospital servers, 30 days captures daily/weekly patterns in backup jobs, log rotation, database maintenance, etc.

When to move on: When baseline counts are in the hundreds or thousands for your key processes. Check with:

heimdall status --verbose
# Look at "Baselines tracked" — should be non-trivial

Phase 2: Monitoring (Days 30+)

Switch to monitoring mode. The daemon now compares live writes against baselines and generates alerts, but does not stop any processes.

sudo heimdall mode monitoring

What to do in this phase:

  1. Watch the alert stream:

    heimdall watch
    # or
    heimdall-tui
  2. Review recent alerts:

    heimdall logs --limit 50
  3. Identify false positives. Common sources:

    • Backup software (writes compressed/encrypted data — high entropy is normal for it)
    • Database engines (WAL writes can spike entropy during checkpoints)
    • Package updates (new binaries have different entropy profiles)
  4. Tag processes to set their policy:

    # Your backup software is not ransomware
    heimdall tag set bacula-fd trusted
    heimdall tag set /backup/ trusted
    
    # Your EHR database must never be interrupted
    heimdall tag set mysqld critical
    heimdall tag set postgres critical
  5. Tune thresholds if needed (edit /etc/heimdall/heimdall.toml):

    • Too many false positives → raise entropy_threshold (try 4.0 or 5.0)
    • Missing obvious anomalies → lower entropy_threshold (try 2.0)

When to move on: When the alert stream is clean — you understand every alert you're seeing and false positives are tagged appropriately.

Phase 3: Enforcing (Optional)

Switch to enforcing mode. The daemon now executes policy actions: freeze (SIGSTOP) or kill (SIGKILL) on processes that match the severity/tag policy matrix.

sudo heimdall mode enforcing

Before enabling enforcement, ensure you have:

  • Tagged every critical service as critical (these are never stopped)
  • Tagged trusted infrastructure as trusted (alert only)
  • Reviewed the policy matrix (see Process Tagging)
  • Tested with watched tags on non-critical services first
  • A way to quickly disable enforcement if something goes wrong:
    sudo heimdall mode monitoring

CLI Reference

All commands communicate with the running daemon via unix socket. The daemon must be running.

heimdall status

Show daemon status: mode, uptime, event count, baseline count, active alerts.

heimdall status            # Plain output
heimdall status --verbose  # Adds events/sec, raw uptime

heimdall logs

Show recent detection verdicts.

heimdall logs                     # Last 20 verdicts
heimdall logs --limit 100         # Last 100
heimdall logs --verbose           # Raw numerical data
heimdall logs --limit 50 --verbose

heimdall watch

Live-stream events from the daemon. Stays connected until Ctrl+C.

heimdall watch             # Plain English
heimdall watch --verbose   # Raw data

heimdall mode

Get or set the operating mode.

heimdall mode                    # Show current mode
sudo heimdall mode learning      # Switch to learning
sudo heimdall mode monitoring    # Switch to monitoring
sudo heimdall mode enforcing     # Switch to enforcing

Mode changes take effect immediately. No daemon restart required.

heimdall tag

Manage process and path tags.

# Set a tag
heimdall tag set <pattern> <tag>

# List all tags
heimdall tag list

Valid tags: critical, trusted, watched, untrusted

# Examples
heimdall tag set mysqld critical
heimdall tag set /opt/ehr/ critical
heimdall tag set /tmp/ watched
heimdall tag set suspicious-binary untrusted
heimdall tag list

Global Options

# Use a non-default socket path
heimdall --socket /path/to/heimdall.sock status

TUI Dashboard

heimdall-tui

# Custom socket
heimdall-tui --socket /path/to/heimdall.sock

The dashboard shows three sections:

  • Top bar: Connection status (green/red), operating mode, uptime, events/sec, total events, alert count
  • Event feed (left): Scrollable list of recent verdicts, color-coded by severity
  • Process leaderboard (right): Top 20 processes ranked by highest anomaly score

Keybindings

Key Action
q Quit
v Toggle verbose/plain English mode
m Cycle mode (learning → monitoring → enforcing → learning)
/ Enter filter mode — type to filter events by process name, path, or summary
Esc Cancel filter input
Enter Apply filter
Up/Down Scroll event feed
Home Jump to oldest event
End Jump to newest event

The TUI auto-reconnects if the daemon restarts. You'll see "DISCONNECTED" in red until the connection is restored.


Process Tagging

Tags determine what happens when Heimdall detects an anomaly from a specific process or path. In enforcing mode, the policy matrix is:

Tag Low Medium High Critical
critical alert alert alert alert
trusted alert alert alert alert
watched alert alert freeze freeze
untrusted alert alert freeze kill
  • Alert: Log the event, send to sinks. Process is not affected.
  • Freeze: Send SIGSTOP to the process. It pauses until manually resumed with kill -CONT <pid>.
  • Kill: Send SIGKILL to the process. It terminates immediately.

Before sending any signal, Heimdall verifies the PID still belongs to the expected process by checking /proc/<pid>/comm. If the PID has been reused by a different process, the signal is not sent.

Tagging Strategy for Hospitals

# === Life-critical / must never be interrupted ===
heimdall tag set mysqld critical
heimdall tag set postgres critical
heimdall tag set java critical              # EHR application server
heimdall tag set /opt/ehr/ critical         # All writes to EHR directories
heimdall tag set /data/pacs/ critical       # PACS imaging archive
heimdall tag set /data/dicom/ critical      # DICOM storage

# === Known infrastructure ===
heimdall tag set sshd trusted
heimdall tag set systemd-journald trusted
heimdall tag set rsyslogd trusted
heimdall tag set crond trusted
heimdall tag set bacula-fd trusted          # Backup agent
heimdall tag set /backup/ trusted           # Backup target directory

# === Recently deployed or updated software ===
heimdall tag set /opt/newapp/ watched

# Everything else defaults to "untrusted"

Pattern rules:

  • Patterns without / match process names exactly (e.g., mysqld)
  • Patterns ending with / match directory prefixes (e.g., /opt/ehr/ matches /opt/ehr/data/file.db)
  • Patterns without trailing / match exact paths only
  • Minimum pattern length is 2 characters

Reading Verdicts

Plain English Mode (default)

Designed for operators who don't need to understand entropy math:

14:23:01 [LOW]      mysqld writing to /var/lib/mysql/ibdata1 — normal behavior.
14:23:05 [MEDIUM]   java write pattern to /opt/ehr/logs/audit.log is slightly unusual. Confidence: moderate.
14:23:12 [CRITICAL] unknown_proc is writing scrambled data to /data/patient_records/db.mdf, this is highly unusual. Confidence: very high.
         Action: kill

The summary tells you: who is writing, where, and how concerned you should be.

Verbose Mode (--verbose or v key in TUI)

For engineers who want the raw data:

14:23:12 [CRITICAL] pid=6291 comm=unknown_proc path=/data/patient_records/db.mdf
         entropy=7.9312  deviation=14.2σ  freq_ratio=1.0x  anomaly=0.9847  size=65536B
         entropy=7.93 baseline_mean=4.12 baseline_stddev=0.27 deviation=14.2σ write_size=65536 freq_ratio=1.0x samples=4821
         Action: kill

Field reference:

Field Meaning
entropy Shannon entropy of the write buffer (0.0-8.0). >7.0 is suspicious.
deviation How many standard deviations from the baseline mean. Higher = more anomalous.
freq_ratio Write frequency compared to baseline. 5.0x = writing 5 times more often than normal.
anomaly Combined anomaly score (0.0-1.0). Weighted: 70% entropy, 30% frequency.
size Bytes written in this call.
baseline_mean The process's normal entropy for this directory.
baseline_stddev How much normal entropy varies for this process.
samples How many observations the baseline is built from. More = more reliable.

SIEM Integration

Heimdall outputs structured JSON to all configured sinks. Events are dispatched concurrently — a slow or unreachable SIEM never blocks detection.

JSON Event Format

Every event written to sinks is a serialized EntropyVerdict:

{
  "event": {
    "pid": 6291,
    "tgid": 6291,
    "comm": "suspicious",
    "path": "/data/records/file.dat",
    "write_size": 65536,
    "entropy": 7.93,
    "timestamp": "2026-02-10T14:23:12.456Z",
    "buffer_sample": [...]
  },
  "entropy_deviation": 14.2,
  "frequency_ratio": 1.0,
  "anomaly_score": 0.9847,
  "severity": "critical",
  "summary": "suspicious is writing scrambled data to /data/records/file.dat...",
  "detail": "entropy=7.93 baseline_mean=4.12 ...",
  "action_taken": "kill"
}

Splunk (HTTP Event Collector)

[[sinks]]
type = "http"
url = "https://splunk.hospital.local:8088/services/collector/event"

[sinks.headers]
Authorization = "Splunk your-hec-token-here"

Elasticsearch

[[sinks]]
type = "http"
url = "https://elastic.hospital.local:9200/heimdall-events/_doc"

[sinks.headers]
Authorization = "ApiKey your-api-key-here"

Syslog (UDP)

[[sinks]]
type = "syslog"
address = "udp://10.0.1.5:514"

Messages are sent as RFC 5424 structured data with the JSON verdict as the payload. Messages exceeding 65,000 bytes are truncated.

Multiple Sinks

You can configure any combination. All sinks receive every event:

[[sinks]]
type = "file"
path = "/var/log/heimdall/events.json"

[[sinks]]
type = "syslog"
address = "udp://siem.hospital.local:514"

[[sinks]]
type = "http"
url = "https://splunk.hospital.local:8088/services/collector/event"
[sinks.headers]
Authorization = "Splunk your-token"

Offline / Air-Gapped Operation

Heimdall is designed for environments with no external network access. This is the default — no configuration required.

What works without any network:

  • eBPF probes (kernel-level, no network)
  • Detection engine (local computation)
  • SQLite baselines (local file)
  • Unix socket IPC (local)
  • File sink (local disk)
  • CLI and TUI (connect via local socket)

What requires network (all optional):

  • Syslog sink (UDP to your local SIEM — internal network only)
  • HTTP sink (HTTPS to your local SIEM — internal network only)

What requires network at build time only:

  • cargo build fetches crates from crates.io — use cargo vendor for air-gapped builds (see INSTALL.md)

There is no:

  • Telemetry
  • Cloud connectivity
  • Signature database updates
  • License server
  • Phone-home of any kind

The detection model is statistical (per-machine baselines), not signature-based. It never needs to download anything. Once installed, it runs indefinitely on its own.


Troubleshooting

"Socket not found. Is the Heimdall daemon running?"

The CLI/TUI can't find the daemon socket.

# Check if daemon is running
sudo systemctl status heimdall

# Check socket exists
ls -la /run/heimdall/heimdall.sock

# If the directory doesn't exist
sudo mkdir -p /run/heimdall
sudo systemctl restart heimdall

Daemon won't start: "config file is world-writable"

Heimdall refuses to start if anyone can edit the config.

sudo chmod 640 /etc/heimdall/heimdall.toml
sudo chown root:root /etc/heimdall/heimdall.toml

Daemon won't start: config validation error

Check the error message in the journal:

sudo journalctl -u heimdall --no-pager | tail -20

Common issues:

  • alpha must be in (0.0, 1.0) — check engine.alpha is between 0 and 1
  • entropy_threshold must be > 0.0 — can't be zero or negative
  • min_samples must be >= 10 — needs at least 10
  • sample_size must be <= 65536 — max 64KB

Too many false positives

  1. Check what's triggering alerts:

    heimdall logs --limit 50 --verbose
  2. Tag known-good processes:

    heimdall tag set backup-process trusted
    heimdall tag set /backup/ trusted
  3. Raise the entropy threshold in /etc/heimdall/heimdall.toml:

    entropy_threshold = 4.0  # or 5.0 for conservative
  4. Restart the daemon:

    sudo systemctl restart heimdall

No events appearing

If heimdall status shows Events processed: 0 after the daemon has been running:

  • The eBPF probes may not be attached (check journalctl -u heimdall for probe loading errors)
  • Your kernel may not support the required eBPF features — verify kernel 5.8+ and BTF support

Baselines look wrong after software update

A major software update changes write patterns. Options:

  1. Temporarily switch to learning mode to absorb the new patterns:
    sudo heimdall mode learning
    # Wait a few hours/days
    sudo heimdall mode monitoring
  2. The EMA will naturally adapt (alpha=0.05 means ~5% of each new observation is absorbed), but this takes hundreds of observations.

Process was incorrectly frozen (SIGSTOP)

Resume it immediately:

# Find the PID
ps aux | grep <process-name>

# Resume it
kill -CONT <pid>

# Then tag it to prevent future freezes
heimdall tag set <process-name> critical

Disk filling up from event log

The file sink at /var/log/heimdall/events.json grows indefinitely. Set up log rotation:

# /etc/logrotate.d/heimdall
sudo tee /etc/logrotate.d/heimdall << 'EOF'
/var/log/heimdall/events.json {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}
EOF