O tráfego dos contêineres Docker contorna a VPN do host: como verificar
Uma VPN do host cobre apenas o espaço de nomes de rede do host. Use estas verificações para saber se o tráfego dos contêineres na ponte entra no túnel ou sai diretamente.
O navegador no host mostra o endereço de saída da VPN, o contêiner informa a sua conexão doméstica e alguém chama isso de vazamento. Nada vazou. Um túnel do host é um conjunto de interfaces, rotas e regras que pertencem ao espaço de nomes de rede do host, e um contêiner numa ponte é outro espaço de nomes com a sua própria rota predefinida. Já fiquei num stack Compose em que o cliente VPN estava conectado havia semanas e nem um único pacote de contêiner tinha entrado nele.
Verifique o espaço de nomes antes do ícone da bandeja
Os espaços de nomes são todo o argumento. Quando o Docker inicia um contêiner numa rede de ponte, cria um espaço de nomes de rede, liga uma extremidade de um par veth dentro dele e dá a esse espaço de nomes um endereço e uma rota predefinida. A interface do túnel, chame-se o que se chamar, vive no espaço de nomes do host. O tráfego dentro do contêiner não consegue vê-la, e nenhuma configuração do cliente muda isso de fora.
Dois movimentos suportados tiram você do isolamento. --network host coloca o contêiner dentro do espaço de nomes do host, pelo que ele herda as rotas do host e, portanto, o túnel. --network container:vpn partilha o espaço de nomes de outro contêiner, e é assim que a maioria dos projetos sidecar envia uma carga de trabalho por um contêiner VPN. Ambos são escolhas explícitas; normalmente só uma delas é o que a pessoa que implanta queria dizer.
O modo host não é uma melhoria gratuita. O contêiner deixa de ter o seu próprio endereço, a publicação de portas deixa de se aplicar, e um processo que detenha NET_ADMIN ali pode reescrever o encaminhamento do host. Aceitar isso pode ser a decisão certa. Assumir que já está ligado é como as pessoas passam uma noite a depurar um túnel que nunca esteve no caminho.
Siga o pacote para fora da ponte
Um contêiner na ponte envia o seu pacote para o seu gateway predefinido, que é a interface da ponte no host. O host encaminha então o pacote e, na configuração predefinida, traduz o endereço de origem para o seu antes de o pacote sair. É esse passo de tradução que derrota a política em silêncio.
Quando o pacote chega ao ponto final do túnel, já leva o endereço do host. Qualquer regra, rota de política ou decisão de túnel dividido baseada no endereço original do contêiner deixa de corresponder, e dois contêineres destinados a sair por saídas diferentes não se distinguem apenas pela origem. Se precisa de encaminhamento por contêiner, a decisão tem de acontecer antes da tradução ou dentro de um espaço de nomes que controle.
O Docker mantém estas regras sozinho, através do backend de firewall com que o daemon foi configurado. Regras escritas à mão fora do gancho suportado para tráfego encaminhado, DOCKER-USER, podem ser reordenadas ou descartadas quando o daemon reinicia ou o host é atualizado. A documentação do Docker sobre filtragem de pacotes mostra a ordem das cadeias; o ponto prático é que cada regra precisa de um dono e de um caminho de recarga que você tenha realmente testado.
Teste os dois sistemas em separado
As provas de um espaço de nomes não dizem nada sobre o outro. Um pedido executado dentro do contêiner VPN prova que o túnel funciona para esse contêiner. Não é prova sobre o host, e o mesmo comando executado a partir de um contêiner --network host não é prova sobre a ponte.
# host namespace
ip route get 1.1.1.1
ip -brief addr show
# a fresh container on the same bridge network
docker run --rm --network appnet alpine sh -c 'ip route; cat /etc/resolv.conf; ip -6 route'
Depois repita o teste dentro do contêiner real da aplicação em vez de uma imagem parecida. A aplicação pode trazer uma rota extra, uma variável de ambiente de proxy ou um resolvedor diferente, e cada uma dessas coisas muda a resposta. Verifique a resolução de nomes e a segunda família de endereços sempre: os contêineres em pontes definidas pelo utilizador resolvem através do resolvedor integrado do Docker em 127.0.0.11, e uma rota predefinida IPv6 na ponte pode levar tráfego para fora enquanto está ocupado a testar um túnel só IPv4.
Leia o padrão antes de tocar nas credenciais
Quando o host funciona e o contêiner não, a causa é estrutural quase sempre, e rodar chaves ou reinstalar o cliente desperdiça uma tarde. Ordene primeiro o sintoma e a correção normalmente nomeia-se a si própria.
| What you see | Usual cause | First check |
|---|---|---|
| Host exits through the VPN, container shows the ISP address | The container never entered the tunnel | Default route inside the container |
| Container works until the daemon restarts, then stops | Rules outside the supported hook, or a changed backend | Daemon's reported firewall backend and DOCKER-USER |
| Container loses internal hosts after the tunnel comes up | VPN prefix overlaps the Docker bridge subnet | ip route on the host, then docker network inspect |
| Small replies arrive, large ones hang | Tunnel MTU or missing MSS clamping | Link MTU on both ends of the tunnel |
| Container falls back to the ISP address when the tunnel drops | Nothing enforces the kill switch for forwarded traffic | Stop the tunnel with a request in flight |
A linha da sobreposição merece a sua própria frase. Um perfil de VPN que empurra uma rota para 172.17.0.0/16, ou para uma 10.0.0.0/8 que por acaso contém o prefixo da sua ponte, faz o túnel reivindicar a sub-rede dos contêineres, e as respostas para endereços traduzidos vão na direção errada ou desaparecem. Renumerar a rede do Docker costuma ser mais limpo do que acumular exceções.
Torne a cobertura explícita e depois quebre-a de propósito
Dois projetos resistem a uma revisão. Partilhe o espaço de nomes do contêiner VPN e cada carga coberta usa um único túnel com uma única fronteira de reinício, o que é simples até um serviço precisar de outra saída ou do seu próprio caminho DNS. Ou encaminhe a rede dos contêineres para um gateway VPN no host: encaminhamento ativado, o prefixo da ponte apontado ao túnel, o tráfego de retorno tratado explicitamente. Isso compra controlo por rede e custa-lhe um conjunto de regras a manter ao longo das atualizações do daemon e do cliente.
De qualquer forma, o teste que importa é o caso de falha. Pare o túnel com um pedido de contêiner em voo e observe para onde vai o pacote. Se voltar ao caminho direto, a cobertura nunca foi imposta, porque um kill switch do cliente governa o tráfego do próprio cliente e não os pacotes encaminhados de uma ponte. Reinicie depois o daemon e o host e confirme o resultado uma segunda vez; é o momento em que as regras escritas à mão desaparecem.
Antes de dar isso por concluído, confirme quatro coisas: a interface do túnel está no mesmo espaço de nomes do tráfego, o teste do contêiner correu dentro do contêiner real, a resolução de nomes e as duas famílias de endereços foram verificadas, e o teste de falha do túnel continua a falhar fechado. Depois anote o backend de firewall, a versão do cliente e o dono de cada regra. Esse registo é o que impede a próxima atualização de deixar uma mistura não documentada de suposições antigas.