eBPF-Traffic-Monitoring

Das eBPF-Netzwerk-Traffic-Tool verwendet eine Kombination aus Kernel- und Userspace-Implementierung, um die Netzwerknutzung auf dem Gerät seit dem letzten Start zu überwachen. Sie bietet zusätzliche Funktionen wie Socket-Tagging, die Trennung von Vordergrund-/Hintergrund-Traffic und eine UID-spezifische Firewall, um Apps je nach Smartphone-Status den Netzwerkzugriff zu blockieren. Die vom Tool erfassten Statistiken werden in einer Kernel-Datenstruktur namens eBPF maps gespeichert. Das Ergebnis wird von Diensten wie NetworkStatsService verwendet, um persistente Traffic-Statistiken seit dem letzten Start bereitzustellen.

Beispiele und Quelle

Die Änderungen im Userspace betreffen hauptsächlich die Projekte system/netd und framework/base. Die Entwicklung erfolgt in AOSP. Der AOSP-Code ist also immer auf dem neuesten Stand. Die Quelle befindet sich hauptsächlich unter system/netd/server/TrafficController*, system/netd/bpfloader und system/netd/libbpf/. Einige erforderliche Änderungen am Framework sind auch in framework/base/ und system/core zu finden.

Implementierung

Ab Android 9 müssen Android-Geräte mit Kernel 4.9 oder höher, die ursprünglich mit der P-Version ausgeliefert wurden, anstelle von xt_qtaguid die eBPF-basierte Netzwerküberwachung verwenden. Die neue Infrastruktur ist flexibler und wartungsfreundlicher und erfordert keinen Out-of-Tree-Kernelcode.

Die wichtigsten Designunterschiede zwischen der bisherigen und der eBPF-basierten Traffic-Überwachung sind in Abbildung 1 dargestellt.

Unterschiede zwischen dem Legacy- und dem eBPF-Traffic-Monitoring

Abbildung 1: Unterschiede beim Traffic-Monitoring mit Legacy (links) und eBPF (rechts)

Das neue trafficController-Design basiert auf einem pro-cgroup-eBPF-Filter sowie dem xt_bpf-Netfilter-Modul im Kernel. Diese eBPF-Filter werden auf die Pakete angewendet, wenn sie den Filter passieren. Der cgroup-eBPF-Filter befindet sich in der Transportschicht und ist dafür verantwortlich, den Traffic je nach Socket-UID und Userspace-Einstellung der richtigen UID zuzuordnen. Die xt_bpf-Netfilter ist an der bw_raw_PREROUTING- und bw_mangle_POSTROUTING-Kette angehängt und für das Zählen des Traffics an der richtigen Schnittstelle verantwortlich.

Beim Starten erstellt der Userspace-Prozess trafficController die für die Datenerhebung verwendeten eBPF-Maps und fügt alle Maps als virtuelle Datei unter sys/fs/bpf an. Anschließend lädt der privilegierte Prozess bpfloader das vorab kompilierte eBPF-Programm in den Kernel und fügt es der richtigen cgroup hinzu. Es gibt eine einzelne Stammcgroup für den gesamten Traffic. Daher sollte der gesamte Prozess standardmäßig in dieser cgroup enthalten sein.

Während der Laufzeit kann der trafficController einen Socket taggen oder das Tag entfernen, indem er in traffic_cookie_tag_map und traffic_uid_counterSet_map schreibt. Der NetworkStatsService kann die Besucherstatistiken von traffic_tag_stats_map, traffic_uid_stats_map und traffic_iface_stats_map lesen. Neben der Funktion zum Erfassen von Traffic-Statistiken sind die eBPF-Filter trafficController und cgroup auch für das Blockieren von Traffic von bestimmten UIDs verantwortlich, je nach den Einstellungen des Smartphones. Die UID-basierte Blockierung von Netzwerkverkehr ersetzt das xt_owner-Modul im Kernel. Der Detailmodus kann durch Schreiben in traffic_powersave_uid_map, traffic_standby_uid_map und traffic_dozable_uid_map konfiguriert werden.

Die neue Implementierung folgt der alten xt_qtaguid-Modulimplementierung. TrafficController und NetworkStatsService werden also entweder mit der alten oder der neuen Implementierung ausgeführt. Wenn die App öffentliche APIs verwendet, sollte es keinen Unterschied machen, ob im Hintergrund xt_qtaguid- oder eBPF-Tools verwendet werden.

Wenn der Gerätekernel auf dem Android Common Kernel 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 oder höher) basiert, sind keine Änderungen an HALs, Treibern oder Kernelcode erforderlich, um das neue eBPF-Tool zu implementieren.

