243 lines
5.9 KiB
Markdown
243 lines
5.9 KiB
Markdown
# 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.
|