Monitoraggio del traffico eBPF

Lo strumento per il monitoraggio del traffico di rete eBPF utilizza una combinazione di implementazione nello spazio utente e nel kernel per monitorare l'utilizzo della rete sul dispositivo dall'ultimo avvio. Fornisce funzionalità aggiuntive come il tagging delle socket, la separazione del traffico in primo piano/in background e il firewall per UID per bloccare l'accesso alla rete da parte delle app in base allo stato dello smartphone. Le statistiche raccolte dallo strumento vengono memorizzate in una struttura di dati del kernel chiamata eBPF maps e il risultato viene utilizzato da servizi come NetworkStatsService per fornire statistiche sul traffico permanenti dall'ultimo avvio.

Esempi e origine

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

Implementazione

A partire da Android 9, i dispositivi Android con kernel 4.9 o versioni successive e originariamente forniti con la release P DEVONO utilizzare il monitoraggio del traffico di rete basato su eBPF anziché xt_qtaguid. La nuova infrastruttura è più flessibile e più gestibile e non richiede codice del kernel out-of-tree.

Le principali differenze di progettazione tra il monitoraggio del traffico precedente 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 di trafficController si basa su cgroup filtro eBPF e su xt_bpf modulo netfilter all'interno del kernel. Questi filtri eBPF vengono applicati ai pacchetti tx/rx quando passano attraverso il filtro. Il filtro eBPF cgroup si trova nel livello di trasporto ed è responsabile del conteggio del traffico rispetto all'UID corretto, a seconda dell'UID della socket e dell'impostazione dello spazio utente. Il netfilter xt_bpf è agganciato alle catene bw_raw_PREROUTING e bw_mangle_POSTROUTING ed è responsabile del conteggio del traffico in base all'interfaccia corretta.

Al momento dell'avvio, il processo nello spazio utente trafficController crea le mappe eBPF impiegate per la raccolta dei dati e fissa tutte le mappe come file virtuale in sys/fs/bpf. Il processo privilegiato bpfloader carica il programma eBPF precompilato nel kernel e lo collega al cgroup corretto. Esiste un singolo cgroup di primo livello per tutto il traffico, pertanto l'intera procedura dovrebbe essere inclusa in questo cgroup per impostazione predefinita.

In fase di esecuzione, trafficController può taggare/scollegare un socket scrivendo in traffic_cookie_tag_map e traffic_uid_counterSet_map. NetworkStatsService può leggere i dati delle statistiche sul traffico da traffic_tag_stats_map, traffic_uid_stats_map e traffic_iface_stats_map. Oltre alla funzione di raccolta delle statistiche sul traffico, il filtro eBPF trafficController e cgroup è responsabile anche del blocco del traffico da determinati UID a seconda delle impostazioni dello smartphone. La funzionalità di blocco del traffico di rete basata su UID è un'alternativa al modulo xt_owner all'interno del kernel e la modalità di dettaglio può essere configurata scrivendo in traffic_powersave_uid_map, traffic_standby_uid_map e traffic_dozable_uid_map.

La nuova implementazione segue l'implementazione precedente del modulo xt_qtaguid, quindi TrafficController e NetworkStatsService verranno eseguite con la precedente o con la nuova. Se l'app utilizza API pubbliche, non dovrebbe notare alcuna differenza tra l'utilizzo in background degli strumenti xt_qtaguid o eBPF.

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

Requisiti

  1. La configurazione del kernel DEVE avere le seguenti configurazioni attive:

    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 della configurazione del kernel VTS è utile per verificare che sia attivata la configurazione corretta.

Procedura di ritiro del parametro xt_qtaguid legacy

Il nuovo strumento eBPF sostituirà il moduloxt_qtaguid e il moduloxt_owner su cui si basa. Inizieremo a rimuovere il modulo xt_qtaguid dal kernel Android e a disattivare le relative configurazioni non necessarie.

Nella release di Android 9, il modulo xt_qtaguid è attivo su tutti i dispositivi, ma tutte le API pubbliche che leggono direttamente il file proc del modulo xt_qtaguid vengono spostate nel servizio NetworkManagement. A seconda della versione del kernel del dispositivo e del primo livello API, il servizio NetworkManagement sa se gli strumenti eBPF sono attivi e sceglie il modulo giusto da ottenere per ogni statistica di utilizzo della rete dell'app. Le app con SDK di livello 28 e superiori non possono accedere ai file procedura xt_qtaguid dal sepolicy.

Nella prossima release di Android dopo la 9, l'accesso delle app a questi file proc xt_qtaguid verrà completamente bloccato e inizieremo a rimuovere il modulo xt_qtaguid dai nuovi kernel comuni di Android. Dopo la rimozione, aggiorneremo la configurazione di base di Android per quella versione del kernel in modo da disattivare esplicitamente il modulo xt_qtaguid. Il modulo xt_qtaguid verrà ritirato completamente quando il requisito di versione minima del kernel per una release di Android è 4.9 o superiore.

Nella release di Android 9, solo i dispositivi lanciati con la release di Android 9 devono disporre della nuova funzionalità eBPF. Per i dispositivi forniti con un kernel in grado di supportare gli strumenti eBPF, consigliamo di aggiornarli alla nuova funzionalità eBPF durante l'upgrade alla release Android 9. Non esiste un test CTS per applicare questo aggiornamento.

Convalida

Dovresti prendere regolarmente le patch dai kernel comuni di Android e da Android AOSP main. Assicurati che l'implementazione superi i test VTS e CTS applicabili, il netd_unit_test e il libbpf_test.

Test

Esistono test di rete del kernel per assicurarti di aver attivato le funzionalità richieste e di aver eseguito il backport delle patch del kernel necessarie. I test sono integrati come parte dei test VTS della release di Android 9. Esistono alcuni test delle unità in system/netd/ (netd_unit_test e libbpf_test). Esistono alcuni test in netd_integration_test per convalidare il comportamento complessivo del nuovo strumento.

CTS e CTS verifier

Poiché entrambi i moduli di monitoraggio del traffico sono supportati nella release Android 9, non esiste un test CTS per forzare l'implementazione del nuovo modulo su tutti i dispositivi. Tuttavia, per i dispositivi con versione del kernel superiore a 4.9 forniti originariamente con la release Android 9 (ovvero il primo livello API >= 28), sono disponibili test CTS su GSI per convalidare il nuovo modulo è configurato correttamente. È possibile utilizzare vecchi test CTS come TrafficStatsTest, NetworkUsageStatsTest e CtsNativeNetTestCases per verificare il comportamento in modo che sia coerente con il modulo UID precedente.

Test manuale

Sono disponibili alcuni test delle unità in system/netd/ (netd_unit_test, netd_integration_test e libbpf_test). È disponibile il supporto di dumpsys per il controllo manuale dello stato. Il comando dumpsys netd mostra lo stato di base del modulo trafficController e se eBPF è correttamente attivato. Se eBPF è attivo, il comando dumpsys netd trafficcontroller mostra i contenuti dettagliati di ogni mappa eBPF, incluse le informazioni sui socket con tag, le statistiche per tag, l'UID e iface e la corrispondenza dell'UID del proprietario.

Sedi di test

I test CTS si trovano all'indirizzo:

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

I test delle unità si trovano in: