A lightweight, high-performance network security tool built in Rust.
Captures live network traffic, filters packets against whitelist/blacklist rules,
evaluates a composable condition DSL, and takes actions (block, log, alert) in real time.
- Real-time packet capture via libpcap
- Whitelist / Blacklist with CIDR, port, and protocol support
- Composable rule engine with AND / OR / NOT conditions
- IP blocking via iptables (Linux) or pf (macOS)
- Block deduplication and alert rate limiting
- Live monitor mode (tcpdump-style packet viewer)
- Structured logging (JSON) to stdout and/or file
- YAML configuration with validation
- Async pipeline (Tokio) with zero-copy packet parsing
- Rust 1.70+
- libpcap (
libpcap-devon Linux, included in Xcode CLI tools on macOS) - Root/sudo for packet capture
libpcap must be installed before building:
# Ubuntu / Debian
sudo apt install libpcap-dev
# Fedora / RHEL
sudo dnf install libpcap-devel
# macOS (included with Xcode CLI tools)
xcode-select --installgit clone https://github.com/muratdemirci/warden.git
cd warden
cargo build --releaseThe binary will be at target/release/warden.
No installation needed. Use the full path to the binary:
sudo ./target/release/warden --monitor -i en0
sudo ./target/release/warden -i en0 --dry-runThis installs the binary to ~/.cargo/bin/, which is typically already in your PATH:
cargo install --path .
sudo warden --monitor -i en0To uninstall later: cargo uninstall warden
Copy the binary to a system directory so all users can run it:
cargo build --release
sudo cp target/release/warden /usr/local/bin/Now warden works from anywhere:
sudo warden --monitor -i en0To uninstall later: sudo rm /usr/local/bin/warden
warden --version
warden --validate
warden --list-interfaces# 1. List available network interfaces
sudo warden --list-interfaces
# 2. Validate your config
warden --validate
# 3. Monitor live traffic (no rules, just watch packets)
sudo warden --monitor -i en0
# 4. Run with full pipeline (filter + rules + actions)
sudo warden -i en0
# 5. Dry run (log actions without executing firewall commands)
sudo warden -i en0 --dry-runMonitor mode prints every captured packet to stdout in a table format, bypassing all filter and rule logic. Useful for inspecting traffic before writing rules.
# Watch all traffic on en0
sudo warden --monitor -i en0
# Watch only TCP traffic
sudo warden --monitor -i en0 -f "tcp"
# Watch only HTTPS, limit to 20 packets
sudo warden --monitor -i en0 -f "tcp port 443" --monitor-count 20
# Watch DNS traffic
sudo warden --monitor -i en0 -f "udp port 53" --monitor-count 10Output:
monitoring en0 — press Ctrl-C to stop
# PROTO SOURCE DESTINATION TTL LEN FLAGS
------------------------------------------------------------------------------------------
1 TCP 192.168.0.101:55432 142.250.187.206:443 64 66 [SA]
2 TCP 192.168.0.101:55432 142.250.187.206:443 64 54 [A]
3 UDP 192.168.0.101:53045 192.168.0.1:53 64 72
4 TCP 142.250.187.206:443 192.168.0.101:55432 112 1452 [A]
5 TCP 192.168.0.101:55432 142.250.187.206:443 64 54 [A]
captured 5 packets, stopping.
─── monitor summary ───
IPv4 packets: 5
non-IPv4 skipped: 3
Columns: packet number, protocol (TCP/UDP/ICMP), source IP:port, destination IP:port, TTL, frame length in bytes, TCP flags (S=SYN, A=ACK, F=FIN, R=RST, P=PSH, U=URG).
Warden uses a YAML config file (default: config.yaml).
interface: en0interface: eth0
filter:
whitelist:
- "127.0.0.1"
- ip: "192.168.1.0/24"
blacklist:
- "10.0.0.66"
- ip: "0.0.0.0/0"
port: 22
protocol: "tcp"
- ip: "172.16.0.0/12"
protocol: "udp"
rules:
# Block SSH from untrusted sources
- name: "block untrusted ssh"
priority: 10
condition:
all:
- protocol: "tcp"
- dst_port: 22
- not:
src_ip: "192.168.1.0/24"
action: block
# Alert on SYN scans to well-known ports
- name: "syn scan alert"
priority: 20
condition:
all:
- protocol: "tcp"
- tcp_flags: ["syn"]
- dst_port: "1-1023"
action: alert
# Log HTTP/HTTPS traffic
- name: "log web traffic"
priority: 50
condition:
all:
- protocol: "tcp"
- any:
- dst_port: 80
- dst_port: 443
action: log
logging:
level: "info"
json: false
# file: "logs/warden.log"Filters run before rules for fast early-exit. Whitelist takes priority over blacklist.
# Bare IP string
- "192.168.1.1"
# CIDR notation
- ip: "10.0.0.0/8"
# IP + port + protocol
- ip: "0.0.0.0/0"
port: 22
protocol: "tcp"Conditions are composable with all (AND), any (OR), and not (NOT):
| Condition | Example | Description |
|---|---|---|
src_ip |
src_ip: "10.0.0.0/8" |
Source IP or CIDR |
dst_ip |
dst_ip: "192.168.1.1" |
Destination IP or CIDR |
src_port |
src_port: 53 |
Source port (single or range) |
dst_port |
dst_port: "1024-65535" |
Destination port (single or range) |
protocol |
protocol: "tcp" |
tcp, udp, or icmp |
tcp_flags |
tcp_flags: ["syn", "ack"] |
Required TCP flags |
all |
all: [...] |
All children must match |
any |
any: [...] |
At least one child must match |
not |
not: { src_ip: "..." } |
Invert the child condition |
| Action | Description |
|---|---|
block |
Adds a firewall rule to drop traffic from the source IP |
log |
Logs the packet with full metadata |
alert |
Logs a warning (rate-limited per rule+IP, 60s cooldown) |
logging:
level: "info" # error, warn, info, debug, trace
json: false # true = JSON output to stdout
file: "logs/warden.log" # optional, always JSONOverride with RUST_LOG env var for module-level filtering:
RUST_LOG=warden=debug,pcap=warn sudo warden -i en0warden [OPTIONS]
Options:
-c, --config <PATH> Config file [default: config.yaml]
-i, --interface <NAME> Network interface
-f, --bpf-filter <EXPR> BPF filter (e.g., "tcp port 80")
-v, --verbose Force DEBUG log level
--dry-run Log actions without executing them
--list-interfaces List network interfaces and exit
--validate Validate config and exit
--stats-interval <N> Stats reporting interval [default: 10000]
--monitor Live packet monitor mode
--monitor-count <N> Max packets in monitor mode [default: 0]
-h, --help Print help
-V, --version Print version
warden/
├── src/
│ ├── main.rs # CLI, async pipeline orchestration
│ ├── net.rs # Shared IpNet (CIDR matching)
│ ├── capture/mod.rs # pcap packet capture
│ ├── parser/mod.rs # Ethernet/IPv4/TCP/UDP frame parsing
│ ├── filter/mod.rs # Compiled whitelist/blacklist
│ ├── rules/mod.rs # Composable condition DSL engine
│ ├── actions/mod.rs # Block/Log/Alert with dedup + rate limiting
│ ├── config/mod.rs # YAML config loader + validation
│ └── logger/mod.rs # Structured logging (stdout + file)
├── config.yaml
├── Cargo.toml
└── docs/
└── DESIGN.md
[Network Interface]
|
Capture Task (pcap, blocking thread)
|
mpsc channel (4096 buffer)
|
Processing Task (async)
|
Parse ──> Filter ──> Rules ──> Actions ──> Log
- Capture — pcap runs in a dedicated blocking thread, raw packets are sent over an async mpsc channel.
- Parse — zero-copy parsing of Ethernet + IPv4 + TCP/UDP headers. Non-IPv4 frames are counted and skipped.
- Filter — pre-compiled CIDR bitmasks for O(1) matching per entry. Whitelist hit = skip blacklist entirely.
- Rules — composable condition tree evaluated in priority order. First match wins.
- Actions — block (with dedup), log, or alert (with 60s rate limiting per rule+IP).
cargo testMIT
