1 stable release
Uses new Rust 2024
| 4.4.0 | Apr 18, 2026 |
|---|
#611 in Network programming
62KB
1.5K
SLoC
nftguard
Atomic nftables ruleset versioning with rollback — invisible firewall guardian.
nftguard snapshots your nftables configuration every time you apply changes, compares rule fingerprints to detect drift, and lets you rollback to any previous state instantly. It runs as a transparent wrapper around nft and a systemd boot service, so your firewall is always versioned — without changing your workflow.
Features
- Atomic snapshots — JSON snapshots with SHA-256 checksums, metadata, and per-rule fingerprints
- Circular buffer — 100-slot ring buffer, oldest snapshots rotate out automatically
- Fingerprint diffing — normalized rule comparison detects semantic changes (ignores counters, handles)
- Retention guard — rejects bulk changes below 60% rule retention (prevents accidental wipes)
- Safe hot-reload —
hot-applyvalidates syntax, shows diff, selectively flushes tables, then applies - Boot protection —
ensurecommand loads the latest valid snapshot at boot; cascading fallback if corrupted - Rollback — restore any snapshot instantly:
nftguard rollback 42 - nft wrapper — transparent interception of
nft -fcalls (kube-proxy, scripts, manual) - Zero dependencies at runtime — single static binary, no daemons, no databases
Quick Start
Install from crates.io
cargo install nftguard
Install from source
git clone https://github.com/OnCeUponTry/nftguard.git
cd nftguard
cargo build --release
sudo install -m 755 target/release/nftguard /usr/local/sbin/nftguard
First use
# Apply your current nftables conf and create the first snapshot
sudo nftguard hot-apply /etc/nftables.conf
# List snapshots
sudo nftguard list
# Check kernel state
sudo nftguard status
# Rollback to the previous snapshot
sudo nftguard rollback
How It Works
┌──────────────┐
/etc/nftables.conf │ Your rules │ ◄── You edit this
└──────┬───────┘
│
nftguard hot-apply
│
┌──────▼───────┐
│ Syntax OK? │──No──► REJECT (kernel unchanged)
└──────┬───────┘
│ Yes
┌──────▼───────┐
│ Diff + show │ fingerprint comparison
└──────┬───────┘
│
┌──────▼───────┐
│ Selective │ flush only tables in conf
│ flush │ (preserves DROP policies)
└──────┬───────┘
│
┌──────▼───────┐
│ nft -f apply │──► Kernel updated
└──────┬───────┘
│
┌──────▼───────┐
│ Snapshot │──► /var/lib/nftguard/snapshot-N.json
└──────────────┘
Boot flow (ensure)
- If kernel already has rules → snapshot current state, done
- If kernel is empty → load latest snapshot
- If latest fails → try previous snapshots (circular)
- If all snapshots fail → try conf file
- If conf fails → try
/etc/nftables.conf - If everything fails → CRITICAL, exit 1
The boot service runs before network-pre.target, so your firewall is up before any interface.
Commands
| Command | Description |
|---|---|
hot-apply [conf] |
Recommended. Validate → diff → selective flush → apply → snapshot |
auto [conf] |
Automatic mode for nft wrapper. Applies if retention ≥ 60% |
ensure |
Boot-only. Loads latest valid snapshot into empty kernel |
rollback [N] |
Restore snapshot N (or previous if no N given) |
compare [N] [M] |
Compare snapshots or snapshot vs conf file |
list |
List all snapshots with timestamps, rule counts, hashes |
status |
Show kernel state: tables, chains, latest snapshot info |
config |
Show active configuration (paths, limits) |
--version |
Show version |
Configuration
Create /etc/nftguard/config (optional):
# Path to your nftables configuration file
conf_path=/etc/nftables.conf
If no config exists, nftguard auto-detects from common locations.
Default paths
| Path | Purpose |
|---|---|
/etc/nftguard/config |
Configuration file |
/var/lib/nftguard/ |
Snapshot storage (JSON) |
/var/log/nftguard/ |
Log files |
/usr/local/sbin/nftguard |
Binary |
Systemd Integration
Install the boot service to protect your firewall across reboots:
sudo cp systemd/nftguard.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable nftguard.service
The service runs nftguard ensure before networking starts, guaranteeing your firewall rules are loaded even after crashes or failed updates.
nft Wrapper (Optional)
You can install nftguard as a transparent wrapper for nft -f:
# Create wrapper at /usr/local/sbin/nft (takes precedence over /usr/sbin/nft)
sudo tee /usr/local/sbin/nft << 'WRAPPER'
#!/bin/bash
# nftguard transparent wrapper
NFT_REAL="/usr/sbin/nft"
case "$*" in
*-c*) exec "$NFT_REAL" "$@" ;; # syntax check: pass through
*-f\ -) nftguard auto_stdin ;; # stdin: ephemeral (no snapshot)
*-f\ *) conf="${*##*-f }"; conf="${conf%% *}"; nftguard auto "$conf" ;;
*) exec "$NFT_REAL" "$@" ;; # everything else: pass through
esac
WRAPPER
sudo chmod +x /usr/local/sbin/nft
This automatically versions every nft -f call from any source (scripts, kube-proxy, manual).
Snapshots
Each snapshot is a JSON file containing:
{
"meta": {
"timestamp": "2025-01-15 14:30:22",
"sha256": "a1b2c3...",
"line_count": 142,
"chain_count": 8,
"rule_count": 67,
"table_names": ["inet filter", "ip nat"]
},
"fingerprints": [
{
"hash": "d4e5f6...",
"original": "tcp dport 22 accept",
"chain": "input",
"table": "inet filter"
}
],
"content": "table inet filter {\n chain input {\n ..."
}
Requirements
- Linux with nftables (
nftv0.9.3+) - Root privileges (firewall management requires it)
- Rust 1.70+ (build only)
License
Licensed under the Apache License, Version 2.0.
Copyright 2025 OnCeUponTry.
Dependencies
~2–3.5MB
~72K SLoC