DEV Community

CARLOS ENRIQUE CASTRO LAZARO
CARLOS ENRIQUE CASTRO LAZARO

Posted on

I built nftguard: atomic nftables versioning with instant rollback

I manage multiple Linux servers. Each one has its own nftables firewall config — some with 50 rules, some with 200+. And for years, my "versioning system" was a mix of .bak files, commented-out lines, and the vague hope that I'd remember what changed last Tuesday.

Then one night I fat-fingered a flush command and locked myself out of a production box via SSH. Recovery took 40 minutes. The fix took 10 seconds — I just needed the previous ruleset. But I didn't have it.

So I built nftguard.

What makes it different

There's nothing else like this. Seriously — I searched. There are iptables backup scripts. There are Ansible playbooks that template firewall configs. But there is zero tooling for atomic nftables versioning with rollback. nftguard is the first.

Here's what it actually does that nothing else can:

1. SHA-256 fingerprinted rule tracking

Every rule gets individually hashed after normalization (counters and handles stripped). This means nftguard detects semantic changes — not just text diffs. If you reorder rules but the logic is identical, it knows.

2. Retention guard (the "oops" detector)

If your new config would delete more than 40% of existing rules, nftguard stops and asks. This catches the most common disaster: accidentally applying a minimal test config over your production ruleset.

3. Selective table flush

Most tools do nft flush ruleset then nft -f config. That creates a window — maybe 50ms, maybe 500ms — where your firewall has zero rules. nftguard only flushes the tables that appear in your new config, preserving everything else. No gap.

4. Cascading boot recovery

At boot, before any network interface comes up, nftguard loads your firewall. If the latest snapshot is corrupted, it tries the previous one. Then the one before that. Then the conf file. Five layers of fallback before giving up.

5. Transparent nft wrapper

Install it as /usr/local/sbin/nft and every nft -f call from any source — scripts, kube-proxy, manual — gets versioned automatically. Nothing changes in your workflow.

How it looks in practice

# Apply config with full safety net
$ sudo nftguard hot-apply /etc/nftables.conf
[nftguard] Syntax OK
[nftguard] 142 rules, 8 chains, 2 tables
[nftguard] Diff: +3 new, -1 removed, 138 unchanged
[nftguard] Retention: 97.2% (above 60% threshold)
[nftguard] Snapshot #47 saved

# Oh no, something broke
$ sudo nftguard rollback
[nftguard] Restored snapshot #46 (2 seconds ago)

# Check what happened
$ sudo nftguard compare 46 47
[nftguard] 3 rules added, 1 rule removed
Enter fullscreen mode Exit fullscreen mode

100 snapshots in a circular buffer. Oldest rotate out automatically.

The technical bits

  • Pure Rust, single binary, ~600KB stripped
  • Zero runtime dependencies — no Python, no Node, no databases
  • Snapshots are plain JSON with full metadata (timestamp, SHA-256, chain/table info, per-rule fingerprints)
  • Runs as a oneshot systemd service before network-pre.target
  • Apache-2.0 licensed — use it anywhere, including commercial infrastructure

Install

cargo install nftguard
Enter fullscreen mode Exit fullscreen mode

Or 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
Enter fullscreen mode Exit fullscreen mode

Links

If you manage Linux firewalls, give it a try. I'd love to hear how it works on your setup.

Top comments (0)