AIO APEX

eBPF: Wie Linux einen sicheren, schnellen und programmierbaren Kernel bekam

Teilen:
eBPF: Wie Linux einen sicheren, schnellen und programmierbaren Kernel bekam

Das Problem mit dem alten Ansatz

Jahrzehntelang gab es zwei Möglichkeiten, wenn man ändern wollte, wie der Linux-Kernel Pakete verarbeitet, Syscalls filtert oder Performance-Engpässe analysiert: einen Kernel-Patch einreichen und jahrelang darauf warten, dass er in Distributionen landet, oder ein Kernel-Modul schreiben. Kernel-Module sind mächtig, aber gefährlich. Ein Fehler in einem Modul bringt den Host zum Absturz. Sie sind kernel-versionsspezifisch – ein Modul, das für 5.15 gebaut wurde, funktioniert unter 6.1 nicht mehr. Den Einsatz über eine heterogene Flotte hinweg bedeutet, Dutzende von Builds zu pflegen. Für ein Unternehmen, das Hunderttausende von Servern betreibt, ist das kein rein technisches Problem – es ist ein Haftungsrisiko.

eBPF löst dieses Problem. Es ermöglicht, eigene Logik in den laufenden Kernel einzuspielen – für Networking, Sicherheit oder Observability – sicher, portabel und ohne irgendetwas neu zu starten.

Was eBPF eigentlich ist

BPF (Berkeley Packet Filter) wurde 1992 entwickelt, um tcpdump schneller zu machen. Statt jedes Paket zur Filterung in den Userspace zu kopieren, betrieb BPF eine kleine virtuelle Maschine im Kernel, um Pakete direkt zu filtern. Es war bewusst eng gehalten.

2014 brachten Alexei Starovoitov und Daniel Borkmann extended BPF in Linux 3.18 ein. Der Befehlssatz wurde für 64-Bit-Architekturen neu gestaltet, die Anzahl der Register erweitert, und – entscheidend – die Menge der Hook-Punkte explodierte weit über die Paketfilterung hinaus. Heute lassen sich eBPF-Programme an Netzwerk-Ingress- und -Egress-Pfaden, Tracepoints, Kprobes (dynamische Kernel-Funktions-Probes), Uprobes (Userspace-Funktions-Probes) und Syscall-Eintrags- und -Austrittspunkten anhängen. Der Kernel wurde programmierbar.

Das Sicherheitsmodell macht das produktionstauglich. Man schreibt ein eBPF-Programm in eingeschränktem C oder verwendet Go- oder Rust-Bibliotheken, die eBPF-Bytecode erzeugen. Bevor das Programm läuft, analysiert der Verifier des Kernels statisch jeden möglichen Ausführungspfad: keine unbegrenzten Schleifen, kein Speicherzugriff außerhalb der Grenzen, keine unsichere Zeigerarithmetik. Programme, die die Verifikation nicht bestehen, werden direkt abgelehnt. Programme, die bestehen, werden JIT-kompiliert zu nativem Maschinencode – es gibt also keinen Interpreter-Overhead zur Laufzeit. Das Ergebnis ist Code, der im Kernel mit nahezu nativer Geschwindigkeit läuft, mit Sicherheitsgarantien, die der Kernel automatisch durchsetzt.

XDP und die Netzwerkrevolution

Die beeindruckendste eBPF-Fähigkeit für Infrastruktur-Teams ist XDP — eXpress Data Path. XDP-Hooks laufen, bevor der Networking-Stack des Kernels ein Paket verarbeitet. Vor der sk_buff-Allokation. Vor der Routing-Abfrage. Vor allem. Ein XDP-Programm kann ein Paket auf Ebene des NIC-Treibers verwerfen, weiterleiten oder modifizieren – mit mehr als 100 Millionen Paketen pro Sekunde auf handelsüblicher Hardware.

Für die DDoS-Abwehr verändert das alles. Ein volumetrischer Angriff, der den normalen Netzwerkpfad des Kernels sättigen würde – Socket-Queues füllen, CPU durch Interrupt-Handling erschöpfen – wird auf Treiberebene verworfen, bevor irgendeiner dieser Overheads anfällt. Cloudflare nutzt XDP-basierte eBPF-Programme, um DDoS-Angriffe im Terabit-Maßstab abzusorbieren. Das Paket erreicht den Stack niemals. Der Host bleibt erreichbar.

Meta ging noch weiter. Sie ersetzten ihre gesamte Load-Balancing-Infrastruktur – zuvor auf IPVS aufgebaut – durch Katran, einen Open-Source eBPF/XDP Load Balancer. Katran läuft auf jedem Server in Metas Rechenzentren und verarbeitet Traffic im Facebook-Maßstab ohne dedizierte Load-Balancer-Appliances. Die Flexibilität von eBPF bedeutet, dass Load-Balancing-Logik durch das Laden eines neuen Programms aktualisiert werden kann, ohne Neustart oder Hardware-Redeployment.

Kubernetes-Networking mit Cilium

Das Kubernetes-Networking-Problem ist komplex. Jeder Pod braucht eine IP. Pods müssen knotenübergreifend kommunizieren. Network Policies müssen durchgesetzt werden. Service-Load-Balancing muss stattfinden. Die traditionelle Antwort war iptables – eine Regel-Engine, die nicht skaliert. Bei einigen Tausend Regeln wird die iptables-Suche O(n) und der CPU-Verbrauch steigt spürbar. Bei Zehntausenden von Pods bricht das System zusammen.

