Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
fortify-xdp
A high-performance XDP (eXpress Data Path) firewall written in Rust with a real-time TUI monitoring interface.
Features
- High-performance packet filtering via eBPF/XDP attached at the earliest ingress point
- Instant blocklist — dynamically ban/unban IPs via CLI with immediate effect (no restart)
- Custom exact-match rules — filter on IPv4 src/dst IP, protocol, and ports with Drop/Pass/Log actions
- IP range dropping — CIDR-based blocks (e.g.
192.168.0.0/16) using an LPM trie - Rate limiting — both flow-based (5-tuple) and IP-based token-bucket rate limits
- Temporary bans — auto-ban IPs or flows that exceed rate limits for a configurable duration
- Logging system — stream matched events to userspace via a BPF ring buffer
- Real-time monitoring — terminal UI showing live counters, active rules, blocklist, and recent hits
Architecture
xdp-firewall/ Userspace CLI + TUI (aya, clap, ratatui, tokio)
xdp-firewall-ebpf/ eBPF/XDP kernel program (aya-ebpf)
xdp-firewall-common/ Shared types between user/kernel space
xtask/ Build helper for eBPF compilation
scripts/setup-veth.sh Virtual veth pair for safe local testing
eBPF Maps
| Map | Type | Purpose |
|---|---|---|
BLOCKLIST |
HashMap<u32, u64> |
IP → expiry timestamp |
IP_RANGES |
LpmTrie<u32, u8> |
CIDR prefix → action |
RULES |
HashMap<RuleKey, RuleValue> |
Exact-match rules |
RATE_LIMIT_STATE |
HashMap<RateLimitKey, RateLimitState> |
Token bucket state |
RATE_LIMIT_CONFIG |
HashMap<u8, RateLimitConfig> |
Global rate limit config |
STATS |
HashMap<u32, Stats> |
Per-rule packet/byte counters |
GLOBAL_STATS |
Array<Stats, 1> |
Aggregated counters |
EVENTS |
RingBuf |
Event stream to userspace |
Packet Flow
- Parse Ethernet → IPv4 → TCP/UDP headers
- Blocklist check →
XDP_DROPif IP is banned and not expired - IP range check →
XDP_DROPif source IP matches a CIDR range with drop action - Rate limit check → token bucket; if exceeded, drop and optionally temp-ban
- Rule check → exact-match lookup; apply Drop/Pass/Log
- Default →
XDP_PASS
Prerequisites
- Linux kernel with BPF and XDP support
- Rust toolchain (stable + nightly for eBPF)
bpf-linkerclang/llvm- Root privileges for loading XDP programs and creating BPF maps
Install nightly and bpf-linker:
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
cargo install bpf-linker
Build
cargo run -p xtask -- build-ebpf
cargo build --release -p xdp-firewall
Quick Start
Create a virtual veth pair for safe local testing:
sudo ./scripts/setup-veth.sh
This creates veth0 (host, 10.200.1.1) and veth1 (in testns, 10.200.1.2).
Load the XDP firewall on veth0:
sudo ./target/release/xdp-firewall load --iface veth0
CLI Usage
Blocklist
sudo ./target/release/xdp-firewall block --iface veth0 --ip 10.200.1.2
sudo ./target/release/xdp-firewall unblock --iface veth0 --ip 10.200.1.2
Block with a temporary duration (seconds):
sudo ./target/release/xdp-firewall block --iface veth0 --ip 10.200.1.2 --duration 300
Rules
Add a rule to drop UDP traffic to port 9999:
sudo ./target/release/xdp-firewall add-rule \
--iface veth0 \
--src-ip 0.0.0.0 \
--dst-ip 10.200.1.1 \
--proto 17 \
--src-port 0 \
--dst-port 9999 \
--action drop
List active rules with live hit counts:
sudo ./target/release/xdp-firewall list-rules --iface veth0
Delete a rule by ID:
sudo ./target/release/xdp-firewall del-rule --iface veth0 --id 0
Use 0.0.0.0 for wildcard IPs and 0 for wildcard ports/protocols.
IP Ranges
sudo ./target/release/xdp-firewall add-range --iface veth0 --cidr 192.168.0.0/16 --action drop
sudo ./target/release/xdp-firewall del-range --iface veth0 --cidr 192.168.0.0/16
Rate Limiting
Set an IP-based rate limit of 100 pps with burst 200; temp-ban after 10 violations for 60 seconds:
sudo ./target/release/xdp-firewall set-ratelimit \
--iface veth0 \
--rate 100 \
--burst 200 \
--ban-threshold 10 \
--ban-duration 60 \
--mode ip
Use --mode flow for 5-tuple flow-based rate limiting.
Monitor (TUI)
sudo ./target/release/xdp-firewall monitor --iface veth0
Keybindings
| Key | Action |
|---|---|
Tab |
Switch panes (Rules → Blocklist → Logs) |
↑ / ↓ |
Navigate lists |
b |
Block IP dialog |
u |
Unblock selected IP |
a |
Add rule dialog |
d |
Delete selected rule |
q |
Quit |
Unload
sudo ./target/release/xdp-firewall unload --iface veth0
Development
The project uses a Cargo workspace. The eBPF crate is compiled with nightly using bpf-linker:
# Build eBPF only
cargo run -p xtask -- build-ebpf
# Build userspace only
cargo build --release -p xdp-firewall
License
MIT