Uma rota adicionada à tabela main no Android parece correta em qualquer listagem e mesmo assim não transporta o tráfego. A razão é que a tabela main é apenas uma opção entre várias, e não é consultada primeiro. O serviço de rede do Android constrói regras de política que escolhem uma tabela de encaminhamento com informações que o endereço de destino não contém — o uid da aplicação, uma marca no pacote, a interface por onde chegou — e a busca do destino acontece depois, dentro da tabela que essas regras escolheram.

Três decisões numa ordem fixa

Um pacote de saída toma três decisões separadas. Primeiro, uma regra de política determina qual tabela de encaminhamento se aplica. Segundo, uma rota dentro dessa tabela determina o próximo salto e a interface de saída. Terceiro, os ganchos do netfilter decidem se o pacote sobrevive, é modificado ou é redirecionado.

A ordem importa porque cada etapa só pode responder à sua própria pergunta. Uma regra de firewall que aceita um pacote não seleciona uma tabela, e uma rota adicionada a uma tabela que nenhuma regra seleciona é inerte. Boa parte da confusão em torno das VPN no Android vem de corrigir uma das três e não observar mudança alguma, porque a falha estava noutra.

StageSelectorWhat it cannot decide
Policy ruleuid range, mark, incoming interfaceWhich route exists inside the table
Route lookupDestination prefix, longest matchWhether the packet is allowed out
Netfilter hookChain position, match conditionsWhich table was selected

As marcas são um campo empacotado, não uma etiqueta que você possui

O Android empacota vários factos no mesmo valor de marca: qual rede foi escolhida, se uma aplicação escolheu uma rede explicitamente, se um socket está protegido da VPN e bits relacionados com permissões. O cabeçalho fwmark do AOSP define essa disposição para a árvore atual, e a disposição é um detalhe interno da plataforma que muda entre versões.

Por isso escrever um valor de marca inteiro com iptables -j MARK --set-mark é perigoso no Android. Não acrescenta uma etiqueta; substitui a seleção de rede que o sistema já fez. O pacote passa então a corresponder a regras diferentes, o que pode parecer que a VPN começou a funcionar ou que uma aplicação não relacionada perdeu a conetividade, consoante os bits sobrescritos.

Se tiver de tocar em marcas, leia primeiro o valor atual e use uma máscara para que só os bits que entende sejam modificados:

ip rule show
ip route show table all | head -40
ip route get 10.20.4.11

Uma marca de ligação é um objeto separado de uma marca de pacote, e nenhuma das duas é uma rota. Restaurar a marca nos pacotes de resposta é um passo distinto de escolher uma tabela na saída, e é por isso que as correções unidirecionais produzem ligações que abrem e depois ficam penduradas.

Quem é dono das regras e das tabelas

O serviço de rede do Android, o netd, cria as regras e as tabelas por rede. O AOSP RouteController é onde essas regras são montadas para VPN, redes físicas e intervalos de uid, e o seu ciclo de vida está ligado a eventos de rede e não a um ficheiro de configuração.

Daí decorrem duas consequências. Primeira, as prioridades e os números de tabela que encontra num telemóvel são detalhes internos da compilação, não uma interface: números de aspeto idêntico noutra versão do Android podem significar algo completamente diferente. Segunda, o estado é reconstruído quando as redes mudam, pelo que uma regra inserida hoje a partir de uma shell root pode ter desaparecido após a transição de Wi-Fi seguinte.

Esse desaparecimento é frequentemente reportado como o sistema a ignorar uma rota. O que aconteceu na realidade é que a regra que escolhia a tabela já não existe, e a rota dentro da tabela está agora inalcançável na perspetiva do pacote. Verifique a lista de regras, não a de rotas, quando uma configuração que funcionava deixa de funcionar após uma reconexão.

As perguntas sobre a ordem dos ganchos não têm resposta universal

A pergunta se o iptables corre antes do encaminhamento da VPN não tem resposta sem nomear o caminho do pacote. Um pacote gerado localmente atravessa o gancho output, onde uma mudança de marca desencadeia uma verificação de reencaminhamento — uma segunda consulta, não uma edição retroativa da primeira. Um pacote que chega de um cliente em tethering atravessa o caminho prerouting e é reencaminhado em vez disso, e as cadeias que o veem são outras.

Assim, a mesma regra pode ser eficaz para o tráfego de uma aplicação e invisível para o tráfego em tethering, e um contador que fica em zero diz-lhe que caminho o pacote tomou, não se a regra está errada. Use contadores para estabelecer o caminho antes de alterar qualquer condição de correspondência.

Esta é também a etapa em que um erro de encaminhamento por política se torna difícil de ver. Encaminhar para uma tabela que existe mas não contém o destino produz um rede inalcançável que parece um descarte da firewall, enquanto um descarte da firewall produz um tempo de espera que parece um buraco negro de encaminhamento.

Diagnostique dentro do sistema, ou deixe-o em paz

Para uma revisão autorizada, estabeleça quatro factos antes de tocar em nada: o uid e o perfil da aplicação, a rede que o Android escolheu para ela, se a VPN inclui essa aplicação e se o problema existe para ambas as famílias de endereços. Uma exclusão por aplicação explica imensos relatos de VPN não funciona sem qualquer falha de encaminhamento.

Depois leia as regras, máscaras e tabelas realmente em vigor, e mantenha uma mudança de rede dentro da janela de observação. Se o comportamento mudar ao longo de uma reconexão, está a olhar para um ciclo de vida gerido, não para uma rota em falta.

Para requisitos comuns, use os controlos suportados: inclusão e exclusão por aplicação na aplicação VPN, e a seleção de rede própria da plataforma para tudo o que precisa de um caminho específico. Se uma integração privilegiada tiver mesmo de cooperar com a maquinaria de encaminhamento, aponte para a implementação da versão exata do Android que suporta e mantenha o seu ciclo de vida através do componente que a possui. Esvaziar cadeias da plataforma ou inserir uma regra de prioridade alta transforma um diagnóstico num segundo gestor de rede, e o telemóvel comportar-se-á em conformidade.

Artigos relacionados