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 notwendige Framework-Änderungen finden Sie auch in framework/base/ und system/core.

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 dem Legacy- und dem eBPF-Traffic-Monitoring sind in Abbildung 1 dargestellt.

Unterschiede zwischen der Legacy- und der eBPF-Verkehrsüberwachung

Abbildung 1. Unterschiede beim Design der Legacy- (links) und eBPF-Verkehrsüberwachung (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. Der Netfilter xt_bpf wird an die Kette bw_raw_PREROUTING und bw_mangle_POSTROUTING angehängt und ist für die Zählung des Traffics für die richtige Schnittstelle verantwortlich.

Beim Booten erstellt der Userspace-Prozess trafficController die eBPF-Karten, die für die Datenerhebung verwendet werden, und pinnen alle Karten 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. Da es für den gesamten Traffic eine einzige Stamm-cgroup gibt, sollte der gesamte Prozess standardmäßig in dieser cgroup enthalten sein.

Während der Laufzeit kann der trafficController einen Socket taggen oder enttippen, 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 Anwendung öffentliche APIs verwendet, sollte es keinen Unterschied geben, ob xt_qtaguid- oder eBPF-Tools im Hintergrund verwendet werden.

Wenn der Geräte-Kernel 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.

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 Modul xt_qtaguid und das Modul xt_owner, auf dem es basiert. Wir beginnen damit, das xt_qtaguid-Modul aus dem Android-Kernel zu entfernen und die unnötigen Konfigurationen zu deaktivieren.

In Android 9 ist das Modul xt_qtaguid auf allen Geräten aktiviert, aber alle öffentlichen APIs, die die Modulproc-Datei xt_qtaguid direkt lesen, werden in den Dienst NetworkManagement verschoben. Abhängig von der Kernel-Version des Geräts und der ersten API-Ebene weiß der NetworkManagement-Dienst, ob eBPF-Tools aktiviert sind, und wählt das richtige Modul für jede Statistik zur Netzwerknutzung der App aus. Apps mit SDK-Level 28 und höher können durch sepolicy nicht auf xt_qtaguid-Prozessdateien zugreifen.

Im nächsten Android-Release nach 9 wird der App-Zugriff auf diese xt_qtaguid-Proc-Dateien vollständig blockiert. Wir beginnen damit, das xt_qtaguid-Modul aus den neuen allgemeinen Android-Kerneln 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 mit einem Kernel, der eBPF-Tools unterstützt, empfehlen wir, beim Upgrade auf Android 9 auf die neue eBPF-Funktion zu aktualisieren. Es gibt keinen CTS-Test, um diese Aktualisierung zu erzwingen.

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 Release-Versionen von Android 9. 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-Verifizierung

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. Für Geräte 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 können Sie das Verhalten prüfen, damit es mit dem alten UID-Modul konsistent ist.

Manuelle Tests

In system/netd/ gibt es einige Einheitentests (netd_unit_test, netd_integration_test und libbpf_test). Dumpsys unterstützt die manuelle Statusprüfung. Der Befehl dumpsys netd zeigt den grundlegenden Status des trafficController-Moduls und ob eBPF richtig 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.

Testorte

CTS-Tests finden Sie hier:

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

Die Unittests finden Sie hier: