Hvordan kan du se netværkstrafik, der anmodes om af en bestemt app?
Hvis du har en rooted telefon, skal du gå til nethogs
(for live overvågning) eller iptables
(for at få statistik) kommandolinjeværktøjer. Brug af VPN eller Android-statistikbaserede apps er den eneste mulige løsning uden rod. Eller se dette svar for en logcat
/dumpsys
-baseret løsning.
Først og fremmest er det ikke ligetil at spore et UID eller PID for en netværksstrøm, fordi disse ikke er netværksrelaterede, men OS-relaterede parametre. Der findes forslag og opgivne projekter.
Android tildeler et unikt UID til hver installeret app, ligesom alle menneskelige brugere på Linux har et UID. Så vi kan fange pakker, der sendes af et bestemt UID over netværksgrænsefladerne for at spore brugen.
TCPDUMP:
Nu hvordan kan vi fange netværkstrafikken? De fleste netværkssniffere bruger libpcap-familien af systemuafhængige biblioteker til dette formål. Den understøtter BSD Packet Filter (BPF) til in-kernel pakkefiltrering. Nogle populære hjælpeprogrammer, der bruger libpcap
, omfatter tcpdump
, nmap
, tshark/wireshark
, dumpcap
, nethogs
osv. Android-appen Network Utilities og andre gør også brug af tcpdump
.
Hvorimod UID-info ikke udbredes gennem AF_PACKET
/PF_PACKET
-kanalen, som pcap
bruger i OSI-lag 2. Så det, vi kan gøre her, er at gøre brug af netværkssoketter (kombination af IP og port), der oprettes og bruges af en app. netstat -tup
eller ss -tup
vil vise alle netværkssoketter med aktive/etablerede forbindelser. Begge værktøjer er tilgængelige på Android (eller du kan få en statisk binær), ss
er den nyere. Socket vs. UID-oplysninger kan også læses direkte fra /proc/net/{tcp,udp}
. Android-appen Netstat Plus fungerer efter samme princip. Dette vil give Local Address (socket), der bruges af en proces.
Når vi ved, hvilke sockets der bruges af en app (UID), vil tcpdump -i wlan0 src <IP> and port <PORT>
dumpe hele trafikken, der stammer fra den pågældende proces.
Sådan kan en ekstern socket (hvis den ikke er forbundet til af flere apps) også bruges til at filtrere resultater.
BEGRÆNSNINGER:
Der er dog nogle problemer med denne fremgangsmåde:
- Android-apps starter normalt mere end én proces ad gangen parallelt, dvs. flere PID’er, der arbejder under samme UID. Så vi er nødt til at opfange trafik fra alle processer.
- Apps bliver ved med at oprette og slette sockets. Det er næsten umuligt at holde styr på de sockets, der hele tiden ændrer sig, især når der er et stort antal apps, der har adgang til netværket samtidig.
- Der er – om end sjældent – mulighed for, at lokale sockets deles af flere processer på UNIX-lignende OS’er. Fjerntliggende delte sockets som f.eks. UDP/53, der bruges til DNS-opløsning, kan ikke spores for en enkelt proces. Dette svækker tilgangen yderligere.
NetHogs gennemløber procfs
og klarer ovenstående begrænsninger (om end ikke altid med stor succes):
IPTABLES:
De ovenfor beskrevne mangler ved et Layer 2-værktøj kan afhjælpes ved hjælp af iptables LOG
eller NFLOG
. Lag 2 ligger lige over det fysiske lag, dvs. det er det sidste, som pakkerne møder, inden de forlader enheden. Derfor er BPF, der befinder sig i Data Link Layer og arbejder på et lavere niveau i netstakken, en slags tilstandsløs pakkefiltreringsmekanisme sammenlignet med netfilter
/ iptables
, der arbejder i OSI Layer 3 (tættere på programmer i brugerrummet). Så iptables
kan også få oplysninger fra TCP/IP-stakken (lag 4). Den filtrerer pakker baseret på deres creator UID’er ved hjælp af modul owner
, der interagerer med sockets for at finde pakkens ejerskab.
iptables
skriver til kernel log, som kan læses ved hjælp af dmesg
eller logcat
. UID for en app kan fås ved hjælp af en eller anden app eller læses fra /data/system/packages.list
eller 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
Output kan gemmes til en fil og formateres ved hjælp af værktøjer som grep
, awk
, printf
osv. Network Log – selv om den er meget forældet – fungerer på lignende måde. AFWall+ er en firewall baseret på iptables
, der kan logge / give besked om en app’s netværksaktivitet, når app’en er blokeret.
Den eneste ulempe ved denne fremgangsmåde er, at den ikke kan bruges til at sniffe trafik fra en proces, når der kører flere processer med samme UID. iptables
kan ikke opfange pakker baseret på PID’er. De besluttede ikke at bruge iptables
med processer, fordi processen startes, før den blokeres/sniffes, og program kunne nemt spawne en børneproces med nyt PID, som ikke ville blive blokeret/sniffet. Desuden oprettes og destrueres PID’er lige så hurtigt som sockets. Så der er altid plads til, at trafik kan blive lækket.
QTAGUID:
owner
modulet vil ikke fungere for indgående eller videresendt trafik, fordi IP-pakker ikke bærer nogen ejerskabsinformation. For at måle indgående/udgående netværksforbrug pr. app patched Android kernen til at inkludere qtaguid
modulet. Vi kan læse statistik fra /proc/net/xt_qtaguid/stats
. Med noget shell-scripting får vi live dataforbrug siden genstart:
Men på Android 9+ bliver qtaguid
erstattet af udvidet BPF (som også er planlagt til at erstatte netfilter
-rammen i Linux-kernen). Relateret:
IPTABLES + TCPDUMP:
Et alternativ er at lægge den udgående trafik fra en app i en NFLOG
gruppe og senere tcpdump fanger pakker fra denne gruppe:
# iptables -I OUTPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30# tcpdump -i nflog:30
Dette er for at sikre, at vi kommer tættere på det fysiske lag, når vi sniffer den udgående trafik. Men det kan stadig give falske positiver f.eks. hvis pakker er droppet / tabt i routing tabeller. Det er derfor sniffere arbejder på OSI lag 2. Eller endnu bedre er at se udefra f.eks. ved hjælp af en proxy / VPN-server eller på en tethered PC eller ved router. Men dette vil ikke fange trafik på per UID/PID basis.
ANDRE OPTIONER:
- Brug diagnostiske værktøjer som
strace
til at sporesyscalls
relateret til netværksaktivitet i en proces. force_bind og tracedump fungerer også efter samme princip. Linux-kernens audit-undersystem kan bruges til det samme. - Brug netværksklassifikator cgroup med
iptables
NETFILTER_XT_MATCH_CGROUP
til at sniffe trafik fra bestemte processer. - Brug
Network Namespaces
til at isolere processer og læse dataforbrug pr. grænseflade. nstrace fungerer efter samme princip. - Hvis hensigten udelukkende er at blokere trafik, der stammer fra visse processer, kan
SELinux
ogseccomp
bruges til at begrænse processernes evne til at oprette sockets ved at definere henholdsvis restrictedpolicies
og suppressingsyscalls
.
De fleste af disse er ikke umiddelbart anvendelige muligheder for Android og kræver avancerede konfigurationer.
ANDROID’S API’er (NON-ROOT OPTIONS):
Nogle apps som NetGuard bruger VpnService API i Android til at blokere trafik på lag 3 (TUN-grænseflade). Appen kan “give besked, når et program får adgang til internettet”. Per app er det muligt at opfange og spore (1, 2) ved hjælp af VPN API, da Android gør brug af UIDs
og SOcket_MARKs
(1, 2) til at kontrollere trafikken i netværkets Routing Policy (RPDB), lige før den forlader enheden.
Nogle apps som NetLive gør brug af NetworkStatsManager, men den halter i forhold til realtidsbrug og “opdateres ikke hurtigt nok”, den er “beregnet til at levere historiske data”.