Hur man ser nätverkstrafik som begärs av en specifik app?

Om du har en rotad telefon kan du använda kommandoradsverktygen nethogs (för direktövervakning) eller iptables (för att få statistik). Att använda VPN eller Android-statistikbaserade appar är den enda möjliga lösningen utan rötter. Eller se det här svaret för en logcat/dumpsys-baserad lösning.

För det första är det inte helt enkelt att spåra ett UID eller PID för en nätverksström eftersom dessa inte är nätverksrelaterade utan OS-relaterade parametrar. Förslag och övergivna projekt finns.

Android tilldelar ett unikt UID till varje installerad app, precis som varje mänsklig användare på Linux har ett UID. Vi kan alltså fånga upp paket som skickas av ett specifikt UID över nätverksgränserna för att spåra användningen.

TCPDUMP:

Hur kan vi nu fånga nätverkstrafik? De flesta nätverkssniffare använder libpcap-familjen av systemoberoende bibliotek för detta ändamål. Den stöder BSD Packet Filter (BPF) för paketfiltrering i kärnan. Några populära verktyg som använder libpcap är tcpdump, nmap, tshark/wireshark, dumpcap, nethogs osv. Android-appen Network Utilities och andra använder också tcpdump.

Hur som helst sprids inte UID-information via AF_PACKET/PF_PACKET-kanalen som pcap använder i OSI Layer 2. Så vad vi kan göra här är att använda oss av nätverkssocklar (kombination av IP och port) som skapas och används av en app. netstat -tup eller ss -tup visar alla nätverksuttag med aktiva/etablerade anslutningar. Båda verktygen finns tillgängliga på Android (eller så kan du få en statisk binärfil), ss är det nyare verktyget. Information om socket vs UID kan också läsas direkt från /proc/net/{tcp,udp}. Android-appen Netstat Plus fungerar enligt samma princip. Den ger lokal adress (socket) som används av en process.

När vi vet vilka sockets som används av en app (UID), kommer tcpdump -i wlan0 src <IP> and port <PORT> att dumpa hela trafiken som härrör från den processen.
På samma sätt kan en fjärransluten socket (om den inte är ansluten till flera appar) också användas för att filtrera resultaten.

BEGRÄNSNINGAR:

Det finns dock vissa problem med detta tillvägagångssätt:

  • Androidappar startar vanligen mer än en process åt gången parallellt, dvs. flera PID:er arbetar under samma UID. Så vi måste fånga trafiken från alla processer.
  • Appar fortsätter att skapa och ta bort sockets. Att hålla reda på kontinuerligt förändrade sockets är nästan omöjligt, särskilt när ett stort antal program har tillgång till nätverket samtidigt.
  • Det finns en – om än sällsynt – möjlighet att lokala sockets delas av flera processer på UNIX-liknande operativsystem. Fjärrdelade sockets som UDP/53, som används för DNS-upplösning, kan inte spåras för en enskild process. Detta försvagar tillvägagångssättet ytterligare.

NetHogs korsar procfs och klarar ovanstående begränsningar (även om det inte alltid är särskilt framgångsrikt):

IPTABLES:

Ovanstående beskrivna brister hos ett Layer 2-verktyg kan mildras med hjälp av iptables LOG eller NFLOG. Layer 2 ligger precis ovanför det fysiska lagret, dvs. det är det sista som paketen möter innan de lämnar enheten. Eftersom BPF befinner sig i datalänkskiktet och arbetar på en lägre nivå i nätstapeln är BPF därför en slags tillståndslös paketfiltreringsmekanism jämfört med netfilter / iptables som arbetar i OSI-lager 3 (närmare program i användarutrymmet). Så iptables kan också få information från TCP/IP-stacken (lager 4). Den filtrerar paket baserat på deras skapare UID med hjälp av modulen owner som interagerar med sockets för att hitta paketens ägare.

iptables skriver till kärnans logg som kan läsas med hjälp av dmesg eller logcat. UID för en app kan erhållas med hjälp av någon app eller läsas från /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

