Acabei de passar cerca de uma hora tentando entender por que os contêineres do Docker não conseguiam se conectar à Internet, particularmente, não conseguiam resolver nenhum nome DNS. Até agora eu encontrei uma solução, mas eu ainda não entendo isso.
O sintoma era que, de acordo com o Wireshark, os pacotes seriam enviados pela rede do docker virtual, mas nunca seriam transmitidos através do NIC físico, apesar do fato de eu ter habilitado o encaminhamento do IPv4. De acordo com os contadores de pacote iptables
, eles foram registrados na regra MASQUERADE
da cadeia POSTROUTING
da tabela nat
, mas não na cadeia FORWARD
da tabela filter
.
Eu tenho os seguintes dispositivos de rede envolvidos aqui:
-
net0 é o meu dispositivo físico de rede local, com o IP 192.168.1.5, localizado atrás de um roteador DSL em 192.168.1.1
-
tun1 é um link de VPN para a rede do meu escritório
-
docker0 é um dispositivo de ponte virtual que o docker configura automaticamente, com contêineres docker que usam a rede 172.17.0.0/16 e a ponte em 172.17.42.1
O ponto chave é a VPN. Quando estou no meu escritório, quero poder me conectar ao meu computador por meio de um registro DynDNS configurado pelo meu roteador DSL. Portanto, os pacotes do meu escritório para o meu computador não passariam pela VPN, mas pelo NAT no roteador. O que significa que, para estabelecer uma conexão, os pacotes de resposta devem seguir o caminho inverso, não passando pela VPN. Para conseguir isso, eu configurei uma tabela de roteamento especial para pacotes de saída vindos da minha LAN:
# ip rule list
0: from all lookup local
50: from all to 127.0.0.0/8 lookup main
51: from all to 192.168.1.0/24 lookup main
100: from 192.168.1.0/24 lookup net0
32766: from all lookup main
32767: from all lookup default
# ip route list table net0
default via 192.168.1.1 dev net0
192.168.1.0/24 dev net0 scope link
# ip route list table main
default via 192.168.1.1 dev net0 metric 3
10.0.0.0/8 dev tun1 scope link
127.0.0.0/8 dev lo scope host
127.0.0.0/8 via 127.0.0.1 dev lo
<VPN gateway> via 192.168.1.1 dev net0 src 192.168.1.5
<VPN network> dev tun1 scope link
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.42.1
192.168.1.0/24 dev net0 proto kernel scope link src 192.168.1.5 metric 3
Eventualmente, descobri que adicionar outra regra para usar a tabela main
de pacotes na rede docker era suficiente para que isso funcionasse. Mas por que? Eu posso ver como a tabela de roteamento especial pode ter afetado os pacotes de resposta vindos do meu roteador. Mas por que isso afetou os pacotes de saída, fazendo com que eles desaparecessem completamente? E existe uma maneira mais flexível de expressar o fato de que eu quero rotear cada pacote de resposta da mesma forma que o pacote de resposta entrou, para que eu não precise adicionar regras sempre que eu configurar uma nova rede virtual de algum tipo?