r/kernel 17h ago

Replacing iptables with eBPF: How I built a zero-downtime, identity-aware kernel firewall engine in Go & C

Over the past few weeks, I’ve been working on an open-source project: Identity-

Aware eBPF Firewall](https://github.com/AboEl3iz/Identity-Aware-eBPF-Firewall) — a

high-performance in-kernel packet filtering engine written in C (eBPF bytecode)

with a Go control plane .

Traditional `iptables`/`netfilter` setups suffer from sequential O(N) rule

scanning, mandatory kernel `sk_buff` memory allocations per packet (which chokes under

volumetric floods), blocking monolithic reloads, and IP-only granularity. I wanted to

build a modern system that addresses these limitations using native eBPF primitives

and container identity.

---

### Key Technical Highlights

  1. Stateless XDP Volumetric Fast-Path (`SEC("xdp")`)

- Drops malicious floods directly inside interface driver RX queues before

`sk_buff` allocation.

- Subnet filtering uses kernel-native Longest Prefix Match Tries

(`BPF_MAP_TYPE_LPM_TRIE`) for $O(\text{prefix_len})$ lookups instead of linear rules.

  1. TC Stateful Connection Tracking (`SEC("tc")`)

- Enforces TCP 3-way handshakes and state machine transitions using an LRU flow

map (`BPF_MAP_TYPE_LRU_HASH`).

- Automatically drops untracked non-SYN packets (e.g. out-of-order ACK/PSH flood

attacks) before reaching the Linux networking stack.

  1. Cgroup v2 Workload Identity Resolution

- Binds network rules directly to container workloads using 64-bit Linux cgroup

v2 inode numbers (`syscall.Stat`) mapped to `bpf_get_current_cgroup_id()`.

- Allows fine-grained container microsegmentation on single hosts without needing

full Kubernetes stack dependencies.

  1. Double-Buffered Zero-Drop Atomic Policy Reloads

- Updates policies without dropping continuous packet streams.

- Compiles AST policies into generation-indexed BPF maps and performs a single-

operation atomic switch via `active_generation_map[0] = next_gen`. If staging fails,

it safely rolls back automatically.

  1. Security Hardening & Control Plane RBAC

- Capability Bounding : Drops full root permissions down to the minimal set

(`CAP_BPF`, `CAP_NET_ADMIN`, `CAP_SYS_RESOURCE`).

- IPC Security : Unix domain socket control plane authenticates caller process

credentials using Linux `SO_PEERCRED` (`unix.GetsockoptUcred`) and enforces 3-tier

RBAC (`Admin`, `Operator`, `Viewer`).

  1. Real-Time Observability & Interactive TUI

- Built an interactive 4-pane Bubbletea Terminal UI (`firewall-tui`) driven by

zero-copy BPF ring buffer streams (`BPF_MAP_TYPE_RINGBUF`) with real-time sparkline

metrics, conntrack flow tables, and explainable audit streams (`[PASS]` / `[DROP]`).

0 Upvotes

3 comments sorted by

1

u/PhilipLGriffiths88 8h ago

Interesting work. One distinction I’d make is around what “identity-aware” means here.

As I read the implementation, identity is a local cgroup v2 ID. That is useful workload attribution within one Linux kernel, but it is still host-local metadata. It is not an identity presented by the workload, cryptographically authenticated, independently verifiable at the destination, or meaningful once the traffic crosses a host boundary.

That distinction matters at XDP ingress too: bpf_get_current_cgroup_id() returns the cgroup of the current local task, not the identity of a remote sender. A same-kernel veth test may demonstrate cgroup attribution, but it does not establish identity across a network trust boundary.

I’d therefore describe the current design as cgroup-aware or workload-context-aware filtering. It becomes stronger identity-aware enforcement when that local context is bound to a verifiable workload identity and policy authorises that identity to a specific service, with the identity independently validated at the other end.

Is that where you see the project heading? Disagree?

1

u/Single-Issue2342 3h ago

Spot-on observation! You’re completely right—bpf_get_current_cgroup_id() in ingress
hooks evaluates local host task context,
making Phase 1 effectively host-local workload attribution rather than cross-host identity verification. i chose local cgroup v2 inodes for Phase 1 as a lightweight baseline for container microsegmentation on bare metal without needing Kubernetes.The long-term goal for true cross-network identity enforcement is to plug in wire- level headers (Geneve/VXLAN Security IDs) and SPIFFE/SPIRE mTLS attestation via my

sockops/sk_msg proxy redirect hooks.

I really appreciate you highlighting this distinction

1

u/PhilipLGriffiths88 24m ago

That makes sense. Out of curiosity, what is the longer-term goal: to keep this primarily a high-performance host firewall with richer local workload context, or turn it into a cross-network identity and service-connectivity layer?