# 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`, and `netdev` 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 ```bash # 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: ```mermaid 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 ```bash # Run test suite cargo test # Run with verbose output cargo test -- --nocapture # Test specific module cargo test lexer ``` ### Code Quality ```bash # 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): ```nftables 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): ```nftables #!/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 ```nftables #!/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 ```nftables #!/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](LICENSE). See license file for more details on what the license entails.