Monitoraggio del traffico eBPF

Lo strumento per il traffico di rete eBPF utilizza una combinazione di implementazione del kernel e dello spazio utente per monitorare l'utilizzo della rete sul dispositivo dall'ultimo avvio del dispositivo. Fornisce funzionalità aggiuntive come il tagging dei socket, la separazione del traffico in primo piano/in background e il firewall per UID per bloccare l'accesso alla rete delle app a seconda dello stato del telefono. Le statistiche raccolte dallo strumento sono archiviate in una struttura dati del kernel chiamata eBPF maps e il risultato viene utilizzato da servizi come NetworkStatsService per fornire statistiche sul traffico persistenti dall'ultimo avvio.

Esempi e fonte

Le modifiche allo spazio utente riguardano principalmente i progetti system/netd e framework/base . Lo sviluppo viene eseguito in AOSP, quindi il codice AOSP sarà sempre aggiornato. La fonte si trova principalmente in system/netd/server/TrafficController* , system/netd/bpfloader e system/netd/libbpf/ . Alcuni cambiamenti necessari al framework sono presenti anche in framework/base/ e system/core .

Implementazione

A partire da Android 9, i dispositivi Android in esecuzione sul kernel 4.9 o versioni successive e originariamente forniti con la versione P DEVONO utilizzare la contabilità di monitoraggio del traffico di rete basata su eBPF anziché xt_qtaguid . La nuova infrastruttura è più flessibile e più manutenibile e non richiede alcun codice kernel fuori albero.

Le principali differenze di progettazione tra il monitoraggio del traffico legacy e quello eBPF sono illustrate nella Figura 1.

Differenze di progettazione del monitoraggio del traffico legacy ed eBPF

Figura 1. Differenze di progettazione del monitoraggio del traffico legacy (a sinistra) ed eBPF (a destra).

Il nuovo design trafficController è basato sul filtro cgroup eBPF così come sul modulo netfilter xt_bpf all'interno del kernel. Questi filtri eBPF vengono applicati ai pacchetti tx/rx quando passano attraverso il filtro. Il filtro cgroup eBPF si trova a livello di trasporto ed è responsabile del conteggio del traffico rispetto all'UID corretto in base all'UID del socket e all'impostazione dello spazio utente. Il netfilter xt_bpf è agganciato alla catena bw_raw_PREROUTING e bw_mangle_POSTROUTING ed è responsabile del conteggio del traffico rispetto all'interfaccia corretta.

Al momento dell'avvio, il processo dello spazio utente trafficController crea le mappe eBPF utilizzate per la raccolta dei dati e aggiunge tutte le mappe come file virtuale su sys/fs/bpf . Quindi il processo privilegiato bpfloader carica il programma eBPF precompilato nel kernel e lo collega al cgroup corretto. Esiste un singolo cgroup root per tutto il traffico, quindi tutto il processo dovrebbe essere incluso in quel cgroup per impostazione predefinita.

In fase di esecuzione, trafficController può contrassegnare/deselezionare un socket scrivendo su traffic_cookie_tag_map e traffic_uid_counterSet_map . Il NetworkStatsService può leggere i dati delle statistiche del traffico da traffic_tag_stats_map , traffic_uid_stats_map e traffic_iface_stats_map . Oltre alla funzione di raccolta delle statistiche sul traffico, trafficController e il filtro eBPF cgroup sono anche responsabili del blocco del traffico da determinati UID a seconda delle impostazioni del telefono. La funzionalità di blocco del traffico di rete basato su UID sostituisce il modulo xt_owner all'interno del kernel e la modalità dettagliata può essere configurata scrivendo su traffic_powersave_uid_map , traffic_standby_uid_map e traffic_dozable_uid_map .

La nuova implementazione segue l'implementazione del modulo xt_qtaguid legacy quindi TrafficController e NetworkStatsService verranno eseguiti con l'implementazione legacy o nuova. Se l'app utilizza API pubbliche, non dovrebbe verificarsi alcuna differenza se gli strumenti xt_qtaguid o eBPF vengono utilizzati in background.

Se il kernel del dispositivo è basato sul kernel comune Android 4.9 (SHA 39c856663dcc81739e52b02b77d6af259eb838f6 o versione successiva), non sono necessarie modifiche agli HAL, ai driver o al codice kernel per implementare il nuovo strumento eBPF.

Requisiti

  1. La configurazione del kernel DEVE avere queste seguenti configurazioni attivate:

    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

    Il test di configurazione del kernel VTS è utile quando si verifica che sia attivata la configurazione corretta.

Processo di deprecazione legacy xt_qtaguid

Il nuovo strumento eBPF sta sostituendo il modulo xt_qtaguid e il modulo xt_owner su cui è basato. Inizieremo a rimuovere il modulo xt_qtaguid dal kernel Android e a disabilitare le sue configurazioni non necessarie.

Nella versione Android 9, il modulo xt_qtaguid è attivato in tutti i dispositivi, ma tutte le API pubbliche che leggono direttamente il file proc del modulo xt_qtaguid vengono spostate nel NetworkManagement Service. A seconda della versione del kernel del dispositivo e del primo livello API, il servizio NetworkManagement sa se gli strumenti eBPF sono attivati ​​e sceglie il modulo giusto da ottenere per ciascuna statistica sull'utilizzo della rete dell'app. Alle app con livello SDK 28 e superiore viene impedito l'accesso ai file proc xt_qtaguid tramite sepolicy.

Nella prossima versione di Android successiva alla 9, l'accesso dell'app ai file proc xt_qtaguid sarà completamente bloccato, inizieremo a rimuovere il modulo xt_qtaguid dai nuovi kernel comuni di Android. Dopo averlo rimosso, aggiorneremo la configurazione di base di Android per quella versione del kernel per disattivare esplicitamente il modulo xt_qtaguid . Il modulo xt_qtaguid sarà completamente deprecato quando il requisito minimo della versione del kernel per una versione Android sarà 4.9 o successiva.

Nella versione Android 9, solo i dispositivi avviati con la versione Android 9 devono disporre della nuova funzionalità eBPF. Per i dispositivi forniti con un kernel in grado di supportare gli strumenti eBPF, consigliamo di aggiornarlo alla nuova funzionalità eBPF durante l'aggiornamento alla versione Android 9. Non esiste alcun test CTS per applicare tale aggiornamento.

Validazione

Dovresti prendere regolarmente le patch dai kernel comuni di Android e dal sistema principale di Android AOSP. Assicurati che la tua implementazione superi i test VTS e CTS applicabili, netd_unit_test e libbpf_test .

Test

Esistono dei net_test del kernel per garantire che le funzionalità richieste siano attivate e che le patch del kernel richieste siano sottoposte a backport. I test sono integrati come parte dei test VTS della versione Android 9. Ci sono alcuni test unitari in system/netd/ ( netd_unit_test e libbpf_test ). Ci sono alcuni test in netd_integration_test per validare il comportamento generale del nuovo strumento.

CTS e verificatore CTS

Poiché entrambi i moduli di monitoraggio del traffico sono supportati nella versione Android 9, non esiste alcun test CTS per forzare l'implementazione del nuovo modulo su tutti i dispositivi. Ma per i dispositivi con versione del kernel successiva alla 4.9 originariamente forniti con la versione Android 9 (ovvero il primo livello API >= 28), sono disponibili test CTS su GSI per verificare che il nuovo modulo sia configurato correttamente. I vecchi test CTS come TrafficStatsTest , NetworkUsageStatsTest e CtsNativeNetTestCases possono essere utilizzati per verificare che il comportamento sia coerente con il vecchio modulo UID.

Test manuale

Ci sono alcuni test unitari in system/netd/ ( netd_unit_test , netd_integration_test e libbpf_test ). È disponibile il supporto dumpsys per il controllo manuale dello stato. Il comando dumpsys netd mostra lo stato di base del modulo trafficController e se eBPF è attivato correttamente. Se eBPF è attivato, il comando dumpsys netd trafficcontroller mostra il contenuto dettagliato di ciascuna mappa eBPF, comprese le informazioni sui socket contrassegnati, le statistiche per tag, UID e iface e la corrispondenza dell'UID del proprietario.

Posizioni di prova

I test CTS si trovano presso:

I test VTS si trovano su https://android.googlesource.com/kernel/tests/+/main/net/test/bpf_test.py .

I test unitari si trovano in: