Como visualizar o tráfego de rede solicitado por um aplicativo específico?

Se você tem o telefone raiz, vá para nethogs (para monitoramento ao vivo) ou iptables (para obter estatísticas) ferramentas de linha de comando. Usando aplicações baseadas em VPN ou Android é a única solução não root possível. Ou consulte esta resposta para uma solução baseada em logcat/dumpsys.

Primeiro de tudo, rastrear um UID ou PID de um fluxo de rede não é direto porque estes não estão relacionados à rede, mas aos parâmetros relacionados ao SO. Propostas e projetos abandonados existem.

Android atribui um UID único a cada aplicativo instalado, assim como todo usuário humano no Linux tem um UID. Assim, podemos capturar pacotes enviados por um UID específico através das interfaces de rede para rastrear o uso.

TCPDUMP:

Agora como podemos capturar o tráfego da rede? A maioria dos sniffers de rede usa a família libpcap de bibliotecas independentes do sistema para este propósito. Ele suporta BSD Packet Filter (BPF) para filtragem de pacotes no kernel. Alguns utilitários populares que usam libpcap incluem tcpdump, nmap, tshark/wireshark, dumpcap, nethogs, etc. Utilitários de rede do aplicativo Android e outros também fazem uso de tcpdump.

No entanto a informação do UID não é propagada através do canal AF_PACKET/PF_PACKET que pcap usa na camada 2 do OSI. Então o que podemos fazer aqui é fazer uso de soquetes de rede (combinação de IP e porta) sendo criados e usados por um aplicativo. netstat -tup ou ss -tup irá mostrar todos os soquetes de rede com conexões ativas/estabelecidas. Ambas as ferramentas estão disponíveis no Android (ou você pode obter um binário estático), ss é o mais recente. As informações do soquete vs. UID também podem ser lidas diretamente de /proc/net/{tcp,udp}. O aplicativo Netstat Plus do Android funciona com o mesmo princípio. Isto irá fornecer Endereço Local (socket) sendo usado por um processo.

Após sabermos quais sockets estão sendo usados por um aplicativo (UID), tcpdump -i wlan0 src <IP> and port <PORT> irá despejar todo o tráfego originado por esse processo.
Simplesmente um socket remoto (se não conectado por vários aplicativos) também pode ser usado para filtrar os resultados.

LIMITAÇÕES:

No entanto existem alguns problemas com esta abordagem:

  • As aplicações Android normalmente lançam mais de um processo de cada vez em paralelo, ou seja, múltiplos PIDs trabalhando sob o mesmo UID. Então temos que capturar tráfego de todos os processos.
  • Aplicações continuam a criar e apagar soquetes. É quase impossível acompanhar a mudança contínua de soquetes, particularmente quando há um grande número de aplicativos acessando a rede simultaneamente.
  • Existe – embora raro – a possibilidade de que soquetes locais estejam sendo compartilhados por vários processos em SOs do tipo UNIX. Sockets compartilhados remotamente, como o UDP/53, que é usado para resolução DNS, não podem ser rastreados para um único processo. Isto enfraquece ainda mais a abordagem.

NetHogs travessa procfs e lida com as limitações acima (embora nem sempre com muito sucesso):

IPTABLES:

As limitações descritas acima de uma ferramenta de Camada 2 podem ser mitigadas usando iptables LOG ou NFLOG. A Camada 2 está logo acima da Camada Física, ou seja, é a última coisa que os pacotes encontram antes de deixar o dispositivo. É por isso que, estando na Camada de Ligação de Dados e trabalhando no nível mais baixo da pilha da rede, BPF é um tipo de mecanismo de filtragem de pacotes sem estado em comparação com netfilter / iptables que funciona na Camada 3 do OSI (mais perto de programas em espaço do usuário). Assim iptables também pode obter informações da pilha TCP/IP (Camada 4). Ele filtra pacotes baseado nos UIDs criadores deles usando o módulo owner que interage com sockets para encontrar a propriedade dos pacotes.