Cilium ersetzt iptables vollständig durch eBPF. Pod-zu-Pod-Routing, Service-Load-Balancing und die Durchsetzung von Network Policies finden alle in eBPF-Programmen statt, die an Netzwerkschnittstellen angehängt sind. Abfragen sind O(1) über eBPF-Hash-Maps. Die Policy-Durchsetzung erfolgt im Fast Path des Kernels. Cilium versteht außerdem HTTP, gRPC und Kafka auf Layer 7 – weil eBPF-Programme Paketnutzlasten inspizieren können, nicht nur Header.

Die Verbreitung spricht für sich. AWS EKS, Google GKE und Azure AKS bieten Cilium alle als Standard- oder empfohlenes CNI an. Kubernetes-Cluster mit Hunderten von Nodes und Tausenden von Pods nutzen eBPF für jede Paketentscheidung, und der iptables-Engpass ist verschwunden.

Observability ohne Instrumentierung

Traditionelle APM-Tools erfordern Code-Änderungen: eine Bibliothek hinzufügen, Funktionen wrappen, neu deployen. eBPF-Observability erfordert nichts davon. Man hängt einen Kprobe oder Uprobe an eine beliebige Kernel- oder Userspace-Funktion und sammelt Daten – Latenzen, Argumente, Rückgabewerte, Stack-Traces – ohne die Anwendung zu verändern.

Netflix setzt bpftrace genau dafür in der Produktion ein. bpftrace ist eine High-Level-Skriptsprache für eBPF, vergleichbar mit dem, was DTrace auf Solaris war. Ein Einzeiler kann jede Disk-I/O über 1ms auf einem Produktions-Host tracen, TCP-Verbindungslatenzen als Histogramm darstellen oder herausfinden, welche Prozesse die meisten Context Switches verursachen – alles mit einem Overhead im einstelligen Prozentbereich, nicht den 10–30% herkömmlichem Profiling.

Pixie geht für Kubernetes noch weiter und instrumentiert automatisch jeden Service in einem Cluster per eBPF, um Request/Response-Daten, Latenzverteilungen und Fehlerraten zu erfassen – ohne servicespezifische Konfiguration. Keine Sidecars. Keine SDK-Integration. Die Observability ist direkt in die Kernel-Schicht eingebaut.

Sicherheitsdurchsetzung auf Kernel-Ebene

seccomp-BPF filtert seit Jahren Syscalls in Linux-Containern – es ist das, was Docker, Chrome und Firefox nutzen, um einzuschränken, welche Systemaufrufe ein isolierter Prozess machen kann. Das ist das schmale Ende der eBPF-Sicherheit.

Das breitere Ende ist die Laufzeit-Sicherheitsdurchsetzung. Falco nutzt eBPF, um jeden Syscall in einem Kubernetes-Cluster zu beobachten und bei verdächtigem Verhalten zu alarmieren – ein Container, der eine Shell startet, ein Prozess, der in /etc schreibt, eine Netzwerkverbindung zu einer unerwarteten IP. Tetragon, aus dem Cilium-Projekt, geht noch weiter: Es kann Policy-Verletzungen nicht nur in Echtzeit erkennen, sondern sie auch durchsetzen, indem es den betreffenden Prozess beendet, bevor der Syscall abgeschlossen ist. Die Policy-Logik läuft im Kernel über eBPF. Es gibt kein Zeitfenster zwischen Erkennung und Reaktion.

Portabilität: CO-RE und BTF

Ein verbleibender Kritikpunkt an eBPF war die Bindung an Kernel-Versionen. Ein eBPF-Programm, das gegen die Header von Kernel 5.15 kompiliert wurde, funktioniert unter 6.1 möglicherweise nicht, wenn sich Struct-Layouts geändert haben. CO-RE — Compile Once, Run Everywhere — löst dieses Problem. Mit BTF (BPF Type Format) stellt der Kernel seine internen Typinformationen zur Laufzeit bereit. Der eBPF-Loader nutzt BTF, um Feldzugriffe beim Laden zu relocieren und das kompilierte Programm an den tatsächlich laufenden Kernel anzupassen. Ein einzelnes eBPF-Binary kann nun über eine gesamte gemischt-konfigurierte Flotte hinweg ohne Neukompilierung eingesetzt werden.

Was als Nächstes kommt

Microsoft portiert eBPF aktiv auf Windows über das ebpf-for-windows-Projekt. SmartNIC-Hersteller fügen Hardware-Offload für eBPF-Programme hinzu, sodass XDP-Filterung auf der NIC selbst laufen kann und Host-CPUs vollständig entlastet werden. User-Space eBPF-Runtimes reifen heran und ermöglichen eBPF-ähnliche, sandboxed Erweiterbarkeit außerhalb des Kernels.

Das zugrundeliegende Muster ist konsistent: Ein programmierbarer Erweiterungsmechanismus mit starken Sicherheitsgarantien schlägt statischen Kernel-Code für alles, was sich mit Produktionsgeschwindigkeit weiterentwickeln muss. eBPF hat nicht nur Linux-Networking und Observability verbessert – es hat das Modell verändert, wie Kernel-Verhalten erweitert wird. Die Infrastruktur-Teams, die das früh verstanden haben, arbeiten schneller, sicherer und in größerem Maßstab als jene, die noch iptables-Regeln und Kernel-Module schreiben.

Teilen:
eBPF: Linux-Infrastruktur im großen Maßstab neu gestalten | AIO APEX