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 spore syscalls 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 og seccomp bruges til at begrænse processernes evne til at oprette sockets ved at definere henholdsvis restricted policies og suppressing syscalls.

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”.