iptables escreve no log do kernel que pode ser lido usando dmesg ou logcat. O UID de um aplicativo pode ser obtido usando algum aplicativo ou lido de /data/system/packages.list ou 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 pode ser salvo em um arquivo e formatado usando ferramentas como grep, awk, printf etc. O Log de Rede – embora muito desactualizado – funciona de forma semelhante. AFWall+ é um firewall baseado em iptables que pode registrar / notificar a atividade de rede de um aplicativo quando o aplicativo é bloqueado.

A única desvantagem desta abordagem é que não pode ser usado para cheirar o tráfego de um processo quando há vários processos em execução com o mesmo UID. iptables não pode capturar pacotes baseados em PIDs. Eles decidiram não usar iptables com processos porque o processo é iniciado antes de ser bloqueado/sniffed, e o programa poderia facilmente gerar um processo infantil com um novo PID que não seria bloqueado/ sniffed. Também os PIDs são criados e destruídos tão rapidamente quanto os soquetes. Então sempre há espaço para tráfego sendo liberado.

QTAGUID:

owner módulo não funcionará para tráfego de entrada ou encaminhado porque os pacotes IP não carregam informações de propriedade. Para medir o uso da rede de entrada/saída por aplicativo, o kernel corrigido do Android para incluir o módulo qtaguid. Podemos ler estatísticas a partir de /proc/net/xt_qtaguid/stats. Com alguns scripts shell obtém-se o uso de dados ao vivo desde a reinicialização:

Contudo no Android 9+, qtaguid está sendo substituído por BPF estendido (que também está planejado para substituir netfilter framework no kernel Linux). Relacionado: Qual processo é responsável por capturar o uso de dados?

IPTABLES + TCPDUMP:

Uma alternativa é colocar o tráfego de saída de uma aplicação num grupo NFLOG e mais tarde o tcpdump captura pacotes desse grupo:

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

Isto é para garantir que nos aproximamos da camada física quando farejamos o tráfego de saída. Mas ele ainda pode dar falsos positivos, por exemplo, se os pacotes forem descartados / perdidos em tabelas de roteamento. É por isso que os sniffers funcionam na camada 2 do OSI. Ou ainda melhor é assistir de fora, por exemplo, usando um servidor proxy / VPN ou em um PC com fio ou em um roteador. Mas isto não irá capturar tráfego por UID/PID.

OUTRAS OPÇÕES:

  • Utilizar ferramentas de diagnóstico como strace para rastrear syscalls relacionado à atividade de rede de um processo. force_bind e tracedump também funcionam com o mesmo princípio. O subsistema de auditoria do kernel Linux pode ser usado para o mesmo.
  • Utilizar cgroup classificador de rede com iptables NETFILTER_XT_MATCH_CGROUP para cheirar o tráfego de certos processos.
  • Utilizar Network Namespaces para isolar processos e ler o uso de dados por interface. nstrace funciona com o mesmo princípio.
  • Se a intenção é bloquear inteiramente o tráfego originado por certos processos, SELinux e seccomp podem ser usados para restringir a capacidade dos processos de criar soquetes definindo restritos policies e suprimindo syscalls respectivamente.

A maior parte destas não são opções diretamente viáveis para o Android e requerem configurações avançadas.

APIs doANDROID (OPÇÕES NÃO RODOVIÁRIAS):

Aplicações como o NetGuard usam a API VpnService do Android para bloquear o tráfego na Camada 3 (interface TUN). O aplicativo pode “notificar quando um aplicativo acessa a internet”. Por aplicativo de captura e rastreamento (1, 2) é possível usar a API VPN como o Android faz uso de UIDs e SOcket_MARKs (1, 2) para controlar o tráfego na Política de Roteamento de Rede (RPDB), pouco antes de sair do dispositivo.

Aplicações como o NetLive fazem uso do NetworkStatsManager, mas ele retarda o uso em tempo real e “não se atualiza com rapidez suficiente”, é “destinado a fornecer dados históricos”.