Quando o emulador não consegue alcançar um servidor de build que o navegador no host abre sem problemas, a pergunta útil não é se a VPN funciona. A pergunta é qual de dois mecanismos falta ao guest. O dispositivo virtual executa sua própria pilha de rede atrás do NAT do emulador, e sua lista de resolvers é uma cópia feita na inicialização, então um túnel que sobe depois muda o caminho do host sem mudar o que o guest pergunta. Entender essas duas camadas explica quase toda variação desse problema.

O guest é uma pilha separada atrás de um NAT fixo

A rede em modo usuário do QEMU coloca o guest em 10.0.2.15 com gateway em 10.0.2.2 e o serviço de DNS em 10.0.2.3 até 10.0.2.6. O tráfego de saída do guest não é encaminhado pelo kernel do host; ele é traduzido em soquetes do lado do host, um por conexão do guest, e esses soquetes saem do espaço de endereços do host. É por isso que uma conexão do guest herda a decisão de roteamento do host no momento em que é criada, e por isso o guest não tem entrada na tabela de rotas que nomeie o seu túnel.

O mesmo mecanismo dá ao guest uma saída útil. 10.0.2.2 é um alias da interface loopback do host, então um serviço escutando em 127.0.0.1 no notebook é alcançável a partir do guest nesse endereço. Tudo o que o cliente expõe apenas no loopback pode ser alcançado por esse caminho, e essa é a base do arranjo de proxy descrito mais adiante.

O que o guest não pode fazer é observar a rede do host como se fosse um namespace dela. Não há bridge, nem tabela de rotas compartilhada, nem resolver herdado; há apenas o serviço NAT que aceita seus pacotes e o snapshot que o launcher tirou quando o dispositivo virtual iniciou.

O DNS é um snapshot, não uma visão ao vivo

Na inicialização o emulador lê a lista de resolvers do host e entrega ao guest até quatro servidores, expostos nos endereços 10.0.2.3 até 10.0.2.6. Se o túnel estava desligado naquele momento, o snapshot contém o resolver público que o notebook usava, e o guest continua perguntando a ele por toda a vida. Nomes públicos resolvem, nomes internos falham, e todos os sintomas apontam para a VPN quando o valor realmente obsoleto é uma lista de resolvers capturada minutos antes de o túnel subir.

A correção de ordem, portanto, não é folclore. Conecte o túnel primeiro, depois reinicie o emulador, e prefira uma inicialização a frio à restauração de um snapshot, porque uma imagem de quick boot pode voltar com o estado de resolvers e rotas salvo antes. Se precisar ver o que o guest usa agora, pergunte ao dispositivo, não ao host:

adb shell dumpsys connectivity | grep -i -A2 dns
adb shell ping -c 1 build.internal.example

O emulador também aceita um resolver explícito no lançamento, o que é útil quando você sabe exatamente qual servidor o guest deve usar e perigoso quando esse servidor é público:

emulator -avd Pixel_API_34 -dns-server 203.0.113.53

Um resolver público não tem cópia de uma zona interna, então fixar um transforma um problema de ordem em falha permanente. Se o perfil empurra DNS privado, deixe o túnel fornecê-lo e inicialize o guest a frio em vez de fixar um endereço no código.

O roteamento segue o host no momento da conexão

Como as conexões do guest se tornam soquetes do host, a decisão de roteamento é tomada quando o soquete é criado. Túnel no ar antes do pedido significa que o pedido sai pelo túnel, sujeito às rotas do perfil. Um perfil split-tunnel que carrega apenas prefixos selecionados deixará sua sub-rede privada de fora sem cerimônia, então a alcançabilidade a partir do host é uma hipótese sobre o guest, não um resultado. Conexões do guest já existentes mantêm o caminho com que foram criadas, e é por isso que um cliente que reconecta nem sempre destrava um download travado dentro do emulador.

A verificação pertence à interface do host, não às estatísticas do guest:

sudo tcpdump -ni tun0 'host 203.0.113.10'

Se o pedido do guest aparece na interface do túnel, o roteamento está funcionando e o problema está acima dele. Se aparece na interface física, o perfil não cobre aquele prefixo, e nenhuma reconfiguração do lado do guest vai mudar isso.

Quando o cliente oferece apenas um proxy de loopback

Alguns clientes comerciais não criam túnel de sistema nenhum. Eles expõem um listener HTTP ou SOCKS em 127.0.0.1 e esperam que os aplicativos o usem. O guest não vê esse soquete diretamente, mas o emulador pode ser instruído a usá-lo, seja pelos controles estendidos (Settings, depois Proxy, modo manual, host 127.0.0.1 e a porta impressa pelo cliente) ou no lançamento:

emulator -avd Pixel_API_34 -http-proxy http://127.0.0.1:8080

Copie a porta da janela do cliente; uma porta adivinhada falha em silêncio e parece um túnel quebrado. Lembre do que isso cobre: a configuração de proxy HTTP é respeitada por aplicativos que conhecem proxy, e soquetes brutos a ignoram por completo. Se a carga de trabalho é um binário nativo que abre suas próprias conexões, o caminho de proxy não é equivalente a um túnel e a comparação precisa ser feita explicitamente.

Prove o resultado de dentro do guest

Separe resolução de roteamento com dois testes na mesma sessão. Um nome que falha enquanto o endereço numérico responde é problema de snapshot de DNS, e a correção é ordem ou um resolver explícito. Se ambos falham, isso aponta para roteamento ou política, e a próxima checagem é se o app roda dentro de um work profile com restrições de rede próprias.

Por fim, saiba em qual guest você está testando. Imagens de emulador muito antigas eram distribuídas sem o suporte a tun que um cliente VPN do lado do guest precisa, então nenhum perfil poderia funcionar ali; as imagens atuais incluem esse suporte. Um cliente que falha em uma imagem atual é problema de cliente ou de perfil, e reconstruir o túnel do host não mudará o resultado.

Artigos relacionados