eBPF-Verkehrsüberwachung

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.

Designunterschiede bei Legacy- und eBPF-Verkehrsüberwachung

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

  1. Die Kernel-Konfiguration MUSS die folgenden Konfigurationen aktiviert haben:

    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, wenn überprüft wird, ob die richtige Konfiguration aktiviert ist.

  2. 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:

VTS-Tests befinden sich unter https://android.googlesource.com/kernel/tests/+/master/net/test/bpf_test.py .

Einheitentests befinden sich unter: