O Erro Silencioso de DNS Que Derrubou Meu Serviço por 3 Dias (e o Script de 40 Linhas Que Impediu o Retorno)
Na segunda-feira passada, acordei com 47 mensagens no Slack. Todas dizendo a mesma coisa: “serviço fora do ar”. O painel de status mostrava verde. O uptime monitor mandava beijinhos. Mas o serviço estava completamente inacessível para usuários no Brasil.
O culpado? Um erro silencioso de DNS que nenhum monitoramento tradicional capturou. E eu levei 3 dias para descobrir. Neste artigo, vou documentar cada passo errado que dei, o que finalmente revelou o problema, e como criei um script de 40 linhas em Bash que nunca mais deixa isso acontecer.
O Cenário: Tudo Verde, Nada Funcionando
Meu setup era clássico: uma aplicação Node.js rodando atrás de um NGINX no DigitalOcean, domínio gerenciado no Cloudflare. Monitoramento com UptimeRobot checando a cada 5 minutos. O health endpoint (/health) retornava 200. Os logs não mostravam nenhum erro.
Mas os usuários no Brasil não conseguiam acessar. Usuários na Europa conseguiam. Usuários nos EUA conseguiam. Só o Brasil ficava olhando para a tela de ERR_NAME_NOT_RESOLVED.
Esse é o tipo de erro que te faz questionar tudo. Primeiro você acha que é cache. Depois acha que é o Cloudflare. Depois você fica desesperado e reinicia o servidor (spoiler: não adianta reiniciar DNS).
O Perrengue: 72 Horas de Investigação Cega
🔥 Box Perrengue: Já passei 3 dias debugando um problema que se resumia a um único registro TXT no DNS. A lição? Quando o erro é intermitente e geográfico, nunca comece investigando a aplicação. Comece pelo DNS. Sempre.
Dia 1: Culpei a Aplicação
Passei o primeiro dia inteiro olhando logs da aplicação. Reiniciei serviços, verifiquei variáveis de ambiente, rodei testes de integração. Tudo passando. O erro continuava.
O que eu deveria ter feito: dig no domínio a partir de um servidor brasileiro.
# O que EU deveria ter rodado no minuto 1
dig +short api.meudominio.com @8.8.8.8
# Retorno esperado: IP do servidor
# Retorno real: (vazio) ← PROBLEMA!
# Verificando de um DNS brasileiro
dig +short api.meudominio.com @200.192.232.8
# Retorno: (vazio) ← Confirmado: DNS não resolve no Brasil
Dia 2: Culpei o Cloudflare
Desativei o proxy do Cloudflare. Mudei os nameservers de volta para o registrador. O problema persistia. Percebi que não era o Cloudflare — era algo mais fundamental.
Foi quando rodei um whois no domínio e descobri que os nameservers estavam apontando para um servidor de DNS que não tinha mais a zona do meu domínio.
# Descobrindo o problema real
whois meudominio.com | grep "Name Server"
# Name Server: ns1.dns-antigo.com
# Name Server: ns2.dns-antigo.com
# Mas a zona DNS estava configurada em:
# ns1.dns-novo.com
# ns2.dns-novo.com
Um mês antes, eu tinha migrado os DNS do registrador antigo para o Cloudflare. A migração pareceu funcionar — e funcionou, para alguns resolvedores DNS. Os outros continuavam consultando o DNS antigo, que não tinha mais a zona. E como o TTL da zona raiz ainda apontava para os servidores antigos em algumas cache… bum.
Dia 3: A Solução (e a Vergonha)
A correção levou literalmente 2 minutos:
- Recriar a zona DNS no servidor antigo
- Apontar para o IP correto
- Agendar a migração DNS corretamente com TTL baixo
Mas a pergunta que ficou: como monitorar isso para não acontecer de novo?
Por Que Seu Monitoramento Não Vê Erros de DNS
A maioria dos serviços de monitoramento (UptimeRobot, Pingdom, BetterUptime) resolve o domínio a partir de seus próprios servidores. Se o DNS resolve de Virginia e Frankfurt, o monitor diz “tudo ok”. Mas seus usuários em São Paulo podem estar consultando um resolvedor DNS diferente que aponta para o servidor errado.
É o equivalente a checar se a luz do porão está acesa usando uma câmera na cozinha. Você acha que está monitorando, mas está olhando para o lugar errado.
O Script: 40 Linhas Que Salvaram Minha Vida
Depois do trauma, criei um script que monitora a resolução DNS a partir de múltiplos pontos geográficos. Funciona com DNS públicos de diferentes regiões:
#!/usr/bin/env bash
# dns-monitor.sh — Monitora resolução DNS multi-região
# Autor: Olivetto | automente.com.br
DOMAIN="${1:-meudominio.com}"
EXPECTED_IP="${2:-203.0.113.50}"
ALERT_WEBHOOK="${DISCORD_WEBHOOK_URL:-}"
# DNS resolvers por região
declare -A RESOLVERS=(
["Brasil"]="200.192.232.8"
["EUA"]="8.8.8.8"
["Europa"]="1.1.1.1"
["Asia"]="168.95.1.1"
["Oceania"]="9.9.9.9"
)
FAILURES=0
echo "=== DNS Monitor: $DOMAIN ==="
echo "IP esperado: $EXPECTED_IP"
echo ""
for regiao in "${!RESOLVERS[@]}"; do
resolver="${RESOLVERS[$regiao]}"
resolved=$(dig +short "$DOMAIN" @"$resolver" 2>/dev/null | head -1)
if [[ -z "$resolved" ]]; then
echo "❌ $regiao ($resolver): FALHA - Sem resolução"
((FAILURES++))
elif [[ "$resolved" != "$EXPECTED_IP" ]]; then
echo "⚠️ $regiao ($resolver): IP divergente - $resolved"
((FAILURES++))
else
echo "✅ $regiao ($resolver): $resolved"
fi
done
echo ""
echo "Falhas: $FAILURES"
if [[ $FAILURES -gt 0 && -n "$ALERT_WEBHOOK" ]]; then
curl -s -X POST "$ALERT_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{\"content\":\"🚨 DNS Alerta: $DOMAIN com $FAILURES falha(s) de resolução!\"}"
fi
exit $FAILURES
Como Usar
# Uso básico
chmod +x dns-monitor.sh
./dns-monitor.sh api.meudominio.com 203.0.113.50
# Com alerta Discord (via variável de ambiente)
export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."
./dns-monitor.sh api.meudominio.com 203.0.113.50
# No cron (a cada 15 minutos)
*/15 * * * * /path/to/dns-monitor.sh api.meudominio.com 203.0.113.50
Lições Que Eu Jurava Já Ter Aprendido
Depois desse episódio, atualizei meu checklist de deploy. Se você também já levou 3 dias para descobrir que era DNS, aqui vai o resumo:
- Sempre valide DNS após mudanças de nameserver — Use
digde múltiplos resolvedores, não só o do seu provedor. - Baixe o TTL antes de migrar — Mude o TTL para 300 segundos pelo menos 48h antes de qualquer mudança DNS.
- Monitore DNS, não só HTTP — Se seu monitor só checa HTTP, ele não vai pegar problemas de resolução.
- Migração DNS não é instantânea — Mesmo com TTL baixo, some caches recursivos demoram até 72h para expirar.
- Documente cada mudança — Eu fiz a migração às pressas e não documentei. Isso custou 3 dias.
Automatizando a Validação Pós-Deploy
Integrei o monitor DNS no meu pipeline CI/CD. Toda vez que faço deploy, o pipeline valida que o DNS resolve corretamente em pelo menos 4 regiões antes de considerar o deploy bem-sucedido:
# .github/workflows/deploy.yml (trecho)
- name: Validate DNS Resolution
run: |
./scripts/dns-monitor.sh ${{ secrets.DOMAIN }} ${{ secrets.EXPECTED_IP }}
if [ $? -gt 1 ]; then
echo "::error::DNS resolution failed in multiple regions!"
exit 1
fi
Se mais de uma região falhar, o deploy é abortado. Simples assim. Melhor prevenir do que acordar com 47 mensagens de pânico no Slack.
Quando o DNS Não É o Culpado (Mas Você Acha Que É)
Nem todo ERR_NAME_NOT_RESOLVED é DNS. Outras causas que já me pegaram:
- Certificado SSL expirado — O navegador mostra erro de DNS, mas na verdade é TLS. Use
openssl s_client -connect dominio:443para verificar. - Firewall bloqueando na borda — O DNS resolve, mas o tráfego não chega.
tracerouteé seu amigo. - Rate limiting agressivo — Cloudflare bloqueando seu IP. Verifique os logs do WAF.
- Propagação parcial — Funciona em alguns provedores e não em outros. Só o tempo resolve (e paciência).
A regra de ouro: quando o problema for geográfico e intermitente, comece pelo DNS. Depois verifique TLS. Só depois olhe a aplicação. Na ordem inversa, você vai perder dias — como eu perdi.
Ferramentas Que Me Ajudaram (E O Que Não Ajudou)
Ferramentas úteis para debug de DNS:
dig— O canivete suíço. Se você só vai aprender um comando, que seja este.- DNSChecker — Mostra a propagação DNS global em tempo real. Grátis.
dnstracer— Rastreia o caminho completo da resolução DNS. Mostra exatamente onde quebra.- MxToolbox — Verifica DNS, SPF, DKIM, DMARC em um lugar só.
O que não ajudou:
- Reiniciar o servidor (obviamente)
- Limpar cache do navegador (o problema nem chegava lá)
- Pedir ajuda no Stack Overflow sem os outputs do
dig(ninguém pode te ajudar no escuro)
Checklist: DNS Migration Runbook
Este é o checklist que eu deveria ter seguido. Agora está colado na minha mesa:
- 📍 T-72h: Reduzir TTL para 300s em todos os registros
- 📍 T-48h: Verificar propagação com DNSChecker
- 📍 T-24h: Criar zona DNS no novo provedor com todos os registros
- 📍 T-0h: Trocar nameservers no registrador
- 📍 T+1h: Validar resolução multi-região com
dns-monitor.sh - 📍 T+24h: Validar novamente — algumas caches demoram
- 📍 T+72h: Confirmar propagação completa, subir TTL de volta
- 📍 T+168h: Desativar zona antiga, documentar a migração
Conclusão: Se Seu Monitor Diz “Verde” e Os Usuários Dizem “Fora”, É DNS
Erros de DNS são os mais traiçoeiros porque seu monitoramento quase nunca pega. Tudo parece funcionar — os health checks passam, os logs estão limpos, o painel está verde. Mas os usuários estão vendo uma tela em branco.
O script de 40 linhas que compartilhei aqui mudou minha relação com DNS. Agora eu monitoro resolução a partir de 5 regiões diferentes, e se alguma diverge, eu sei em minutos — não em dias.
Se você já levou um susto com DNS (ou quer evitar), copia esse script, bota no cron, e dorme tranquilo. DNS não deveria ser motivo de insônia. Já temos bugs suficientes no código mesmo.
E você? Já perdeu horas (ou dias) com um erro de DNS silencioso? Compartilha nos comentários — e me diz qual automação de monitoramento você quer ver aqui no blog.
