Hoe het netwerkverkeer te bekijken dat door een specifieke app wordt opgevraagd?

Als je een geroote telefoon hebt, ga dan voor nethogs (voor live monitoring) of iptables (om statistieken te krijgen) commandline tools. Het gebruik van VPN of Android stats gebaseerde apps is de enige mogelijke niet-root oplossing. Of raadpleeg dit antwoord voor een logcat/dumpsys gebaseerde oplossing.

First of all, het volgen van een UID of PID van een netwerkstream is niet rechttoe rechtaan omdat deze niet netwerkgerelateerd zijn maar OS-gerelateerde parameters. Voorstellen en verlaten projecten bestaan wel.

Android wijst een unieke UID toe aan elke geïnstalleerde app, net zoals elke menselijke gebruiker op Linux een UID heeft. Dus kunnen we pakketten vangen die door een specifieke UID over de netwerk interfaces worden verzonden om het gebruik te volgen.

TCPDUMP:

Nu, hoe kunnen we netwerkverkeer vastleggen? De meeste netwerk sniffers gebruiken libpcap familie van systeem-onafhankelijke bibliotheken voor dit doel. Het ondersteunt BSD Packet Filter (BPF) voor in-kernel pakket filtering. Enkele populaire utilities die libpcap gebruiken zijn tcpdump, nmap, tshark/wireshark, dumpcap, nethogs enz. Android app Network Utilities en anderen maken ook gebruik van tcpdump.

Hoewel UID info niet wordt doorgegeven via het AF_PACKET/PF_PACKET kanaal dat pcap gebruikt op OSI Layer 2. Dus wat we hier kunnen doen is gebruik maken van netwerk sockets (combinatie van IP en poort) die worden aangemaakt en gebruikt door een app. netstat -tup of ss -tup zal alle netwerk sockets tonen met actieve/gevestigde verbindingen. Beide tools zijn beschikbaar op Android (of je kunt een statische binary krijgen), ss is de nieuwere. Socket vs. UID informatie kan ook direct worden gelezen uit /proc/net/{tcp,udp}. Android app Netstat Plus werkt volgens hetzelfde principe. Dit geeft het lokale adres (socket) dat wordt gebruikt door een proces.

Zodra we weten welke sockets worden gebruikt door een app (UID), tcpdump -i wlan0 src <IP> and port <PORT> zal het hele verkeer afkomstig van dat proces dumpen.
Ook een remote socket (indien niet verbonden met meerdere apps) kan worden gebruikt voor het filteren van resultaten.

LIMIETEN:

Er zijn echter een aantal problemen met deze aanpak:

  • Android apps starten meestal meer dan een proces tegelijk in parallel, dat wil zeggen meerdere PID’s werken onder dezelfde UID. Dus we moeten het verkeer van alle processen vast te leggen.
  • Apps blijven maken en verwijderen van sockets. Het bijhouden van continu veranderende sockets is bijna onmogelijk, vooral wanneer er een groot aantal apps tegelijkertijd op het netwerk werken.
  • Er is – hoewel zeldzaam – een mogelijkheid dat lokale sockets worden gedeeld door meerdere processen op UNIX-achtige OS’en. Gedeelde sockets op afstand, zoals UDP/53, dat wordt gebruikt voor DNS-resolutie, kunnen niet worden gevolgd voor een enkel proces. Dit verzwakt de aanpak nog meer.

NetHogs doorkruist procfs en gaat om met de bovenstaande beperkingen (hoewel niet altijd erg succesvol):

IPTABLES:

De hierboven beschreven tekortkomingen van een Layer 2 tool kunnen worden ondervangen met behulp van iptables LOG of NFLOG. Layer 2 staat net boven de Physical Layer, d.w.z. het is het laatste waar pakketten tegenaan lopen voordat ze het apparaat verlaten. Daarom is BPF, omdat het op de Data Link Layer zit en op een lager niveau van de net stack werkt, een soort stateless pakket filtering mechanisme in vergelijking met netfilter / iptables die op OSI Layer 3 werkt (dichter bij userspace programma’s). Dus iptables kan ook informatie krijgen van de TCP/IP stack (Laag 4). Het filtert pakketten op basis van UID’s van de maker met behulp van module owner die interacteert met sockets om het eigendom van pakketten te achterhalen.

