How to view network traffic requested by a specific app? There are lots of discussion on how to see which app is requesting network connection. I have tried the following apps:

tcapturepacket
wifi monitor
connection tracker


However, none of them was useful. For example, for a short period of time, I uploaded a 30KB pcap file which can be viewed here. Still I haven't find out which app is requesting connection and to where it is trying to connect.

I also tried to look at adb logcat, but didn't find useful information. Maybe something has been missed here. Any guess?
If you have rooted phone, go for nethogs (for live monitoring) or iptables (to get statistics) commandline tools. Using VPN or Android stats based apps is the only possible non-root solution. Or refer to this answer for a logcat/dumpsys based solution.



First of all, tracking a UID or PID of a network stream isn't straight forward because these aren't network related but OS related parameters. Proposals and abandoned projects do exist.

Android assigns a unique UID to every installed app just like every human user on Linux has a UID. So we can capture packets sent by a specific UID over the network interfaces to track the usage.  

TCPDUMP:

Now how we can capture network traffic? Most of the network sniffers use libpcap family of system-independent libraries for this purpose. It supports BSD Packet Filter (BPF) for in-kernel packet filtering. Some popular utilities that use libpcap include tcpdump, nmap, tshark/wireshark, dumpcap, nethogs etc. Android app Network Utilities and others also make use of tcpdump.

However UID info is not propagated through the AF_PACKET/PF_PACKET channel that pcap uses at OSI Layer 2. So what we can do here is to make use of network sockets (combination of IP and port) being created and used by an app. netstat -tup or ss -tup will show all network sockets with active/established connections. Both tools are available on Android (or you can get a static binary), ss is the newer one. Socket vs. UID information can also be directly read from /proc/net/{tcp,udp}. Android app Netstat Plus works on same principle. This will provide Local Address (socket) being used by a process.

Once we know what sockets are being used by an app (UID), tcpdump -i wlan0 src &lt;IP&gt; and port &lt;PORT&gt; will dump the whole traffic originated from that process.
Similarly a remote socket (if not connected to by multiple apps) can also be used for filtering results.

LIMITATIONS:

However there are some issues with this approach:


Android apps usually launch more than one process at a time in parallel i.e. multiple PIDs working under same UID. So we have to capture traffic from all processes.
Apps keep on creating and deleting sockets. Keeping track of continuously changing sockets is almost impossible particularly when there are a large number of apps accessing network simultaneously.
There is - though rare - possibility that local sockets are being shared by multiple processes on UNIX-like OS's. Remote shared sockets such as UDP/53 which is used for DNS resolution cannot be tracked for a single process. This further weakens the approach.


NetHogs traverses procfs and copes with the above limitations (though not always very successful):



IPTABLES:

The above described shortcomings of a Layer 2 tool can be mitigated using iptables LOG or NFLOG. Layer 2 is just above the Physical Layer i.e. it's the last thing packets encounter before leaving the device. That's why, being at Data Link Layer and working at lower level of net stack, BPF is a kind of stateless packet filtering mechanism as compared to netfilter / iptables which works at OSI Layer 3 (nearer to userspace programs). So iptables can also get information from TCP/IP stack (Layer 4). It filters packets based on their creator UIDs using module owner that interacts with sockets to find packet ownership.

iptables writes to kernel log which can be read using dmesg or logcat. UID of an app can be obtained using some app or read from /data/system/packages.list or pm list packages -U.

# iptables -I OUTPUT -m owner --uid-owner &lt;UID&gt; -j LOG --log-level 7 --log-prefix 'SNIFFER: ' --log-uid
# dmesg -w | grep SNIFFER


Output can be saved to a file and formatted using tools like grep, awk, printf etc. Network Log - though very outdated - works in similar way. AFWall+ is a firewall based on iptables that can log / notify an app's network activity when the app is blocked. 

The only downside with this approach is that it cannot be used to sniff traffic from one process when there are multiple processes running with same UID. iptables can't capture packets based on PIDs. They decided not to use iptables with processes because the process is started before it is blocked/sniffed, and program could easily spawn a child process with new PID which would not be blocked / sniffed. Also PIDs are created and destroyed as quick as sockets are. So there is always room for traffic being leaked.

QTAGUID:

owner module won't work for incoming or forwarded traffic because IP packets carry no ownership information. To measure per-app incoming / outgoing network usage, Android patched kernel to include qtaguid module. We can read statistics from /proc/net/xt_qtaguid/stats. With some shell scripting get live data usage since reboot:



However on Android 9+, qtaguid is being replaced with extended BPF (which is also planned to replace netfilter framework in Linux kernel). Related: Which process is responsible for capturing data usage?

IPTABLES + TCPDUMP:

An alternate is to put the outgoing traffic from an app in an NFLOG group and later tcpdump captures packets from that group:

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


This is to ensure that we get closer to physical layer when sniffing outgoing traffic. But it can still give false positives e.g. if packets are dropped / lost in routing tables. That's why sniffers work at OSI layer 2. Or even better is to watch from outside e.g. using a proxy / VPN server or on a tethered PC or at router. But this won't capture traffic on per UID/PID basis.

OTHER OPTIONS:


Use diagnostic tools like strace to track syscalls related to network activity of a process. force_bind and tracedump also work on same principle. Linux kernel's audit subsystem can be used for the same.
Use Network classifier cgroup with iptables NETFILTER_XT_MATCH_CGROUP to sniff traffic from certain process(es).
Use Network Namespaces to isolate processes and read data usage on per interface basis. nstrace works on same principle.
If the intention is entirely to block traffic originating from certain processes, SELinux and seccomp can be used to restrict the processes' ability to create sockets by defining restricted policies and suppressing syscalls respectively.


Most of these are not straightforwardly viable options for Android and require advanced configurations.



ANDROID'S APIs (NON-ROOT OPTIONS):

Some apps like NetGuard use VpnService API of Android to block traffic at Layer 3 (TUN interface). The app can "notify when an application accesses the internet". Per app capturing and tracking (1, 2) is possible using VPN API as Android makes use of UIDs and SOcket_MARKs (1, 2) to control traffic in network Routing Policy (RPDB), just before leaving the device.

Some apps like NetLive make use of NetworkStatsManager, but it lags the real-time usage and "does not update quickly enough", it's "meant to provide historical data".

NOTE: I've no affiliation with any app referenced.



RELATED:


Restricting an app to only send internet traffic but not receive that back?
Why network activity is detected from apps after firewall blocks them?
Capturing mobile phone traffic on Wireshark