|
| 1 | +# Firebee |
| 2 | + |
| 3 | +An eBPF-based network firewall for Linux that uses XDP (eXpress Data Path) for high-performance ingress packet filtering and TC-BPF (Traffic Control) for egress filtering. Firebee provides a declarative policy file format, a CLI for rule management, and a real-time terminal UI (TUI) for monitoring traffic. |
| 4 | + |
| 5 | +## Features |
| 6 | + |
| 7 | +- **XDP ingress filtering** — Drops or allows packets at the earliest point in the network stack, before the kernel allocates an `sk_buff`, for near line-rate performance. |
| 8 | +- **TC-BPF egress filtering** — Filters outgoing traffic using the Linux Traffic Control subsystem. |
| 9 | +- **IPv4 and IPv6 support** — Rules can target individual IPs or CIDR ranges for both address families. |
| 10 | +- **Protocol and port matching** — Filter by TCP, UDP, ICMP, or any protocol, with optional source/destination port constraints. |
| 11 | +- **Declarative policy files** — Define rules in YAML or JSON; firebee validates and loads them. |
| 12 | +- **Per-rule statistics** — Track packet and byte counts per rule in real time. |
| 13 | +- **Terminal UI** — A ratatui-based TUI shows active rules, live packet logs from a BPF ring buffer, and per-rule stats. |
| 14 | +- **Pinned BPF maps** — Maps are pinned to `/sys/fs/bpf/firebee/` so rules persist across CLI invocations and multiple tools can interact with the running firewall. |
| 15 | + |
| 16 | +## Prerequisites |
| 17 | + |
| 18 | +- Linux kernel ≥ 5.15 (with BPF and XDP support) |
| 19 | +- `clang` and `llvm` (for compiling BPF C programs) |
| 20 | +- `libelf-dev`, `libbpf-dev`, `pkg-config` |
| 21 | +- Linux headers for your kernel (`linux-headers-$(uname -r)`) |
| 22 | +- Rust toolchain (stable) |
| 23 | +- Root privileges (or `CAP_BPF` + `CAP_NET_ADMIN`) to load BPF programs |
| 24 | + |
| 25 | +### Install dependencies (Debian/Ubuntu) |
| 26 | + |
| 27 | +```bash |
| 28 | +sudo apt-get install -y \ |
| 29 | + llvm clang libelf-dev libbpf-dev linux-headers-$(uname -r) \ |
| 30 | + linux-libc-dev build-essential pkg-config |
| 31 | +``` |
| 32 | + |
| 33 | +## Building |
| 34 | + |
| 35 | +```bash |
| 36 | +make build |
| 37 | +``` |
| 38 | + |
| 39 | +This runs `cargo build --release` (compiles the Rust userspace binary) and `cargo libbpf build` (compiles the BPF C programs into `.bpf.o` object files under `target/bpf/`). |
| 40 | + |
| 41 | +## Architecture |
| 42 | + |
| 43 | +``` |
| 44 | +┌──────────────────────────────────────────────────────────┐ |
| 45 | +│ Userspace (Rust) │ |
| 46 | +│ │ |
| 47 | +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │ |
| 48 | +│ │ CLI │ │ Policy │ │ State │ │ TUI │ │ |
| 49 | +│ │ (clap) │ │ Parser & │ │ Manager │ │(ratatui)│ │ |
| 50 | +│ │ │ │Validator │ │ │ │ │ │ |
| 51 | +│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬────┘ │ |
| 52 | +│ │ │ │ │ │ |
| 53 | +│ └──────────────┴─────┬───────┴──────────────┘ │ |
| 54 | +│ │ │ |
| 55 | +│ ┌───────▼────────┐ │ |
| 56 | +│ │ BPF Loader │ │ |
| 57 | +│ │ & Maps API │ │ |
| 58 | +│ └───────┬────────┘ │ |
| 59 | +└────────────────────────────┼─────────────────────────────┘ |
| 60 | + │ libbpf-rs |
| 61 | + ┌─────────▼──────────┐ |
| 62 | + │ Pinned BPF Maps │ |
| 63 | + │ /sys/fs/bpf/firebee│ |
| 64 | + └─────────┬──────────┘ |
| 65 | + │ |
| 66 | + ┌────────────────┼────────────────┐ |
| 67 | + │ │ │ |
| 68 | + ┌────────▼──────┐ ┌─────▼──────┐ ┌──────▼───────┐ |
| 69 | + │ XDP Program │ │ TC Egress │ │ Ring Buffer │ |
| 70 | + │ (ingress) │ │ Program │ │ (log_events)│ |
| 71 | + │ firebee.bpf.c│ │firebee_ │ │ │ |
| 72 | + │ │ │egress.bpf.c│ │ │ |
| 73 | + └───────────────┘ └────────────┘ └──────────────┘ |
| 74 | + Kernel space (eBPF) |
| 75 | +``` |
| 76 | + |
| 77 | +### Major Components |
| 78 | + |
| 79 | +#### 1. CLI (`src/main.rs`) |
| 80 | + |
| 81 | +The entry point. Uses [clap](https://docs.rs/clap) to expose these subcommands: |
| 82 | + |
| 83 | +| Command | Description | |
| 84 | +|---------|------------| |
| 85 | +| `run <interface>` | Attach the XDP/TC programs to a network interface and optionally load a policy file. | |
| 86 | +| `ui` | Launch the terminal UI to monitor an already-running firewall. | |
| 87 | +| `add --policy <file>` | Parse and load rules from a YAML/JSON policy file into the running firewall. | |
| 88 | +| `get rule [name]` | Print one or all active rules (YAML or JSON output). | |
| 89 | +| `delete rule <name>` | Remove a rule by name. | |
| 90 | +| `stats show` | Display per-rule packet/byte statistics. | |
| 91 | +| `stats reset` | Reset all counters to zero. | |
| 92 | + |
| 93 | +#### 2. BPF Programs (`src/bpf/`) |
| 94 | + |
| 95 | +- **`firebee.bpf.c`** — The XDP program (`xdp_firewall`). Attached to a network interface, it inspects every incoming packet: parses Ethernet/IP/IPv6 headers, extracts protocol and ports, iterates through the rules array map to find a match (with CIDR, protocol, port, and direction checks), logs the decision to a ring buffer, and returns `XDP_DROP` or `XDP_PASS`. |
| 96 | +- **`firebee_egress.bpf.c`** — The TC-BPF program (`tc_egress_firewall`). Attached via the Traffic Control egress hook, it performs the same matching logic on outgoing packets, returning `TC_ACT_SHOT` (drop) or `TC_ACT_OK` (pass). |
| 97 | +- **`firebee_common.h`** — Shared struct definitions (`rule_entry`, `rule_entry_v6`, `rule_metadata`, `log_event`, `rule_stats`) used by both kernel and userspace. |
| 98 | +- **`firebee_helpers.h`** — BPF helper functions for port extraction, rule matching, and IPv6 prefix comparison. |
| 99 | +- **`firebee_test.bpf.c`** — Kernel-side BPF unit tests using Cilium-style `CHECK`/`TEST` macros. |
| 100 | + |
| 101 | +BPF maps used: |
| 102 | + |
| 103 | +| Map | Type | Purpose | |
| 104 | +|-----|------|---------| |
| 105 | +| `rules_map` | Array | IPv4 rule entries for fast iteration | |
| 106 | +| `rules_map_v6` | Array | IPv6 rule entries | |
| 107 | +| `rule_metadata_map` | Hash | Human-readable metadata (name, description) keyed by index | |
| 108 | +| `rule_stats_map` | Array | Per-rule packet/byte counters | |
| 109 | +| `log_events` | Ring Buffer | Real-time packet log events sent to userspace | |
| 110 | + |
| 111 | +#### 3. BPF Userspace Layer (`src/bpf_user/`) |
| 112 | + |
| 113 | +- **`loader.rs`** — `BpfLoader` opens the compiled `.bpf.o` files, pins all maps to `/sys/fs/bpf/firebee/`, attaches the XDP program to the given interface, and optionally loads the TC egress program. |
| 114 | +- **`maps.rs`** — `BpfMaps` provides a safe Rust API over the pinned BPF maps: add/remove/list rules, read/write metadata, get/reset statistics, and interact with both IPv4 and IPv6 rule maps. |
| 115 | +- **`handler.rs`** — `BpfHandler` runs the event loop: listens for commands (add rule, remove rule, unload) and polls the ring buffer for log events. |
| 116 | + |
| 117 | +#### 4. Policy Engine (`src/policy/`) |
| 118 | + |
| 119 | +- **`parser.rs`** — Reads a `.yaml`/`.yml` or `.json` file, deserialises it into a `PolicyFile` containing a list of `PolicyRule` structs. Supports IPv4, IPv6, CIDR notation, protocol, direction, and port fields. |
| 120 | +- **`validator.rs`** — Validates the parsed policy: checks for non-empty rules, unique names, valid IP addresses, valid actions (`allow`/`pass`/`accept`/`drop`/`deny`/`block`), and valid protocols/directions. |
| 121 | + |
| 122 | +#### 5. State Manager (`src/state.rs`) |
| 123 | + |
| 124 | +`RulesState` bridges the policy layer and the BPF maps. It converts `PolicyRule` objects into kernel-level `Rule` structs and calls the maps API to add, get, delete, or list rules. |
| 125 | + |
| 126 | +#### 6. Terminal UI (`src/ui/`) |
| 127 | + |
| 128 | +Built with [ratatui](https://docs.rs/ratatui) and [crossterm](https://docs.rs/crossterm): |
| 129 | + |
| 130 | +- **`app.rs`** — Application state: active rules, log buffer, per-rule stats, input mode. |
| 131 | +- **`widgets.rs`** — Renders a rules table (name, IP, protocol, direction, ports, action, stats, description), a scrolling log pane, and help text. |
| 132 | +- **`events.rs`** — Keyboard event handling: `Q` to quit, `A` to add a rule interactively, `U` to unload the firewall (with confirmation). |
| 133 | + |
| 134 | +## Usage |
| 135 | + |
| 136 | +All commands require root privileges. |
| 137 | + |
| 138 | +### Start the firewall on an interface |
| 139 | + |
| 140 | +```bash |
| 141 | +sudo ./target/release/firebee run eth0 |
| 142 | +``` |
| 143 | + |
| 144 | +Optionally load a policy file at startup: |
| 145 | + |
| 146 | +```bash |
| 147 | +sudo ./target/release/firebee run eth0 --policy example-policy.yaml |
| 148 | +``` |
| 149 | + |
| 150 | +### Add rules from a policy file to a running firewall |
| 151 | + |
| 152 | +```bash |
| 153 | +sudo ./target/release/firebee add --policy example-policy.yaml |
| 154 | +``` |
| 155 | + |
| 156 | +To attach to a new interface and load rules in one step: |
| 157 | + |
| 158 | +```bash |
| 159 | +sudo ./target/release/firebee add --policy example-policy.yaml --interface eth0 --attach |
| 160 | +``` |
| 161 | + |
| 162 | +### Launch the TUI |
| 163 | + |
| 164 | +```bash |
| 165 | +sudo ./target/release/firebee ui |
| 166 | +``` |
| 167 | + |
| 168 | +This connects to the already-running firewall's pinned maps and shows live rules, stats, and packet logs. |
| 169 | + |
| 170 | +### Query active rules |
| 171 | + |
| 172 | +```bash |
| 173 | +# List all rules (YAML output) |
| 174 | +sudo ./target/release/firebee get rule |
| 175 | + |
| 176 | +# Get a specific rule in JSON |
| 177 | +sudo ./target/release/firebee get rule block_suspicious_ip --output json |
| 178 | +``` |
| 179 | + |
| 180 | +### Delete a rule |
| 181 | + |
| 182 | +```bash |
| 183 | +sudo ./target/release/firebee delete rule block_suspicious_ip |
| 184 | +``` |
| 185 | + |
| 186 | +### View and reset statistics |
| 187 | + |
| 188 | +```bash |
| 189 | +# Show per-rule stats |
| 190 | +sudo ./target/release/firebee stats show |
| 191 | + |
| 192 | +# Reset all counters |
| 193 | +sudo ./target/release/firebee stats reset |
| 194 | +``` |
| 195 | + |
| 196 | +### Cleanup |
| 197 | + |
| 198 | +To fully detach all BPF programs and remove pinned maps: |
| 199 | + |
| 200 | +```bash |
| 201 | +sudo ./cleanup.sh |
| 202 | +``` |
| 203 | + |
| 204 | +## Policy File Format |
| 205 | + |
| 206 | +Rules are defined in YAML (recommended) or JSON. See [POLICY.md](POLICY.md) for the full specification. |
| 207 | + |
| 208 | +### Example (YAML) |
| 209 | + |
| 210 | +```yaml |
| 211 | +rules: |
| 212 | + - name: block_suspicious_ip |
| 213 | + ip: 192.168.1.100 |
| 214 | + action: drop |
| 215 | + protocol: any |
| 216 | + direction: ingress |
| 217 | + description: Block known malicious IP address |
| 218 | + |
| 219 | + - name: allow_dns_queries |
| 220 | + ip: 8.8.8.8 |
| 221 | + action: allow |
| 222 | + protocol: udp |
| 223 | + dst_port: 53 |
| 224 | + direction: both |
| 225 | + description: Allow DNS queries to Google DNS |
| 226 | + |
| 227 | + - name: block_ssh_from_subnet |
| 228 | + ip: 192.168.100.0/24 |
| 229 | + action: drop |
| 230 | + protocol: tcp |
| 231 | + dst_port: 22 |
| 232 | + direction: ingress |
| 233 | + description: Block SSH access from entire subnet |
| 234 | +``` |
| 235 | +
|
| 236 | +### Example (IPv6) |
| 237 | +
|
| 238 | +```yaml |
| 239 | +rules: |
| 240 | + - name: block_google_ipv6_dns_icmp |
| 241 | + ip: 2001:4860:4860::8888/128 |
| 242 | + action: drop |
| 243 | + direction: ingress |
| 244 | + protocol: icmp |
| 245 | + description: Block ICMPv6 from Google IPv6 DNS |
| 246 | + |
| 247 | + - name: allow_cloudflare_ipv6_https |
| 248 | + ip: 2606:4700::/32 |
| 249 | + action: allow |
| 250 | + direction: ingress |
| 251 | + protocol: tcp |
| 252 | + src_port: 443 |
| 253 | + description: Allow HTTPS from Cloudflare IPv6 |
| 254 | +``` |
| 255 | +
|
| 256 | +### Rule Fields |
| 257 | +
|
| 258 | +| Field | Required | Default | Values | |
| 259 | +|-------|----------|---------|--------| |
| 260 | +| `name` | yes | — | Unique identifier | |
| 261 | +| `ip` | yes | — | IPv4/IPv6 address or CIDR (e.g. `10.0.0.0/8`, `2001:db8::/32`) | |
| 262 | +| `action` | yes | — | `allow` / `pass` / `accept` / `drop` / `deny` / `block` | |
| 263 | +| `protocol` | no | `any` | `tcp` / `udp` / `icmp` / `any` | |
| 264 | +| `direction` | no | `ingress` | `ingress` / `egress` / `both` | |
| 265 | +| `src_port` | no | any | Source port number | |
| 266 | +| `dst_port` | no | any | Destination port number | |
| 267 | +| `description` | no | — | Human-readable description | |
| 268 | + |
| 269 | +## Testing |
| 270 | + |
| 271 | +```bash |
| 272 | +# Run userspace unit tests |
| 273 | +make test |
| 274 | +
|
| 275 | +# Run BPF kernel-side tests (requires root) |
| 276 | +sudo make run_bpf_tests |
| 277 | +
|
| 278 | +# Run all tests |
| 279 | +sudo make test_all |
| 280 | +``` |
| 281 | + |
| 282 | + |
| 283 | +## License |
| 284 | + |
| 285 | +The license will be added in the future. |
0 commit comments