Voraussetzungen

  1. In der Kernelkonfiguration MÜSSEN die folgenden Konfigurationen aktiviert sein:

    1. CONFIG_CGROUP_BPF=y
    2. CONFIG_BPF=y
    3. CONFIG_BPF_SYSCALL=y
    4. CONFIG_NETFILTER_XT_MATCH_BPF=y
    5. CONFIG_INET_UDP_DIAG=y

    Der VTS-Kernel-Konfigurationstest ist hilfreich, um zu prüfen, ob die richtige Konfiguration aktiviert ist.

Einstellung der Legacy-Kennzeichnung „xt_qtaguid“

Das neue eBPF-Tool ersetzt das xt_qtaguid-Modul und das darauf basierende xt_owner-Modul. Wir werden das xt_qtaguid-Modul aus dem Android-Kernel entfernen und die unnötigen Konfigurationen deaktivieren.

In der Android 9-Version ist das xt_qtaguid-Modul auf allen Geräten aktiviert, aber alle öffentlichen APIs, die die Proc-Datei des xt_qtaguid-Moduls direkt lesen, werden in den NetworkManagement-Dienst verschoben. Je nach Gerätekernelversion und erster API-Ebene weiß der NetworkManagement-Dienst, ob eBPF-Tools aktiviert sind, und wählt das richtige Modul für die einzelnen Statistiken zur Netzwerknutzung der App aus. Apps mit SDK-Level 28 und höher werden durch sepolicy vom Zugriff auf xt_qtaguid-Proc-Dateien blockiert.

In der nächsten Android-Version nach Version 9 wird der App-Zugriff auf diese xt_qtaguid-Proc-Dateien vollständig blockiert. Wir beginnen dann, das xt_qtaguid-Modul aus den neuen Android Common Kernels zu entfernen. Nach der Entfernung aktualisieren wir die Android-Basiskonfiguration für diese Kernelversion, um das xt_qtaguid-Modul explizit zu deaktivieren. Das xt_qtaguid-Modul wird vollständig eingestellt, wenn die Mindestkernelversionsanforderung für eine Android-Version 4.9 oder höher ist.

Bei der Android 9-Version müssen nur Geräte, die mit der Android 9-Version auf den Markt kommen, die neue eBPF-Funktion haben. Bei Geräten, die mit einem Kernel geliefert wurden, der eBPF-Tools unterstützen kann, empfehlen wir, beim Upgrade auf Android 9 auf die neue eBPF-Funktion umzustellen. Es gibt keinen CTS-Test, um diese Aktualisierung durchzusetzen.

Zertifizierungsstufe

Sie sollten regelmäßig Patches aus den Android Common Kernels und Android AOSP main übernehmen. Ihre Implementierung muss die entsprechenden VTS- und CTS-Tests, den netd_unit_test und den libbpf_test bestehen.

Testen

Es gibt Kernel-net_tests, mit denen Sie prüfen können, ob die erforderlichen Funktionen aktiviert und die erforderlichen Kernel-Patches zurückportiert wurden. Die Tests sind Teil der VTS-Tests für die Android 9-Release. In system/netd/ gibt es einige Unit-Tests (netd_unit_test und libbpf_test). In netd_integration_test gibt es einige Tests, um das Gesamtverhalten des neuen Tools zu validieren.

CTS und CTS-Verifier

Da beide Module zur Verkehrsüberwachung in der Android 9-Version unterstützt werden, gibt es keinen CTS-Test, mit dem die Implementierung des neuen Moduls auf allen Geräten erzwungen werden kann. Bei Geräten mit einer Kernelversion höher als 4.9, die ursprünglich mit der Android 9-Version ausgeliefert wurden (d.h. die erste API-Ebene >= 28), gibt es CTS-Tests auf GSI, um zu prüfen, ob das neue Modul richtig konfiguriert ist. Mit alten CTS-Tests wie TrafficStatsTest, NetworkUsageStatsTest und CtsNativeNetTestCases lässt sich prüfen, ob das Verhalten mit dem alten UID-Modul übereinstimmt.

Manuelle Tests

Es gibt einige Unit-Tests in system/netd/ (netd_unit_test, netd_integration_test und libbpf_test). Dumpsys unterstützt die manuelle Prüfung des Status. Der Befehl dumpsys netd zeigt den grundlegenden Status des trafficController-Moduls und ob eBPF korrekt aktiviert ist. Wenn eBPF aktiviert ist, zeigt der Befehl dumpsys netd trafficcontroller den detaillierten Inhalt jeder eBPF-Map an, einschließlich getaggter Socket-Informationen, Statistiken pro Tag, UID und iface sowie der Übereinstimmung der Eigentümer-UID.

Teststandorte

CTS-Tests finden Sie hier:

Die VTS-Tests finden Sie unter https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py.

Die Unittests befinden sich hier: