O fantasma do IP antigo: quando split-horizon e race conditions corrompem a resolução DNS#
O DNS costuma ser o primeiro suspeito em comportamentos estranhos de rede. Recentemente, enfrentei um caso curioso: um sintoma de "Split-Horizon" às avessas em um servidor Linux rodando DirectAdmin e BIND.
Neste artigo, detalho o passo a passo da investigação, do sintoma de latência e rota errada até a solução na camada do sistema operacional.
O problema: o fantasma do IP antigo#
O cenário era o seguinte: o domínio meudominio.com.br havia mudado para o IP local do servidor (203.0.113.50). A internet inteira já estava enxergando o IP novo. Porém, ao acessar o terminal do próprio servidor (srv-core) e disparar um simples ping, o ICMP echo request teimava em ser roteado para o IP antigo e externo (198.51.100.10).
Veja o comportamento primário no terminal:
[root@srv-core ~]# ping meudominio.com.br
PING meudominio.com.br (198.51.100.10) 56(84) bytes of data.
64 bytes from srv-old.provedor.com (198.51.100.10): icmp_seq=1 ttl=49 time=27.7 ms
O tráfego estava saindo da máquina e indo buscar o domínio na internet, gerando latência desnecessária e quebrando a comunicação interna entre serviços locais.
Análise detalhada: onde mora a resolução?#
Para entender por que o kernel estava despachando os pacotes para o gateway externo, precisei olhar a cadeia de resolução. O comando ping não consulta o DNS diretamente; ele delega a resolução de nomes para a biblioteca C padrão do sistema (invocando getaddrinfo() na glibc).
A primeira parada foi o arquivo de hosts:
cat /etc/hosts
O arquivo estava limpo, contendo apenas as entradas de loopback (127.0.0.1) e o hostname do servidor. Não havia nada forçando o IP antigo.
Em seguida, verifiquei a zona DNS local do BIND no DirectAdmin:
cat /var/named/meudominio.com.br.db
Ao inspecionar a zona, o serial do SOA estava atualizado e todos os registros A (www, mail, ftp) apontavam corretamente para o IP local 203.0.113.50. O BIND local estava autoritativo e correto.
O ponto de divergência estava no resolvedor do sistema operacional:
cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 203.0.113.99
nameserver 1.1.1.1
O servidor estava configurado para ignorar o próprio daemon local: o 127.0.0.1 não estava listado. Ele abria sockets UDP diretamente para resolvers públicos externos.
Hipóteses descartadas#
Antes de alterar configurações, isolei os componentes:
- Atraso de Propagação Global:
Usando o dig (que ignora a glibc e o nsswitch e consulta os servidores diretamente):
dig @8.8.8.8 meudominio.com.br +short
# Retorno: 203.0.113.50
Tanto o Google (8.8.8.8) quanto a Cloudflare (1.1.1.1) retornaram o IP novo instantaneamente. A propagação pública já estava 100% concluída (diferente de cenários onde há falha de glue records no BIND).
- Daemons de Cache Locais (
nscd/systemd-resolved):
Verifiquei os serviços de cache em memória, mas nem o nscd nem o systemd-resolved estavam ativos. A resolução passava de forma direta pela biblioteca de sistema.
Rastreabilidade e a race condition#
Para garantir que não havia registros residuais na tabela de rotas do kernel, apliquei um flush no cache de rotas:
ip route flush cache
Ao rodar o ping novamente logo após o flush, o sistema revelou o comportamento real: uma race condition na resolução de nomes alternando entre resolvers:
[root@srv-core ~]# ping meudominio.com.br
PING meudominio.com.br (203.0.113.50) ... time=0.024 ms
...
[root@srv-core ~]# ping www.meudominio.com.br
PING www.meudominio.com.br (198.51.100.10) ... time=27.9 ms
As respostas oscilavam: quando a consulta batia no resolvedor local ou no cache rápido da rede, vinha o IP correto com latência de 0.024ms. Quando ocorria timeout ou rotação para o segundo nameserver da lista (203.0.113.99), ele recebia a resposta antiga de um forwarder intermediário com latência de 27.9ms.
A solução prática#
Em servidores com DirectAdmin e BIND local, a prática recomendada é manter nameserver 127.0.0.1 na primeira linha do /etc/resolv.conf.
Para eliminar qualquer dependência de timeout de rede externa e blindar a comunicação local das aplicações, utilizei a prioridade de resolução do /etc/nsswitch.conf. No Linux, a diretiva padrão hosts: files dns instrui o sistema a consultar o arquivo estático antes de disparar queries na rede.
Fixei o apontamento estático no host:
echo "203.0.113.50 meudominio.com.br www.meudominio.com.br" >> /etc/hosts
Ao adicionar a entrada estática no /etc/hosts:
- O
getaddrinfo()lê o arquivo estático e retorna o IP local em microssegundos. - A oscilação parou imediatamente e o tráfego permaneceu confinado à interface de loopback e rede local.
Considerações práticas de resolução DNS#
Diagnosticar falhas de DNS exige separar a ferramenta de teste da chamada de sistema executada pela aplicação:
- O
dige onslookupmontam pacotes DNS brutos e enviam direto para o nameserver especificado, ignorando o/etc/hostse o/etc/nsswitch.conf. - O
ping,curle os runtimes das aplicações (PHP, Node.js, Python) utilizamgetaddrinfo()daglibc, respeitando a ordem definida no/etc/nsswitch.conf. - Quando um servidor hospeda zonas autoritativas locais, garanta que o
/etc/resolv.confconsulte o127.0.0.1ou use entradas estáticas no/etc/hostspara evitar que tráfego local dê voltas desnecessárias pela internet.
Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários