Das eBPF-Netzwerkverkehrstool verwendet eine Kombination aus Kernel- und Userspace-Implementierung, um die Netzwerknutzung auf dem Gerät seit dem letzten Gerätestart zu überwachen. Es bietet zusätzliche Funktionen wie Socket-Tagging, Trennung von Vordergrund- und Hintergrunddatenverkehr und Per-UID-Firewall, um Apps den Netzwerkzugriff je nach Telefonstatus zu verweigern. Die vom Tool gesammelten Statistiken werden in einer Kernel-Datenstruktur namens eBPF maps
und das Ergebnis wird von Diensten wie NetworkStatsService
verwendet, um seit dem letzten Start dauerhafte Verkehrsstatistiken bereitzustellen.
Beispiele und Quelle
Die Userspace-Änderungen betreffen hauptsächlich die Projekte system/netd
und framework/base
. Die Entwicklung erfolgt in AOSP, sodass der AOSP-Code immer auf dem neuesten Stand ist. Die Quelle befindet sich hauptsächlich unter system/netd/server/TrafficController*
, system/netd/bpfloader
und system/netd/libbpf/
. Einige notwendige Framework-Änderungen gibt es auch in framework/base/
und system/core
.
Implementierung
Ab Android 9 MÜSSEN Android-Geräte, die auf Kernel 4.9 oder höher laufen und ursprünglich mit der P-Version ausgeliefert wurden, anstelle von xt_qtaguid
eine eBPF-basierte Überwachung des Netzwerkverkehrs verwenden. Die neue Infrastruktur ist flexibler und wartbarer und benötigt keinen Out-of-Tree-Kernel-Code.
Die wichtigsten Designunterschiede zwischen Legacy- und eBPF-Verkehrsüberwachung sind in Abbildung 1 dargestellt.
Abbildung 1. Designunterschiede bei Legacy- (links) und eBPF-Datenverkehrsüberwachung (rechts).
Das neue trafficController
Design basiert auf cgroup
eBPF-Filter sowie dem xt_bpf
-Netzfiltermodul im Kernel. Diese eBPF-Filter werden auf das Paket tx/rx angewendet, wenn sie den Filter passieren. Der cgroup
eBPF-Filter befindet sich auf der Transportschicht und ist dafür verantwortlich, den Datenverkehr gegen die richtige UID zu zählen, abhängig von der Socket-UID sowie der Benutzerbereichseinstellung. Der xt_bpf
ist an die bw_raw_PREROUTING
und bw_mangle_POSTROUTING
-Ketten angeschlossen und ist dafür verantwortlich, den Datenverkehr für die richtige Schnittstelle zu zählen.
Beim Booten erstellt der Userspace-Prozess trafficController
die eBPF-Karten, die für die Datenerfassung verwendet werden, und fixiert alle Karten als virtuelle Datei unter sys/fs/bpf
. Dann lädt der privilegierte Prozess bpfloader
das vorkompilierte eBPF-Programm in den Kernel und hängt es an die richtige cgroup
. Es gibt eine einzelne Root- cgroup
für den gesamten Datenverkehr, sodass der gesamte Prozess standardmäßig in dieser cgroup
enthalten sein sollte.
Zur Laufzeit kann der trafficController
einen Socket markieren/unmarkieren, indem er in die traffic_cookie_tag_map
und traffic_uid_counterSet_map
. Der NetworkStatsService
kann die Verkehrsstatistikdaten von traffic_tag_stats_map
, traffic_uid_stats_map
und traffic_iface_stats_map
. Neben der Funktion zum Sammeln von Verkehrsstatistiken sind der trafficController
und der cgroup
eBPF-Filter auch dafür verantwortlich, den Datenverkehr von bestimmten UIDs abhängig von den Telefoneinstellungen zu blockieren. Die UID-basierte Funktion zum Blockieren des Netzwerkverkehrs ist ein Ersatz für das Modul xt_owner
im Kernel, und der Detailmodus kann durch Schreiben in traffic_powersave_uid_map
, traffic_standby_uid_map
und traffic_dozable_uid_map
werden.
Die neue Implementierung folgt der Legacy xt_qtaguid
, sodass TrafficController
und NetworkStatsService
entweder mit der Legacy- oder der neuen Implementierung ausgeführt werden. Wenn die App öffentliche APIs verwendet, sollte es keinen Unterschied geben, ob xt_qtaguid
oder eBPF-Tools im Hintergrund verwendet werden.
Wenn der Gerätekernel auf dem allgemeinen Android-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.
Anforderungen
Die Kernel-Konfiguration MUSS die folgenden Konfigurationen aktiviert haben:
-
CONFIG_CGROUP_BPF=y
-
CONFIG_BPF=y
-
CONFIG_BPF_SYSCALL=y
-
CONFIG_NETFILTER_XT_MATCH_BPF=y
-
CONFIG_INET_UDP_DIAG=y
Der VTS-Kernel-Konfigurationstest ist hilfreich, wenn überprüft wird, ob die richtige Konfiguration aktiviert ist.
-
Das Gerät
MEM_LOCK
rlimit MUSS auf 8 MB oder mehr eingestellt werden.
Legacy-xt_qtaguid-Verfallsprozess
Das neue eBPF-Tool ersetzt das xt_qtaguid
-Modul und das xt_owner
-Modul, auf dem es basiert. Wir werden damit beginnen, das xt_qtaguid
-Modul aus dem Android-Kernel zu entfernen und seine unnötigen Konfigurationen zu 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
verschoben. Abhängig von der Kernelversion des Geräts und der ersten API-Ebene weiß der NetworkManagement
-Dienst, ob die eBPF-Tools aktiviert sind, und wählt das richtige Modul aus, um für jede App die Netzwerknutzungsstatistik abzurufen. Apps mit SDK-Level 28 und höher werden von sepolicy daran gehindert, auf xt_qtaguid
proc-Dateien zuzugreifen.
In der nächsten Android-Version nach 9 wird der App-Zugriff auf diese xt_qtaguid
Dateien vollständig blockiert. Wir werden damit beginnen, das xt_qtaguid
-Modul aus den neuen allgemeinen Android-Kerneln zu entfernen. Nachdem es entfernt wurde, aktualisieren wir die Android-Basiskonfiguration für diese Kernelversion, um das xt_qtaguid
-Modul explizit zu deaktivieren. Das xt_qtaguid
-Modul wird vollständig verworfen, wenn die minimale Kernel-Versionsanforderung für eine Android-Version 4.9 oder höher ist.
In der Android 9-Version müssen nur Geräte, die mit der Android 9-Version gestartet werden, über die neue eBPF-Funktion verfügen. Für Geräte, die mit einem Kernel geliefert wurden, der eBPF-Tools unterstützen kann, empfehlen wir, ihn beim Upgrade auf die Version Android 9 auf die neue eBPF-Funktion zu aktualisieren. Es gibt keinen CTS-Test, um dieses Update zu erzwingen.
Validierung
Sie sollten regelmäßig Patches von Android Common Kernels und Android AOSP Master nehmen. Stellen Sie sicher, dass Ihre Implementierung die anwendbaren VTS- und CTS-Tests, den netd_unit_test
und den libbpf_test
.
Testen
Es gibt Kernel net_tests , um sicherzustellen, dass Sie die erforderlichen Funktionen aktiviert und erforderliche Kernel-Patches zurückportiert haben. Die Tests sind als Teil der VTS-Tests der Version Android 9 integriert. Es gibt einige Komponententests in system/netd/
( netd_unit_test
und libbpf_test
). Es gibt einige Tests in netd_integration_test
, um das Gesamtverhalten des neuen Tools zu validieren.
CTS und CTS-Verifizierer
Da beide Verkehrsüberwachungsmodule in der Android 9-Version unterstützt werden, gibt es keinen CTS-Test, um die Implementierung des neuen Moduls auf allen Geräten zu erzwingen. Aber für Geräte mit einer Kernel-Version höher als 4.9, die ursprünglich mit der Android 9-Version (dh der ersten API-Ebene >= 28) ausgeliefert werden, gibt es CTS-Tests auf GSI, um zu überprüfen, ob das neue Modul korrekt konfiguriert ist. Alte CTS-Tests wie TrafficStatsTest
, NetworkUsageStatsTest
und CtsNativeNetTestCases
können verwendet werden, um zu überprüfen, ob das Verhalten mit dem alten UID-Modul konsistent ist.
Manuelles Testen
Es gibt einige Komponententests in system/netd/
( netd_unit_test
, netd_integration_test
und libbpf_test
). Es gibt dumpsys-Unterstützung für die manuelle Überprüfung des Status. Der Befehl dumpsys netd
zeigt den Grundzustand des trafficController
-Moduls und ob eBPF korrekt eingeschaltet ist. Wenn eBPF aktiviert ist, zeigt der Befehl dumpsys netd trafficcontroller
den detaillierten Inhalt jeder eBPF-Zuordnung an, einschließlich getaggter Socket-Informationen, Statistiken pro Tag, UID und iface und UID-Übereinstimmung des Besitzers.
Testorte
CTS-Tests befinden sich unter:
- https://android.googlesource.com/platform/cts/+/master/tests/tests/net/src/android/net/cts/TrafficStatsTest.java {: .external}
- https://android.googlesource.com/platform/cts/+/master/tests/tests/app.usage/src/android/app/usage/cts/NetworkUsageStatsTest.java {: .external}
- https://android.googlesource.com/platform/system/netd/+/master/tests/bpf_base_test.cpp {: .external}
VTS-Tests befinden sich unter https://android.googlesource.com/kernel/tests/+/master/net/test/bpf_test.py .
Einheitentests befinden sich unter:
- https://android.googlesource.com/platform/system/netd/+/master/libbpf/BpfNetworkStatsTest.cpp {: .external}
- https://android.googlesource.com/platform/system/netd/+/master/server/TrafficControllerTest.cpp {: .external}