BSD-Paketfilter

Der BPF ( Berkeley Packet Filter ) oder BSD-Paketfilter ist ein minimalistischer Code, der in den Kernel eingefügt wird und es dem Benutzer ermöglicht, Netzwerkfilter im Kernel durchzuführen. In seinen verschiedenen Versionen (Beispiel: eBPF (extend Berkeley Packet Filter)) wurden neue Werkzeuge implementiert, um die Erstellung von BPF-Programmen zu erleichtern. Darüber hinaus sind neue Einsatzgebiete erschlossen worden, wie zum Beispiel die Ereignisüberwachung im Kernel und dessen Tracing. Bis heute bestehen verschiedene Probleme, hauptsächlich auf der Ebene des Prüfers.

Definition

BPF wurde ursprünglich 1992 entwickelt und ist minimalistischer Binärcode, der aus dem Benutzerbereich in den Kernel injiziert wird . Es ermöglicht dem Benutzer, im Kernel zirkulierende Pakete zu filtern, ohne sie in den Benutzerbereich übertragen zu müssen. Aufgrund seiner minimalistischen Seite hat es jedoch nur wenige Anweisungen, außerdem wird es aufgrund seiner Programmierschwierigkeiten von einer kleinen Anzahl von Anwendungen wie tcpdump verwendet. Im Jahr 2013 hat Alexei Starovoitov (Software-Ingenieur, spezialisiert auf den Kernel bei Facebook) BPF komplett überarbeitet, indem er neue Funktionen hinzugefügt und seine Leistung verbessert hat. Diese neue Version heißt eBPF, im Gegensatz zu cBPF (klassisches BPF), das die vorherige Version bezeichnet. Diese neue Sprache ermöglicht die Gestaltung einer größeren Vielfalt von Anwendungsfällen, die sich in zwei Anwendungsbereiche unterteilen lassen. Der erste Bereich ist das Kernel-Tracing und -Monitoring, der zweite die Netzwerkprogrammierung.

Anwendungsfall

Es gibt mehrere Anwendungsfälle wie Tracing, Container-Firewall-Filterung oder -Netzwerk, Socket- Filterung, Paketfilterung und Datenverkehrssteuerung. Es ist auch möglich, auf der untersten Ebene des Netzwerkstapels zu filtern, also direkt durch den Treiber der Netzwerkschnittstellenkarte. So können Pakete sehr früh weggeworfen werden; XDP (Express Data Path) ist beispielsweise ein Projekt, das eBPF verwendet, das zur Verhinderung von Denial-of-Service-Angriffen verwendet werden kann . Darüber hinaus ermöglichen BPFs eine effiziente und flexible Überwachung der Netzwerkleistung für Anwendungen in virtuellen Maschinen , ein Beispiel ist das vNetTracer-Framework.

Hier ist eine nicht erschöpfende Liste von Projekten, die GMPs verwenden:

Verfolgung / Überwachung:

Bpftrace ist eine High-Level-Plottersprache zur Verbesserung von Linux Berkeley Packet Filters (eBPF), sie ist in neueren Versionen des Linux-Kernels (dh seit Version 4.x) verfügbar. Darüber hinaus verwendet bpftrace LLVM zum Kompilieren von Skripten und verwendet BCC, um mit dem Linux-BPF-System zu interagieren. Perf ist ein Tool zur Analyse der Systemleistung, das von der Linux-Kernel-Entwicklungsgemeinschaft entwickelt wurde. Lage ist ein schlankes dynamisches Tracing-Tool ohne andere Abhängigkeiten als libc. Es unterstützt x86_64 Arch64-, Arm- und PowerPC-Architekturen. Es kompiliert ply-Skripte in ein BPF-Programm und verwendet eine ähnliche Syntax wie C. Systemtipp ist ein unter der GPL lizenziertes Tracing-/Probing-Tool, mit dem Sie die Neukompilierungs-, Installations- und Neustartroutine umgehen können, um Daten zu sammeln. Es verfügt über eine Befehlszeilenschnittstelle sowie eine Skriptsprache. PCP steht für „Performance Co-Pilot“. Es ist ein ausgereiftes, erweiterbares, plattformübergreifendes Toolset, das eine Live- und retrospektive Analyse eines Systems ermöglicht. Zielfernrohr ist ein Tool zur Überwachung und Steuerung eines Docker-Containers in Echtzeit. Es bietet einen Überblick über Metriken, Tags und Container-Metadaten; sowie die Verwaltung von Containern.


Vernetzung:

