nix | ||
src | ||
.envrc | ||
.gitignore | ||
Cargo.lock | ||
Cargo.toml | ||
flake.lock | ||
flake.nix | ||
LICENSE | ||
README.md |
nff
This is a high performance configuration parser and written in Rust. The goal is to receive possibly jumbled up nftables rule files, and output ✨ pretty ✨ human readable output in return. The main emphasis is on the syntax-aware formatting with comprehensive grammar support. It is a future goal to allow editors to hook into nff in order to format your rulesets directly from your editor, or as a diagnostics source.
Features
nff is in its early stages of development. While most of the syntax is supported, I cannot guarantee that everything is supported just yet.
Core Functionality
- Syntax-aware formatting - Deep understanding of nftables grammar with semantic preservation
- Multi-family support - Handles
inet
,ip
,ip6
,arp
,bridge
, andnetdev
table families - Flexible indentation - Configurable tabs/spaces with custom depth
- CIDR notation - Proper handling of network addresses (
192.168.1.0/24
) - Chain properties - Hooks, priorities (including negative), policies, device bindings
Advanced Features
- CST - Lossless representation preserving all tokens
- Debug mode - Comprehensive inspection of lexer tokens, AST, and CST
- Validation - Syntax checking with precise error locations
- Optimization - Configurable empty line reduction and whitespace control
Usage
# Basic formatting
nff -f /etc/nftables.conf
# Custom indentation (4 spaces)
nff -f config.nft --indent spaces --spaces 4
# Optimize formatting (reduce empty lines)
nff -f config.nft --optimize
# Output to file
nff -f config.nft -o formatted.nft
# Syntax validation only
nff -f config.nft --check
# Debug output for development (or debugging)
nff -f config.nft --debug
Architecture
Processing Pipeline
nff implements a multi-stage pipeline:
graph TD
Input --> Lexer
Lexer --> Tokens
Lexer --> Parser
Tokens --> Parser
Parser --> CST
Parser --> AST
AST --> Formatter
Formatter --> Output
CST --> Formatter
Installation
Recommended way of installing nff is to use Nix.
Development
Testing
# Run test suite
cargo test
# Run with verbose output
cargo test -- --nocapture
# Test specific module
cargo test lexer
Code Quality
# Check compilation
cargo check
# Format code
cargo fmt
# Lint code
cargo clippy
# Check for unused dependencies
cargo machete
Supported nftables Features
Table Families
- inet - Dual-stack IPv4/IPv6 (most common)
- ip - IPv4 only
- ip6 - IPv6 only
- arp - ARP protocol
- bridge - Bridge/Layer 2
- netdev - Network device (ingress/egress)
Chain Types & Hooks
- filter:
input
,forward
,output
- nat:
prerouting
,input
,output
,postrouting
- route:
output
- security:
input
,forward
,output
Expression Types
- Protocol matching:
ip protocol tcp
,tcp dport 80
- Interface matching:
iifname "eth0"
,oifname "wlan0"
- Address matching:
ip saddr 192.168.1.0/24
,ip6 daddr ::1
- Connection tracking:
ct state established,related
- Port specifications:
tcp dport { 22, 80, 443 }
- Rate limiting:
limit rate 10/minute burst 5 packets
- Sets and maps: Named sets with timeout support
Actions & Statements
- Verdicts:
accept
,drop
,reject
,return
- NAT:
snat to 192.168.1.1
,dnat to 192.168.1.100:80
- Marking:
mark set 0x1
,ct mark set 0x1
- Logging:
log prefix "dropped: "
- Counters:
counter packets 0 bytes 0
Examples
Basic Firewall
Input (minified):
table inet firewall{chain input{type filter hook input priority 0;policy drop;ct state established,related accept;iifname lo accept;tcp dport 22 accept}}
Output (formatted):
#!/usr/sbin/nft -f
table inet firewall {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iifname lo accept
tcp dport 22 accept
}
}
NAT Configuration
#!/usr/sbin/nft -f
table ip nat {
chain prerouting {
type nat hook prerouting priority -100; policy accept;
iifname "eth0" tcp dport 80 dnat to 192.168.1.100:8080
}
chain postrouting {
type nat hook postrouting priority 100; policy accept;
oifname "eth0" masquerade
}
}
Rate Limiting
#!/usr/sbin/nft -f
table inet protection {
chain input {
type filter hook input priority 0; policy accept;
tcp dport 22 limit rate 5/minute burst 10 packets accept
tcp dport 22 drop
}
}
Contributing
Code Style
- Follow
cargo fmt
formatting - Use
cargo clippy
recommendations - Maintain comprehensive documentation
- Add tests for new features
Testing Strategy (WIP)
- Unit tests: Individual component validation
- Integration tests: End-to-end formatting verification
- Regression tests: Known issue prevention
- Performance tests: Benchmark critical paths
Building
Build with cargo build
as usual. If you are using Nix, you will also want to
ensure that the Nix package builds as expected.
Technical Notes
CST Implementation
The Concrete Syntax Tree (CST) preserves all source information including:
- Whitespace and indentation
- Comments and their positions
- Token-level error recovery
- Lossless round-trip formatting
Parser Architecture
Below are the design goals of nff's architechture.
- Error recovery: Continues parsing after syntax errors
- Incremental parsing: Supports partial file processing
- Memory efficiency: Streaming token processing where possible
- Grammar completeness: Covers full nftables syntax specification
License
nff is licensed under MPL v2.0. See license file for more details on what the license entails.