nftsim - nftables Simulation and Testing Tool
A high-fidelity, unprivileged simulation environment for testing nftables firewall rulesets.
Features
- Unprivileged Testing: Runs User-Mode Linux (UML) without requiring root privileges for tests
- Comprehensive Protocol Support: TCP, UDP, ICMP, IPv6 with payload data, proper checksums, and connection tracking
- NAT Validation: SNAT, DNAT, masquerade with automatic verification
- Multi-Zone Firewalls: Support for DMZ/3+ interface configurations
- Advanced nftables Features: Sets, maps, counters, quotas, rate limiting
- Hybrid Validation: Combines nftables trace output with packet capture for authoritative results
- Real-World Scenarios: Docker hosts, VPN gateways, laptop firewalls with comprehensive tes…
nftsim - nftables Simulation and Testing Tool
A high-fidelity, unprivileged simulation environment for testing nftables firewall rulesets.
Features
- Unprivileged Testing: Runs User-Mode Linux (UML) without requiring root privileges for tests
- Comprehensive Protocol Support: TCP, UDP, ICMP, IPv6 with payload data, proper checksums, and connection tracking
- NAT Validation: SNAT, DNAT, masquerade with automatic verification
- Multi-Zone Firewalls: Support for DMZ/3+ interface configurations
- Advanced nftables Features: Sets, maps, counters, quotas, rate limiting
- Hybrid Validation: Combines nftables trace output with packet capture for authoritative results
- Real-World Scenarios: Docker hosts, VPN gateways, laptop firewalls with comprehensive test coverage
- 321 Test Cases: Across 26 comprehensive test suites
Quick Start
Prerequisites
- Rust toolchain (1.70+)
- Linux kernel source (Debian:
apt-get install linux-source) - Build tools:
debootstrap,make,gcc,flex,bison,bc - Sudo access for bootstrap (mount, debootstrap operations)
Building
cargo build --release
Bootstrap (One-Time Setup)
Build the custom UML kernel and create rootfs:
./target/release/nftsim bootstrap
# Or install and run from anywhere
cargo install --path .
nftsim bootstrap
What this does:
- Builds a custom UML kernel with all nftables features built-in (no modules)
- Creates a 2GB Debian bookworm rootfs with required packages
- Stores all artifacts in
$HOME/.local/share/nftsim/(relocatable, not tied to source directory) - Caches kernel build in
$HOME/.local/share/nftsim/linux/for fast incremental rebuilds - Caches debootstrap packages in
$HOME/.local/share/nftsim/rootfs-cache/for fast rootfs recreation - Prompts for sudo only when needed (mount, debootstrap)
Outputs:
$HOME/.local/share/nftsim/linux/linux- Custom UML kernel binary$HOME/.local/share/nftsim/rootfs.img- 2GB ext4 root filesystem$HOME/.local/share/nftsim/linux/- Kernel source build directory with build artifacts$HOME/.local/share/nftsim/rootfs-cache/- Debootstrap package cache
All build artifacts are stored in $HOME/.local/share/nftsim/ (user-specific, relocatable).
Relocatable Binary:
- Resources (bootstrap.sh, harness.sh, kernel.config) are embedded in the binary
- nftsim can be run from anywhere after
cargo install --path . - No need to be in the source directory
Rebuilding:
- Kernel only rebuilds if embedded kernel.config changes or binary is missing
- Rootfs creation prompts before overwriting existing image
Running Tests
Single Test Suite
./target/release/nftsim test testdata/01_basics.nft testdata/01_basics.toml
All Test Suites
./test.sh
Specific Test Suites
./test.sh 01_basics 08_nat 22_ipv6
Test Coverage
nftsim includes 26 comprehensive test suites with 321 test cases covering:
- Core firewall functionality (TCP, UDP, ICMP, IPv6)
- NAT and port forwarding scenarios
- Multi-zone firewalls (DMZ configurations)
- Advanced nftables features (sets, maps, counters, quotas, rate limiting)
- Real-world scenarios (Docker hosts, VPN gateways, laptop firewalls)
- Edge cases and security validation
See CONTRIBUTING.md for the complete list of test suites and their descriptions.
Writing Tests
Tests are defined using TOML configuration files. Here’s a simple example:
# Network topology
[network]
interfaces = [
{ name = "eth0", ip = "192.168.1.1/24" },
{ name = "eth1", ip = "10.0.0.1/24" },
]
routes = [
{ destination = "0.0.0.0/0", via = "10.0.0.2" },
]
# Guest setup
[guest_setup]
sysctls = { "net.ipv4.ip_forward" = "1" }
# Test case
[[tests]]
name = "Allow HTTP from Internal to External"
[[tests.packets]]
packet = {
on_interface = "eth0",
source_ip = "192.168.1.50",
dest_ip = "8.8.8.8",
tcp = { source_port = 40000, dest_port = 80, flags = ["SYN"] }
}
expect = [
{ hook = "forward", verdict = "accept", to_interface = "eth1" }
]
For complete TOML format reference, examples, and best practices, see TESTDATA.md.
How It Works
- Socketpair Creation: Unix socketpairs for each network interface
- UML Launch: Spawns User-Mode Linux with
fdtransport - Network Setup: Configures interfaces, routes, sysctls in guest
- Ruleset Loading: Loads your nftables rules
- Trace Enablement: Enables
meta nftrace set 1for verdict detection - Packet Injection: Builds Ethernet/IP/TCP frames with proper checksums
- Hybrid Validation: Combines trace output (verdict) + socket capture (interface)
- Result Display: PASS/FAIL with detailed expectations
Architecture
- Orchestrator: Rust binary (
nftsim) manages UML, injects packets, validates results - UML Guest: Isolated Linux kernel with your firewall rules
- Transport: Unix socketpairs with
fdtransport (fully unprivileged) - Validation: Hybrid approach using nftables trace + packet capture
See DESIGN.md for detailed architecture documentation.
For known limitations and planned improvements, see ROADMAP.md.
License
See LICENSE file for details.
Contributing
Contributions are welcome! See CONTRIBUTING.md for:
- Development workflow and debugging tips
- How to create custom tests
- Code structure and key implementation details
- Performance metrics and test output modes
For architectural details, see DESIGN.md.