iptables schrijft naar kernel log dat kan worden gelezen met dmesg of logcat. UID van een app kan worden verkregen met behulp van een app of worden gelezen uit /data/system/packages.list of 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 worden opgeslagen in een bestand en geformatteerd met behulp van tools zoals grep, awk, printf etc. Network Log – hoewel sterk verouderd – werkt op vergelijkbare wijze. AFWall+ is een firewall gebaseerd op iptables die de netwerkactiviteit van een app kan loggen / melden wanneer de app wordt geblokkeerd.

Het enige nadeel van deze aanpak is dat het niet kan worden gebruikt om verkeer van één proces te sniffen als er meerdere processen met dezelfde UID draaien. iptables kan geen pakketten vangen op basis van PID’s. Ze besloten om iptables niet te gebruiken met processen omdat het proces wordt gestart voordat het wordt geblokkeerd/gesnuffeld, en het programma gemakkelijk een kind-proces zou kunnen spawnen met een nieuw PID dat niet zou worden geblokkeerd/gesnuffeld. Ook worden PID’s net zo snel aangemaakt en vernietigd als sockets. Er is dus altijd ruimte voor gelekt verkeer.

QTAGUID:

owner module werkt niet voor inkomend of doorgestuurd verkeer omdat IP-pakketten geen eigendomsinformatie bevatten. Om per-app inkomend / uitgaand netwerkgebruik te meten, heeft Android de kernel gepatcht om qtaguid module op te nemen. We kunnen statistieken lezen van /proc/net/xt_qtaguid/stats. Met wat shell scripting krijgen live data gebruik sinds reboot:

Maar op Android 9+, qtaguid wordt vervangen door uitgebreide BPF (die ook is gepland om netfilter framework in Linux kernel te vervangen). Gerelateerd: Welk proces is verantwoordelijk voor het vastleggen van gegevensgebruik?

IPTABLES + TCPDUMP:

Een alternatief is om het uitgaande verkeer van een app in een NFLOG groep te zetten en later tcpdump pakketten van die groep vastlegt:

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

Dit is om ervoor te zorgen dat we dichter bij de fysieke laag komen bij het snuiven van uitgaand verkeer. Maar het kan nog steeds valse positieven geven, b.v. als pakketten gedropt worden / verloren gaan in routing tabellen. Dat is waarom sniffers werken op OSI laag 2. Of nog beter is om van buitenaf te kijken, b.v. via een proxy / VPN server of op een getethered PC of bij een router. Maar dit vangt geen verkeer op per UID/PID basis.

ANDERE OPTIES:

  • Gebruik diagnostische tools zoals strace om syscalls gerelateerd aan netwerk activiteit van een proces op te sporen. force_bind en tracedump werken ook volgens hetzelfde principe. Linux kernel’s audit subsysteem kan voor hetzelfde worden gebruikt.
  • Gebruik Netwerk classifier cgroup met iptables NETFILTER_XT_MATCH_CGROUP om verkeer van bepaalde processen te sniffen.
  • Gebruik Network Namespaces om processen te isoleren en data gebruik te lezen op per interface basis. nstrace werkt op hetzelfde principe.
  • Als het volledig de bedoeling is om verkeer afkomstig van bepaalde processen te blokkeren, kunnen SELinux en seccomp worden gebruikt om de mogelijkheid van de processen om sockets te maken te beperken door het definiëren van respectievelijk restricted policies en suppressing syscalls.

De meeste van deze zijn niet direct uitvoerbare opties voor Android en vereisen geavanceerde configuraties.

ANDROID’S API’s (NON-ROOT OPTIES):

Sommige apps zoals NetGuard gebruiken VpnService API van Android om verkeer te blokkeren op Layer 3 (TUN interface). De app kan “melden wanneer een toepassing het internet opgaat”. Per app vastleggen en volgen (1, 2) is mogelijk met behulp van VPN API als Android maakt gebruik van UIDs en SOcket_MARKs (1, 2) om het verkeer te controleren in het netwerk Routing Policy (RPDB), net voor het verlaten van het apparaat.

Sommige apps zoals NetLive maken gebruik van NetworkStatsManager, maar het loopt achter op het real-time gebruik en “werkt niet snel genoeg bij”, het is “bedoeld om historische gegevens te verstrekken”.