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 rastrearsyscalls
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
eseccomp
podem ser usados para restringir a capacidade dos processos de criar soquetes definindo restritospolicies
e suprimindosyscalls
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”.