Skip to content

copyleftdev/plumbum

Plumbum

Deterministic DNS TXT tunnel detection.

It does not guess. It computes.
It does not alert. It explains.

Rust License: MIT Build Crates


Plumbum computes composite anomaly scores from PCAP and Zeek dns.log files, persists results in SQLite, and produces fully decomposable explanations for every finding. No machine learning. No black boxes. Every score is a deterministic function of six inspectable features.

Install

cargo build --release

Two binaries are produced in target/release/:

Binary Purpose
plumbum CLI for analysis, scoring, and export
plumbum-mcp MCP server over stdio JSON-RPC

Quick Start

plumbum init                                    # create .plumbum/ working directory
plumbum validate capture.pcap                   # check file structure
plumbum plan capture.pcap                       # dry-run: preview scope
plumbum apply capture.pcap --c2-domains evil.tk # full analysis
plumbum show evil.tk                            # inspect a domain
plumbum explain evil.tk                         # score decomposition
plumbum export --format json                    # export findings
plumbum dashboard                               # interactive TUI
plumbum stream -i eth0                          # live capture + scoring
Example output
Plumbum Findings:

CRITICAL   94.4  evil.tk

Artifacts written to .plumbum/plumbum.db (run #1)

Summary: 1 domains scored, 1 CRITICAL, 0 HIGH, 0 MEDIUM
Domain: evil.tk
Score:  94.4 (CRITICAL)

Components:
  entropy                norm=0.000  w=0.1500  contrib=0.000  ( 0.0%)
  periodicity            norm=1.000  w=0.1000  contrib=0.100  ( 3.7%)
  volume                 norm=1.000  w=0.2500  contrib=0.250  ( 9.3%)
  length                 norm=1.000  w=0.1000  contrib=0.100  ( 3.7%)
  client_rarity          norm=1.000  w=1.8000  contrib=1.800  (66.7%)
  subdomain_diversity    norm=1.000  w=0.3000  contrib=0.300  (11.1%)

Commands

Command Description
init Create .plumbum/ directory with config and database
validate Parse inputs and report record counts
plan Dry-run showing what will be analyzed
apply Full analysis: parse, extract, score, persist
show Display a domain's score and raw features
explain Detailed score decomposition with per-feature contributions
export Export as JSON, CSV, or Sigma rule
dashboard Interactive TUI dashboard
stream Live capture DNS from a network interface and score in real time
version Print version

Scoring Model

Plumbum uses a weighted linear model over six normalized features:

Feature Signal Range
Entropy Shannon entropy of TXT content 0 = low, 1 = high
Periodicity Regularity of query timing 0 = irregular, 1 = clockwork
Volume Query count per parent domain 0 = quiet, 1 = loudest in corpus
Length Mean TXT response length 0 = short, 1 = longest in corpus
Client Rarity Inverse of unique source IPs 1 = single host (most suspicious)
Subdomain Diversity Unique subdomains per parent 0 = few, 1 = most in corpus

Weight Presets

Preset Description
default Balanced equal-ish weights
optimized Tuned via simulated annealing on labeled data
regularized SA-informed with enforced feature diversity (default)

Severity Thresholds

Severity Score
CRITICAL ≥ 80
HIGH ≥ 60
MEDIUM ≥ 40
LOW < 40

Supported Formats

Format Details
PCAP Classic libpcap — both endianness, micro/nanosecond timestamps
pcapng SHB / IDB / EPB blocks
Zeek dns.log Tab-separated with standard #fields headers
Link layers Ethernet (type 1), Linux SLL (type 113)

Configuration

plumbum init writes .plumbum/config.hcl:

analysis {
  weight_preset              = "regularized"
  entropy_weight             = 0.15
  periodicity_weight         = 0.10
  volume_weight              = 0.25
  length_weight              = 0.10
  client_rarity_weight       = 1.80
  subdomain_diversity_weight = 0.30
}

thresholds {
  critical = 80
  high     = 60
  medium   = 40
}

MCP Server

Plumbum exposes analysis results via the Model Context Protocol over stdio JSON-RPC:

plumbum-mcp
Type Endpoint Description
Resource plumbum://domains Scored domains from the latest run
Resource plumbum://status Analysis state and run summary
Tool plumbum_explain Score decomposition for a domain
Tool plumbum_query Query scored domains with filters

Architecture

┌─────────────────────────────────────────────────────────┐
│                      plumbum-cli                        │
│         init validate plan apply stream                  │
│            show explain export dashboard                 │
├────────────┬────────────┬───────────────┬───────────────┤
│plumbum-tui │plumbum-mcp │plumbum-config │plumbum-stream │
│  ratatui   │ stdio rpc  │  HCL parser   │ live capture  │
├────────────┴────────────┴───────────────┴───────────────┤
│            plumbum-store                │ plumbum-score  │
│    SQLite · WAL · batch ingest          │  weights       │
│    schema · queries · artifacts         │  normalize     │
│                                         │  composite     │
│                                         │  explain       │
├─────────────────────────────────────────┴───────────────┤
│                     plumbum-core                        │
│          dns types · features · pcap · zeek             │
└─────────────────────────────────────────────────────────┘
Crate Role
plumbum-core DNS types, PCAP/pcapng + Zeek parsers, feature extraction
plumbum-score Composite scoring, weight presets, normalization, explain
plumbum-store SQLite schema, batch ingest, prepared queries, export artifacts
plumbum-config HCL config parser, types, defaults
plumbum-cli CLI binary (plumbum)
plumbum-tui Interactive dashboard with ratatui
plumbum-mcp MCP server binary (plumbum-mcp)
plumbum-stream Live network capture, sliding window accumulator, real-time scoring

Live Streaming

Capture DNS traffic directly from a network interface and score domains in real time:

# Stream from eth0, 60s windows, alert on score >= 40
sudo plumbum stream -i eth0 --window 60 --threshold 40

# List available interfaces
plumbum stream --list-interfaces

# Pipe to jq for filtering
sudo plumbum stream -i any | jq 'select(.severity == "CRITICAL")'

Output is newline-delimited JSON — one alert per domain per window:

{"domain":"evil.tk","score":94.4,"severity":"CRITICAL","query_count":1847,"client_count":1,"subdomain_count":1234,"mean_entropy":4.21,"cv":1.80,"mean_txt_length":189.0,"window_secs":60.0,"is_c2":true}

Requires: libpcap-dev (Linux), Npcap (Windows), built-in on macOS.
Privileges: root or CAP_NET_RAW for raw socket access.

License

This project is licensed under the MIT License.

About

Deterministic DNS TXT tunnel detection. Composite anomaly scoring over PCAP and Zeek logs — every score is a decomposable function of six inspectable features. No ML. No black boxes. It computes. It explains.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages