You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: POLICY.md
+25-6Lines changed: 25 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,12 @@ rules:
14
14
protocol: tcp|udp|icmp|any
15
15
direction: ingress|egress|both
16
16
description: Optional description
17
+
18
+
# FQDN rule (domain instead of ip)
19
+
- name: block_ads
20
+
domain: "*.ads.example.com"
21
+
action: drop
22
+
direction: both
17
23
```
18
24
19
25
### JSON Format
@@ -40,7 +46,8 @@ rules:
40
46
### Rule Object
41
47
42
48
-**name** (required): Unique identifier for the rule
43
-
-**ip** (required): IPv4 address to match (e.g., "192.168.1.1" or "192.168.0.0/24")
49
+
-**ip** (required unless `domain` is set): IPv4 address to match (e.g., "192.168.1.1" or "192.168.0.0/24")
50
+
-**domain** (optional): Domain name for FQDN-based rules (e.g., "ads.example.com" or "*.tracking.com"). When set, `ip` should be omitted — IPs are resolved dynamically from DNS responses.
44
51
-**action** (required): Action to take. Valid values:
45
52
- Allow: `allow`, `pass`, `accept`
46
53
- Drop: `drop`, `deny`, `block`
@@ -57,17 +64,29 @@ rules:
57
64
-**dst_port** (optional): Destination port to match (0 or omit for any)
58
65
-**description** (optional): Human-readable description of the rule
59
66
67
+
> **Note:** Each rule must specify either `ip` or `domain`, but not both.
68
+
60
69
## Validation Rules
61
70
62
71
1. Each rule must have a unique name
63
-
2. IP addresses must be valid IPv4 format or CIDR notation
64
-
3. Actions must be one of the allowed values
65
-
4. Protocols must be tcp, udp, icmp, or any
66
-
5. Directions must be ingress, egress, or both
67
-
6. Policy file must contain at least one rule
72
+
2. Each rule must specify either `ip` or `domain`, but not both
73
+
3. IP addresses must be valid IPv4 format or CIDR notation
74
+
4. Domain names must be non-empty; wildcards use `*.` prefix (e.g., `*.example.com`)
75
+
5. Actions must be one of the allowed values
76
+
6. Protocols must be tcp, udp, icmp, or any
77
+
7. Directions must be ingress, egress, or both
78
+
8. Policy file must contain at least one rule
68
79
69
80
## Important Notes
70
81
82
+
### FQDN (Domain-Based) Rules
83
+
- FQDN rules use passive DNS sniffing to resolve domain names to IP addresses
84
+
- When a DNS response is seen for a matching domain, firebee automatically installs BPF rules for the resolved IPs
85
+
- Resolved IP rules are named `fqdn:<domain>:<ip>` and are automatically removed when the DNS TTL expires
86
+
- Wildcard domains are supported: `*.example.com` matches `sub.example.com`, `deep.sub.example.com`, and `example.com` itself
87
+
- FQDN rules require the XDP/TC programs to be loaded (via `firebee run` or `firebee add --attach`)
88
+
- A minimum TTL floor of 30 seconds is applied to prevent excessive rule churn
89
+
71
90
### Direction Field
72
91
-**XDP Limitation**: The current XDP implementation only processes ingress (incoming) traffic
73
92
- Rules with `direction: egress` will be stored but won't match traffic until TC-BPF egress support is added
Copy file name to clipboardExpand all lines: README.md
+51-35Lines changed: 51 additions & 35 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,7 @@ An eBPF-based network firewall for Linux that uses XDP (eXpress Data Path) for h
7
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
8
-**TC-BPF egress filtering** — Filters outgoing traffic using the Linux Traffic Control subsystem.
9
9
-**IPv4 and IPv6 support** — Rules can target individual IPs or CIDR ranges for both address families.
10
+
-**FQDN domain-based rules** — Block or allow traffic by domain name (e.g., `*.ads.example.com`). Firebee passively sniffs DNS responses via BPF, resolves domains to IPs, and dynamically installs/removes BPF rules with TTL-based expiry.
10
11
-**Protocol and port matching** — Filter by TCP, UDP, ICMP, or any protocol, with optional source/destination port constraints.
11
12
-**Declarative policy files** — Define rules in YAML or JSON; firebee validates and loads them.
12
13
-**Per-rule statistics** — Track packet and byte counts per rule in real time.
@@ -41,36 +42,36 @@ This runs `cargo build --release` (compiles the Rust userspace binary) and `carg
@@ -95,7 +96,7 @@ The entry point. Uses [clap](https://docs.rs/clap) to expose these subcommands:
95
96
-**`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
97
-**`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
98
-**`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_helpers.h`** — BPF helper functions for port extraction, rule matching, IPv6 prefix comparison, and DNS response capture.
99
100
-**`firebee_test.bpf.c`** — Kernel-side BPF unit tests using Cilium-style `CHECK`/`TEST` macros.
100
101
101
102
BPF maps used:
@@ -107,6 +108,7 @@ BPF maps used:
107
108
|`rule_metadata_map`| Hash | Human-readable metadata (name, description) keyed by index |
|`log_events`| Ring Buffer | Real-time packet log events sent to userspace |
111
+
|`dns_events`| Ring Buffer | DNS response payloads captured for FQDN resolution |
110
112
111
113
#### 3. BPF Userspace Layer (`src/bpf_user/`)
112
114
@@ -116,14 +118,28 @@ BPF maps used:
116
118
117
119
#### 4. Policy Engine (`src/policy/`)
118
120
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
+
-**`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, port fields, and FQDN domain rules.
122
+
-**`validator.rs`** — Validates the parsed policy: checks for non-empty rules, unique names, valid IP addresses or domains, valid actions (`allow`/`pass`/`accept`/`drop`/`deny`/`block`), and valid protocols/directions.
121
123
122
-
#### 5. State Manager (`src/state.rs`)
124
+
#### 5. DNS Monitor (`src/dns/`)
125
+
126
+
Implements passive DNS sniffing for FQDN-based firewall rules (Cilium-style approach):
127
+
128
+
-**`parser.rs`** — Parses DNS wire format responses: extracts query names and A/AAAA answer records with IPs and TTLs. Handles DNS label compression pointers.
129
+
-**`cache.rs`** — TTL-aware cache mapping domain names to resolved IP addresses. Tracks per-IP expiry and supports sweep operations to clean up stale entries.
130
+
-**`monitor.rs`** — The orchestrator: polls the `dns_events` BPF ring buffer, parses each captured DNS response, matches against FQDN rules (exact or wildcard), and dynamically installs/removes BPF rules via `RulesState`. Rules are named `fqdn:<domain>:<ip>` for tracking and cleanup.
131
+
132
+
**How it works:**
133
+
1. BPF programs (XDP + TC) detect UDP packets with source port 53 (DNS responses) and copy the DNS payload into the `dns_events` ring buffer.
134
+
2. The DNS monitor thread polls this ring buffer, parses each DNS response, and checks if the queried domain matches any FQDN rule.
135
+
3. For matching domains, the resolved IP addresses are installed as concrete BPF rules with `/32` masks, inheriting the FQDN rule's action/protocol/direction.
136
+
4. When DNS TTLs expire, the corresponding BPF rules are automatically removed.
137
+
138
+
#### 6. State Manager (`src/state.rs`)
123
139
124
140
`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
141
126
-
#### 6. Terminal UI (`src/ui/`)
142
+
#### 7. Terminal UI (`src/ui/`)
127
143
128
144
Built with [ratatui](https://docs.rs/ratatui) and [crossterm](https://docs.rs/crossterm):
0 commit comments