Utput kan sparas till en fil och formateras med hjälp av verktyg som grep, awk, printf osv. Network Log – även om den är mycket föråldrad – fungerar på liknande sätt. AFWall+ är en brandvägg baserad på iptables som kan logga/anmäla en apps nätverksaktivitet när appen är blockerad.

Enda nackdelen med detta tillvägagångssätt är att det inte kan användas för att sniffa trafik från en process när det finns flera processer som körs med samma UID. iptables kan inte fånga upp paket baserat på PID. De bestämde sig för att inte använda iptables med processer eftersom processen startas innan den blockeras/sniffas, och programmet skulle lätt kunna skapa en barnprocess med nytt PID som inte skulle blockeras/sniffas. Dessutom skapas och förstörs PIDs lika snabbt som sockets. Så det finns alltid utrymme för att trafik kan läcka.

QTAGUID:

owner modulen kommer inte att fungera för inkommande eller vidarebefordrad trafik eftersom IP-paket inte innehåller någon ägarinformation. För att mäta inkommande och utgående nätverksanvändning per app har Android patchat kärnan för att inkludera qtaguid-modulen. Vi kan läsa statistik från /proc/net/xt_qtaguid/stats. Med några skalskript kan vi få fram levande dataanvändning sedan omstart:

Hursomhelst, på Android 9+ ersätts qtaguid med utökad BPF (som också planeras att ersätta netfilter-ramverket i Linuxkärnan). Relaterat:

IPTABLES + TCPDUMP:

Ett alternativ är att lägga den utgående trafiken från en app i en NFLOG-grupp och senare fångar tcpdump paket från den gruppen:

# iptables -I OUTPUT -m owner --uid-owner 1000 -j NFLOG --nflog-group 30# tcpdump -i nflog:30

Detta är för att se till att vi kommer närmare det fysiska lagret när vi sniffar utgående trafik. Men det kan fortfarande ge falska positiva resultat t.ex. om paket tappas/förloras i routningstabeller. Det är därför sniffare arbetar på OSI-lager 2. Eller ännu bättre är att titta utifrån, t.ex. med hjälp av en proxy-/VPN-server eller på en uppkopplad dator eller vid routern. Men detta kommer inte att fånga trafik per UID/PID.

ÖVRIGA MÖJLIGHETER:

  • Använd diagnostiska verktyg som strace för att spåra syscalls relaterat till nätverksaktivitet för en process. force_bind och tracedump fungerar också enligt samma princip. Linuxkärnans audit-subsystem kan användas för samma sak.
  • Använd nätverksklassificatorn cgroup med iptables NETFILTER_XT_MATCH_CGROUP för att sniffa trafik från vissa processer.
  • Använd Network Namespaces för att isolera processer och läsa av dataanvändning per gränssnitt. nstrace fungerar enligt samma princip.
  • Om avsikten helt och hållet är att blockera trafik som kommer från vissa processer kan SELinux och seccomp användas för att begränsa processernas förmåga att skapa sockets genom att definiera restricted policies respektive suppressing syscalls.

De flesta av dessa är inte direkt genomförbara alternativ för Android och kräver avancerade konfigurationer.

ANDROIDs API:er (NON-ROOT OPTIONS):

En del appar som NetGuard använder Androids VpnService API för att blockera trafik i lager 3 (TUN-gränssnitt). Appen kan ”meddela när ett program får tillgång till internet”. Det är möjligt att fånga och spåra (1, 2) per app med hjälp av VPN API eftersom Android använder UIDs och SOcket_MARKs (1, 2) för att kontrollera trafiken i nätverkets Routing Policy (RPDB), precis innan den lämnar enheten.

En del appar som NetLive använder sig av NetworkStatsManager, men den släpar efter i förhållande till användningen i realtid och ”uppdateras inte tillräckligt snabbt”, den är ”tänkt att tillhandahålla historiska data”.