eBPF-Verkehrsüberwachung

Das eBPF-Netzwerkverkehrstool verwendet eine Kombination aus Kernel- und User-Space-Implementierung, um die Netzwerknutzung auf dem Gerät seit dem letzten Gerätestart zu überwachen. Es bietet zusätzliche Funktionen wie Socket-Tagging, die Trennung von Vorder- und Hintergrundverkehr und eine UID-Firewall, um Apps je nach Telefonstatus vom Netzwerkzugriff zu blockieren. Die vom Tool gesammelten Statistiken werden in einer Kernel-Datenstruktur namens eBPF maps gespeichert und das Ergebnis wird von Diensten wie NetworkStatsService verwendet, um dauerhafte Verkehrsstatistiken seit dem letzten Start bereitzustellen.

Beispiele und Quelle

Die Userspace-Änderungen finden sich hauptsächlich in den system/netd und framework/base -Projekten. 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 finden sich 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 die eBPF-basierte Netzwerkverkehrsüberwachungsabrechnung verwenden. Die neue Infrastruktur ist flexibler und wartbarer und erfordert keinen Out-of-Tree-Kernel-Code.

Die wichtigsten Designunterschiede zwischen Legacy- und eBPF-Verkehrsüberwachung sind in Abbildung 1 dargestellt.

Unterschiede im Design der Legacy- und eBPF-Verkehrsüberwachung

Abbildung 1. Designunterschiede zwischen Legacy- (links) und eBPF-Verkehrsüberwachung (rechts).

Das neue trafficController Design basiert auf dem Per- cgroup eBPF-Filter sowie xt_bpf Netfilter-Modul im Kernel. Diese eBPF-Filter werden auf das gesendete/empfangende Paket angewendet, wenn es den Filter passiert. Der cgroup eBPF-Filter befindet sich auf der Transportschicht und ist dafür verantwortlich, den Datenverkehr abhängig von der Socket-UID und der Userspace-Einstellung anhand der richtigen UID zu zählen. Der xt_bpf Netzfilter ist an die bw_raw_PREROUTING und bw_mangle_POSTROUTING Ketten angeschlossen und dafür verantwortlich, den Datenverkehr für die richtige Schnittstelle zu zählen.

Beim Booten erstellt der Userspace-Prozess trafficController die für die Datenerfassung verwendeten eBPF-Karten und pinnen alle Karten als virtuelle Datei unter sys/fs/bpf an. Dann lädt der privilegierte Prozess bpfloader das vorkompilierte eBPF-Programm in den Kernel und hängt es an die richtige cgroup an. Es gibt eine einzige 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/deaktivieren, indem er in die traffic_cookie_tag_map “ und traffic_uid_counterSet_map schreibt. Der NetworkStatsService kann die Verkehrsstatistikdaten von traffic_tag_stats_map , traffic_uid_stats_map und traffic_iface_stats_map lesen. Neben der Funktion zum Sammeln von Verkehrsstatistiken sind der trafficController und cgroup eBPF-Filter je nach Telefoneinstellungen auch dafür verantwortlich, den Verkehr von bestimmten UIDs zu blockieren. Die UID-basierte Netzwerkverkehrsblockierungsfunktion ist ein Ersatz des xt_owner Moduls im Kernel und 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 Legacy-Implementierung des xt_qtaguid Moduls, 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 machen, ob xt_qtaguid oder eBPF-Tools im Hintergrund 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.

Anforderungen

  1. In der Kernel-Konfiguration 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 überprüfen, ob die richtige Konfiguration aktiviert ist.

Legacy-xt_qtaguid-Abwertungsprozess

Das neue eBPF-Tool ersetzt das xt_qtaguid Modul und das darauf basierende xt_owner Modul. Wir beginnen damit, das xt_qtaguid Modul aus dem Android-Kernel zu entfernen und seine unnötigen Konfigurationen zu deaktivieren.

In der Android 9-Version ist das Modul xt_qtaguid auf allen Geräten aktiviert, aber alle öffentlichen APIs, die die Proc-Datei des Moduls xt_qtaguid direkt lesen, werden in den NetworkManagement Service verschoben. Abhängig von der Kernelversion des Geräts und der ersten API-Ebene weiß der NetworkManagement Service, ob die eBPF-Tools aktiviert sind, und wählt das richtige Modul aus, um für jede App-Netzwerknutzungsstatistik abzurufen. Apps mit SDK-Level 28 und höher werden durch 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 Proc-Dateien vollständig blockiert. Wir werden damit beginnen, das xt_qtaguid Modul aus den neuen gemeinsamen Android-Kerneln zu entfernen. Nachdem es entfernt wurde, aktualisieren wir die Android-Basiskonfiguration für diese Kernel-Version, um das xt_qtaguid Modul explizit zu deaktivieren. Das xt_qtaguid Modul wird vollständig veraltet sein, wenn die Mindestanforderung an die Kernelversion für eine Android-Version 4.9 oder höher beträgt.

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 ausgeliefert werden, der eBPF-Tools unterstützt, empfehlen wir, ihn beim Upgrade auf die Android 9-Version auf die neue eBPF-Funktion zu aktualisieren. Es gibt keinen CTS-Test, um dieses Update durchzusetzen.

Validierung

Sie sollten regelmäßig Patches von Android Common Kernels und Android AOSP Main herunterladen. Stellen Sie sicher, dass Ihre Implementierung die entsprechenden VTS- und CTS-Tests, den netd_unit_test und den libbpf_test , besteht.

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 für die Android 9-Version integriert. Es gibt einige Unit-Tests 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, der die Implementierung des neuen Moduls auf allen Geräten erzwingt. Aber für Geräte mit einer Kernel-Version 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 ü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 übereinstimmt.

Manuelles Testen

Es gibt einige Unit-Tests 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 Grundstatus des trafficController Moduls und ob eBPF korrekt eingeschaltet ist. Wenn eBPF aktiviert ist, zeigt der Befehl dumpsys netd trafficcontroller den detaillierten Inhalt jeder eBPF-Karte an, einschließlich getaggter Socket-Informationen, Statistiken pro Tag, UID und iface sowie Eigentümer-UID-Übereinstimmung.

Teststandorte

CTS-Tests finden Sie unter:

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

Unit-Tests finden Sie unter: