Come visualizzare il traffico di rete richiesto da una specifica applicazione?
Se hai il telefono rootato, vai per nethogs
(per il monitoraggio live) o iptables
(per ottenere statistiche) strumenti da linea di comando. Usare VPN o app basate su statistiche Android è l’unica soluzione possibile non rootata. Oppure fare riferimento a questa risposta per una soluzione basata su logcat
/dumpsys
.
Prima di tutto, tracciare un UID o PID di un flusso di rete non è semplice perché questi non sono parametri legati alla rete ma al sistema operativo. Esistono proposte e progetti abbandonati.
Android assegna un UID unico ad ogni app installata proprio come ogni utente umano su Linux ha un UID. Quindi possiamo catturare i pacchetti inviati da uno specifico UID sulle interfacce di rete per tracciare l’utilizzo.
TCPDUMP:
Ora come possiamo catturare il traffico di rete? La maggior parte degli sniffer di rete usa la famiglia libpcap di librerie indipendenti dal sistema per questo scopo. Supporta BSD Packet Filter (BPF) per il filtraggio dei pacchetti nel kernel. Alcune utility popolari che usano libpcap
includono tcpdump
, nmap
, tshark/wireshark
, dumpcap
, nethogs
ecc. Anche le app Android Network Utilities e altre fanno uso di tcpdump
.
Tuttavia le informazioni UID non vengono propagate attraverso il canale AF_PACKET
/PF_PACKET
che pcap
utilizza a OSI Layer 2. Quindi quello che possiamo fare qui è utilizzare i socket di rete (combinazione di IP e porta) creati e utilizzati da un’applicazione. netstat -tup
o ss -tup
mostrerà tutti i socket di rete con connessioni attive/stabilite. Entrambi gli strumenti sono disponibili su Android (o puoi ottenere un binario statico), ss
è quello più recente. Le informazioni su socket e UID possono anche essere lette direttamente da /proc/net/{tcp,udp}
. L’app Android Netstat Plus funziona sullo stesso principio. Questo fornirà l’indirizzo locale (socket) utilizzato da un processo.
Una volta che sappiamo quali socket sono utilizzati da un’app (UID), tcpdump -i wlan0 src <IP> and port <PORT>
scaricherà l’intero traffico originato da quel processo.
Similmente un socket remoto (se non connesso da più app) può anche essere utilizzato per filtrare i risultati.
Limitazioni:
Tuttavia ci sono alcuni problemi con questo approccio:
- Le app Android di solito lanciano più di un processo alla volta in parallelo, cioè più PID che lavorano sotto lo stesso UID. Quindi dobbiamo catturare il traffico da tutti i processi.
- Le app continuano a creare e cancellare i socket. Tenere traccia dei socket che cambiano continuamente è quasi impossibile soprattutto quando c’è un gran numero di applicazioni che accedono alla rete simultaneamente.
- C’è – anche se rara – la possibilità che i socket locali siano condivisi da più processi sui sistemi operativi UNIX-like. I socket condivisi remoti come UDP/53 che è usato per la risoluzione DNS non possono essere tracciati per un singolo processo. Questo indebolisce ulteriormente l’approccio.
NetHogs attraversa procfs
e fa fronte alle limitazioni di cui sopra (anche se non sempre con molto successo):
IPTABLES:
I difetti sopra descritti di uno strumento Layer 2 possono essere mitigati usando iptables LOG
o NFLOG
. Il Layer 2 è appena sopra il Physical Layer, cioè è l’ultima cosa che i pacchetti incontrano prima di lasciare il dispositivo. Ecco perché, essendo al Data Link Layer e lavorando al livello più basso dello stack di rete, BPF è una sorta di meccanismo di filtraggio dei pacchetti stateless rispetto a netfilter
/ iptables
che lavora al Layer 3 OSI (più vicino ai programmi userspace). Quindi iptables
può anche ottenere informazioni dallo stack TCP/IP (Layer 4). Filtra i pacchetti in base agli UID dei loro creatori utilizzando il modulo owner
che interagisce con le prese per trovare la proprietà del pacchetto.
iptables
scrive nel log del kernel che può essere letto utilizzando dmesg
o logcat
. L’UID di un’applicazione può essere ottenuto usando qualche app o letto da /data/system/packages.list
o pm list packages -U
.
# iptables -I OUTPUT -m owner --uid-owner <UID> -j LOG --log-level 7 --log-prefix 'SNIFFER: ' --log-uid# dmesg -w | grep SNIFFER
L’output può essere salvato in un file e formattato usando strumenti come grep
, awk
, printf
ecc. Network Log – anche se molto datato – funziona in modo simile. AFWall+ è un firewall basato su iptables
che può registrare / notificare l’attività di rete di un’app quando questa è bloccata.
L’unico aspetto negativo di questo approccio è che non può essere utilizzato per fiutare il traffico di un processo quando ci sono più processi in esecuzione con lo stesso UID. iptables
non può catturare pacchetti basati su PID. Hanno deciso di non usare iptables
con i processi perché il processo viene avviato prima di essere bloccato/sniffato, e il programma potrebbe facilmente generare un processo figlio con un nuovo PID che non sarebbe bloccato/sniffato. Inoltre i PID sono creati e distrutti velocemente come i socket. Quindi c’è sempre spazio per la fuga di traffico.
QTAGUID:
owner
Il modulo non funziona per il traffico in entrata o inoltrato perché i pacchetti IP non portano informazioni sulla proprietà. Per misurare l’utilizzo della rete in entrata e in uscita per applicazione, Android ha patchato il kernel per includere il modulo qtaguid
. Possiamo leggere le statistiche da /proc/net/xt_qtaguid/stats
. Con un po’ di scripting di shell ottenere l’utilizzo dei dati in diretta dal riavvio:
Tuttavia su Android 9+, qtaguid
è stato sostituito con BPF esteso (che è anche previsto per sostituire netfilter
framework nel kernel Linux). Correlato: Quale processo è responsabile della cattura dell’utilizzo dei dati?
IPTABLES + TCPDUMP:
Un’alternativa è mettere il traffico in uscita da un’app in un gruppo NFLOG
e successivamente tcpdump cattura i pacchetti da quel gruppo:
# iptables -I OUTPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30# tcpdump -i nflog:30
Questo è per garantire che ci avviciniamo al livello fisico quando sniffiamo il traffico in uscita. Ma può ancora dare falsi positivi, ad esempio se i pacchetti vengono abbandonati / persi nelle tabelle di routing. Ecco perché gli sniffer lavorano al livello OSI 2. O ancora meglio è guardare dall’esterno, ad esempio utilizzando un proxy / server VPN o su un PC collegato o al router. Ma questo non catturerà il traffico su base UID/PID.
ALTRE OPZIONI:
- Utilizzare strumenti diagnostici come
strace
per tracciaresyscalls
relativi all’attività di rete di un processo. force_bind e tracedump lavorano anche sullo stesso principio. Il sottosistema di audit del kernel Linux può essere utilizzato per lo stesso. - Utilizzare il classificatore di rete cgroup con
iptables
NETFILTER_XT_MATCH_CGROUP
per sniffare il traffico da certi processi. - Utilizzare
Network Namespaces
per isolare i processi e leggere l’utilizzo dei dati su base di interfaccia. nstrace funziona sullo stesso principio. - Se l’intenzione è interamente quella di bloccare il traffico proveniente da certi processi,
SELinux
eseccomp
possono essere usati per limitare la capacità dei processi di creare socket definendo rispettivamente restrictedpolicies
e suppressingsyscalls
.
La maggior parte di queste non sono opzioni direttamente attuabili per Android e richiedono configurazioni avanzate.
APPI DI ANDROID (OPZIONI NON-ROOT):
Alcune applicazioni come NetGuard usano l’API VpnService di Android per bloccare il traffico al livello 3 (interfaccia TUN). L’app può “notificare quando un’applicazione accede a internet”. La cattura e il tracciamento (1, 2) per ogni app è possibile utilizzando l’API VPN in quanto Android fa uso di UIDs
e SOcket_MARKs
(1, 2) per controllare il traffico nella Routing Policy di rete (RPDB), appena prima di lasciare il dispositivo.
Alcune app come NetLive fanno uso di NetworkStatsManager, ma è in ritardo sull’utilizzo in tempo reale e “non si aggiorna abbastanza rapidamente”, è “destinato a fornire dati storici”.