Wimper ist Open-Source-Software, die Netzwerk- und Lastausgleichsverbindungen zwischen Anwendungscontainern oder -prozessen bereitstellt und sichert. Es ist in die Orchestrierungs-Frameworks von Kubernetes und Mesos integriert . Suricata ist ein Netzwerk- Intrusion-Detection- System, ein Intrusion-Prevention-System und ein Netzwerksicherheitskontrollgerät. Systemd ist eine Reihe von Programmen zur Systemverwaltung im Linux-Kernel. IProute2 ist eine Open-Source-Software, die Dienstprogramme zur Steuerung und Überwachung von Netzwerken im Linux-Kernel bereitstellt. P4c-xdp ist ein P4-Code-Backend-Compiler für XDP.


Andere:

LLVM ist ein C-Code-Compiler im eBPF-Programm. BCC steht für BPF Compiler Collection und ist ein Toolkit zum Schreiben effizienter Programme zum Verfolgen und Manipulieren des Kernels. Darüber hinaus erleichtert BCC das Schreiben von BPF-Programmen mit der Instrumentierung des Kernels in C und seiner Frontends in Python und lua . Libbpf ist eine BPF-Bibliothek, die es ermöglicht, BPF-Programme im von LLVM produzierten ELF-Format in den Kernel zu laden. Bpftool ist ein Werkzeug zur Inspektion und Manipulation von eBPF-Programmen. Gobpf ist eine GO- Bibliothek , die es dem BCC-Toolkit ermöglicht, eBPF-Programme aus GO-Code zu erstellen. Ebpf_asm ist ein Assembler für eBPF-Programme, der in einer ähnlichen Syntax wie Intel geschrieben ist.

Technischer Betrieb

BPF verwendet CFG- Kontrollflussdiagramme, um die bei der Paketanalyse verwendeten Kriterien darzustellen und auch für seine Leistung bei Baummodellausdrücken . Darüber hinaus werden diese Graphen von BPF verwendet, um Filterregeln aufzustellen, die es ermöglichen, CFG-Pfade, die für die Analyse eines Pakets unnötig sind, sowie redundante Vergleiche effektiv zu reduzieren. Der Datentransfer durch die Systemaufrufe erfolgt bidirektional zwischen dem Kernel und dem Userspace. Diese ermöglichen den ordnungsgemäßen Fortschritt der Injektion des eBPF-Binärcodes in den Kernel sowie die Übermittlung von Daten vom Zielkernel an einen User-Space-Prozess. Die vom BPF-Programm zugeordneten Pakete werden teilweise in einen Puffer kopiert, bevor sie in den Benutzerbereich übertragen werden. Mit BPF kann das Programm die Anzahl der Bytes des Pakets definieren, die in den Puffer kopiert werden sollen. Dies spart Zeit, da unnötige Daten nicht kopiert werden. Für TCP/IP/Ethernet-Pakete sind beispielsweise 134 Byte ausreichend. Ein Programm, das Statistiken über TCP-Frames erstellen möchte, kann nur einen Teil der Frames kopieren, wodurch Ausführungszeit gespart wird.

eBPF ist eine Erweiterung von BPF, die sich von dieser in mehreren Punkten unterscheidet: Das Laden von Programmen erfolgt durch den Benutzer und beim Beenden eines Programms wird überprüft, ob es sicher lauffähig ist. Die neueste Erweiterung von eBPF ist die Möglichkeit, auf gemeinsam genutzte Datenstrukturen zuzugreifen. Tatsächlich verwendet eBPF drei verschiedene Mechanismen, um diese Daten zu teilen:

Seit der Version 3.15 des Linux-Kernels bieten die eBPF-Funktionen der virtuellen Maschine durch grundlegende Anweisungen und die Einführung neuer eBPF-Funktionalität den Link-Layer-Zugriff, wodurch eine Möglichkeit zum Filtern und Filtern von Netzwerkpaketen geschaffen wird. eBPF-Programme können jedoch in verschiedenen Schichten des Netzwerkstapels aufgerufen werden, wodurch die erfassten Pakete verarbeitet werden können, bevor zur nächsten Schicht übergegangen wird. EBPF basiert auf Binärcode, der in native CPU-Anweisungen kompiliert wird, wenn die Erweiterung in den Kernel geladen wird. Im Gegensatz zu klassischem Bytecode, beispielsweise Java, erzwingen der Compiler und die Ausführungszeit von eBPF keine Typ- oder Speichersicherheit. Stattdessen wird die Sicherheit durch einen statischen Verifizierer erhöht, der überprüft, dass das Programm nicht auf Kernel-Datenstrukturen zugreifen oder Seitenfehler verursachen kann.

Sicherheits- und Stabilitätsrisiken sind vorhanden, wenn Code im Kernel ausgeführt wird. Um diese Risiken zu mindern, verlässt sich BPF auf einen Interpreter, um ein Programm sicher auszuführen. Um diese Risiken zu reduzieren, führt eBPF einen Linux-Verifier ein, der sicherstellt, dass jedes Programm bestimmte Bedingungen erfüllt, bevor es in den Kernel geladen wird, wodurch hohe Kosten für die Überprüfungszeit vermieden werden. Es stellt sicher, dass das Programm terminiert werden kann, keine Schleife enthält, die zum Absturz des Kernels führen könnte oder dass auf bestimmte Anweisungen nicht zugegriffen werden kann. Und ein anderes Mal überprüft es jeden Befehl und simuliert ihn, um sicherzustellen, dass der Zustand der Register und der Batterien gültig ist, und verhindert so den Zugriff auf den Speicher oder den Zustand des Kernels außerhalb seines zugewiesenen Bereichs. Die eBPF-Implementierung sorgt für Sicherheit für den Kernel, bietet aber auch die Möglichkeit, verschiedene Arbeiten im Kernel einzurichten, wie z. B. das Tracing des Kernels und das Herstellen des Netzwerks.

Systemaufrufe ermöglichen das Laden von Binärcode. Damit der Upload erfolgreich ist, muss das Programm vom eBPF-Verifier verifiziert werden. EBPF-Programme können gleichzeitig instanziiert werden, sogar an verschiedenen Hooks. So können sie einzeln oder verkettet betrieben werden.

Netzwerke

Ein BPF-Programm kann auf einer Schnittstelle lauschen, wenn dies geschieht, ruft der Schnittstellentreiber dieses Programm zuerst auf. BPF verteilt die Pakete dann an jeden an der Verarbeitung beteiligten Filter. Benutzerdefinierte Filter werden dann auf die Pakete angewendet und entscheiden, ob das Paket akzeptiert wird oder nicht und wie viele Bytes jedes Pakets gespeichert werden sollen. Für jeden Filter, der das Paket akzeptiert, kopiert BPF die angeforderte Datenmenge als Puffer, dem er zugeordnet werden kann dieser Filter. Bei Topologieänderungen oder einer Änderung in den Anwendungen ist es notwendig, die als Firewall dienenden Regeln zu ändern, um die von den Filtern betroffenen Ports und Adressen hinzufügen, löschen oder ändern zu können. Um dies zu tun, erstellen Sie dank der Bitmap-Strategie, die das C-Programm einfach hält, einfach ein neues Programm mit neuen Maps und laden Sie die Map mit neuen Schlüsselwerten und tauschen Sie sie mit dem alten Programm aus, um das Verhalten nachzuahmen von iptables-restore.

Werkzeuge

Jit kompilieren

Filter werden in einem Kernel mit Interpreter als Bytecode interpretiert. Ist dieser nicht vorhanden, kann eBPF den On-the-Fly- Compiler (JIT-Compiler) des Kernels verwenden, um die von eBPF erzeugten Bytecodes in nativen Code zu übersetzen und optionale maschinenabhängige Optimierungen durchzuführen.

LLVM

Clang (natives LLVM) ermöglicht es dem Benutzer, seinen C-Code in eine eBPF-Anweisung in einer ELF-Datei zu kompilieren.

BCC

Die Programmierung in eBPF-Anweisungen kann kompliziert sein. Aus diesem Grund existiert ein Toolkit namens BPF Compiler Collection (BCC), mit dem der Benutzer einfach eBPF-Programme erstellen kann. BCC umfasst und erweitert LLVM, um dem Benutzer die Möglichkeit zu geben, eBPF-Maps in C-Code zu definieren und diesen C-Code in ein eBPF-Programm zu kompilieren.

Anleitung

Die virtuelle Maschine BPF + hat 5 Betriebsklassen:

Verbesserungen und Einschränkungen

Im Jahr 2019 ergeben sich für den Entwickler noch verschiedene Probleme wie:

Es gibt Einschränkungen bei der Nutzung von Kernel-Diensten, wenige Hilfsfunktionen und es können in eBPF-Programmen kein Userspace oder Dienste von Drittanbietern verwendet werden. Bestimmte Beschränkungen machen Programmprüfungen flexibel und ermöglichen die Systemintegrität, wie beispielsweise die Unfähigkeit, dynamische Zuweisungen vorzunehmen, auf Kernel-Datenstrukturen zuzugreifen, Kernel-APIs aufzurufen oder Sprunganweisungen indirekt zu machen. Sowie die Tatsache, dass es auf einem einzigen Thread ausgeführt wird und daher eine Ausführungszeit hat, die an die Anzahl der Anweisungen gebunden ist.

BPF-Leistung

Die cGMP verwendet eine Implementierungsstrategie Puffer , der seine Gesamtleistung macht bis zu 100 - mal schneller als die NIT (Network Interface Tap ) SUN auf der gleichen Hardware laufen. Die Ausführungszeit für einen Aufruf an BPF beträgt ungefähr 6 Mikrosekunden pro Paket für einen Filter, der alle Pakete verwirft. EBPFs sind auf x86_64-Architekturen bis zu 4-mal schneller als die cBPF-Implementierung für einige Netzwerkfilter-Mikrobenchmarks, und die meisten sind 1,5-mal schneller. Es gibt eine Leistungsverbesserung von eBPFs um den Faktor 10 im Vergleich zu IPTABLES und NFTABLES.

Vorkern (XDP)

XDP, das an die unterste Ebene des Netzwerkstapels angehängt ist, eignet sich für grobe Paketfilterung, z. B. zur Verhinderung von Denial-of-Service-Angriffen . Es kann die vierfache Leistung im Vergleich zu einer ähnlichen Aufgabe im Kernel produzieren. Darüber hinaus bietet XDP auch Verbesserungen der mittleren Latenz mithilfe von Codekompilierung in JIT (Just In Time), bis zu 45 % Leistungsverbesserung mit dem Preis höherer Ausreißer-Latenzwerte. XDP bietet einen Kompromiss, es bietet keine so gute Leistung wie hochleistungsfähige dedizierte Frameworks, die den Kernel überschreiben. Bietet jedoch eine Kernel-Integration, was bedeutet, dass Pakete mit all seinen Vorteilen den Netzwerkstapel durchlaufen können. Obwohl sie nur 50 % des Durchsatzes einer 10-GbE-Leitung bewältigt, entspricht dies der Leistung eines einzelnen Kerns, dh sie skaliert mit der Anzahl der CPU-Kerne.

BPF-Historie

BPF steht ursprünglich für „Berkeley Packet Filter“, 1992 für UNIX entwickelt, um Netzwerkpakete zu filtern, ermöglichen sie dann eine Leistungssteigerung in Netzwerküberwachungsanwendungen wie „tcpdump“. BPF hat nicht die Funktion empfangene Pakete zu verwerfen, aber als Filter beschrieben, können sie Pakete assoziieren, Pakete kopieren und senden.Anfänglich sind BPFs im Linux 2.x-Kernel implementiert, mit 2 Registern 32 Dann im Jahr 2013 schlug Alexei Starovoitov eine Verbesserung der BPFs vor, die jetzt cBPF (klassisch) unterscheiden BPF) und eBPF (erweitertes BPF), eine der bemerkenswertesten Änderungen ist der Übergang zu 10 64-Bit-Registern sowie der Funktionsaufruf im Kernel dank einer neuen Anweisung Ein weiterer Unterschied ist das Fehlen von Zustandspersistenz im cBPF während in eBPF die Zustände dank der Karten beibehalten werden können eBPFs erscheinen in Version 3 .x aus dem Linux-Kernel, mit kontinuierlichen Verbesserungen wie einem JIT (Just In Time) Compiler, neuen Features wie „Maps“ und „Tail Calls“.

Referenz

  1. Monnet 2016
  2. Chaignon 2018
  3. Suo 2018
  4. Scholz 2018
  5. Cilium Autoren 2019
  6. bptrace
  7. perf
  8. Lage
  9. Systemtipp
  10. PCP
  11. Zielfernrohr
  12. Zilium
  13. Suricata
  14. systemd
  15. iproute2
  16. P4C-xdp
  17. LLVM
  18. BCC
  19. libbpf
  20. bpftool
  21. gobpf
  22. ebpf_asm
  23. McCanne 1993
  24. Lidl 2002
  25. Baidya 2018
  26. Saif 2018
  27. Ellis 2017
  28. Belkalem 2018
  29. Nam 2017
  30. Gershuni 2019
  31. Fleming 2017
  32. Miano 2018
  33. Deepak 2018
  34. Begel 1999
  35. Di 2018
  36. Van Tu 2017
  37. Spielzeug 2015
  38. Corbet 2014
  39. Spielzeug 2017
  40. Bos 2004

Literaturverzeichnis

Webseite

Siehe auch