Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

DNS no Node.js: Guia Prático

Atualizado em: 2 de agosto de 2026

Rack de comunicação ilustrando EventEmitter no Node.js

Antes de uma aplicação acessar uma API, banco ou serviço externo pelo nome, esse endereço precisa ser convertido em um IP. O módulo DNS no Node.js, disponível como node:dns, oferece APIs para resolver hosts, consultar registros e controlar servidores DNS usados pela aplicação.

Problemas de DNS podem parecer falhas de rede, timeout ou indisponibilidade do serviço. Além disso, dns.lookup() e dns.resolve() possuem comportamentos diferentes. Escolher a função errada pode afetar cache, ordem IPv4/IPv6 e consumo do thread pool.

Neste guia, você aprenderá a resolver endereços, consultar registros A, AAAA, MX e TXT, usar Promises, definir servidores customizados, aplicar cache e diagnosticar falhas.

Carregando o módulo

const dns = require('node:dns');
const dnsPromises = require('node:dns/promises');

A documentação oficial do módulo DNS detalha funções, códigos de erro e a classe Resolver. Para revisar redes e servidores, veja o que é um servidor e o que é Node.js.

dns.lookup() e o resolvedor do sistema

const dns = require('node:dns/promises');

const result = await dns.lookup('example.com');
console.log(result.address, result.family);

lookup() usa mecanismos do sistema operacional semelhantes aos usados por outras aplicações. Ele pode considerar arquivo hosts, configuração local e políticas do ambiente. Apesar da interface assíncrona, algumas resoluções usam o thread pool do Node.js.

Retornando todos os endereços

const addresses = await dns.lookup('example.com', {
  all: true,
  verbatim: true
});

Com all, a função retorna IPv4 e IPv6 disponíveis. A opção verbatim preserva a ordem entregue pelo resolvedor. Em versões atuais, também existe configuração de ordem padrão com dns.setDefaultResultOrder().

Consultando registros diretamente

resolve() faz consultas DNS pela rede e não usa exatamente o mesmo caminho de lookup():

const ips = await dns.resolve4('example.com');
const ipv6 = await dns.resolve6('example.com');

Essa abordagem é apropriada quando você precisa de registros específicos ou TTL, não apenas de um endereço para abrir conexão.

Consultando TTL

const records = await dns.resolve4('example.com', {
  ttl: true
});

for (const record of records) {
  console.log(record.address, record.ttl);
}

TTL indica por quanto tempo uma resposta pode ser armazenada. Um cache deve respeitar esse valor e também ter limites de tamanho.

Registros MX

const mailServers = await dns.resolveMx('example.com');

mailServers.sort((a, b) => a.priority - b.priority);

Registros MX indicam servidores de e-mail. Encontrar um MX não garante que o endereço de e-mail exista ou que mensagens serão aceitas.

Registros TXT

const txt = await dns.resolveTxt('example.com');

const values = txt.map(parts => parts.join(''));
console.log(values);

Um registro TXT pode ser dividido em vários fragmentos. SPF, verificações de domínio e outras informações usam esse formato.

Registros SRV

const services = await dns.resolveSrv(
  '_service._tcp.example.com'
);

SRV fornece host, porta, prioridade e peso. Clientes precisam aplicar corretamente prioridade e distribuição por peso, não apenas escolher o primeiro elemento.

Resolução reversa

const names = await dns.reverse('8.8.8.8');

Uma resposta reversa não prova identidade ou propriedade. Não use PTR como mecanismo isolado de autenticação.

Classe Resolver

Uma instância separada permite configurar servidores sem alterar o processo inteiro:

const { Resolver } = require('node:dns/promises');

const resolver = new Resolver();
resolver.setServers([
  '1.1.1.1',
  '8.8.8.8'
]);

const records = await resolver.resolve4('example.com');

Isso é útil em ferramentas de diagnóstico ou ambientes com resolvedor dedicado. Servidores públicos podem não conhecer domínios internos.

Timeout e tentativas

Algumas opções do Resolver permitem definir timeout e número de tentativas:

const resolver = new Resolver({
  timeout: 3000,
  tries: 2
});

Retries devem ser limitados e considerar o tempo total da requisição. Para uma política mais ampla, veja o guia de AbortController no Node.js.

Erros comuns de DNS

Trate códigos específicos:

try {
  await dns.resolve4('missing.example');
} catch (error) {
  if (error.code === 'ENOTFOUND') {
    console.log('Domínio não encontrado');
  } else if (error.code === 'ETIMEOUT') {
    console.log('Servidor DNS não respondeu');
  } else {
    throw error;
  }
}

Também podem aparecer ESERVFAIL, EREFUSED, ENODATA e outros. Não transforme todos em “host inexistente”.

Cache na aplicação

Repetir consultas em alto volume aumenta latência e carga. Um cache simples precisa armazenar valor e expiração:

const cache = new Map();

async function resolveCached(hostname) {
  const current = cache.get(hostname);

  if (current && current.expiresAt > Date.now()) {
    return current.addresses;
  }

  const records = await dns.resolve4(hostname, { ttl: true });
  const minimumTtl = Math.min(...records.map(item => item.ttl));
  const addresses = records.map(item => item.address);

  cache.set(hostname, {
    addresses,
    expiresAt: Date.now() + minimumTtl * 1000
  });

  return addresses;
}

Limite a quantidade de entradas, trate TTL zero e não mantenha resultados negativos indefinidamente.

DNS e balanceamento

Um hostname pode retornar vários IPs. Se a biblioteca resolve uma vez e mantém a conexão por muito tempo, mudanças no DNS só serão percebidas após reconexão. Considere keep-alive, TTL e política de renovação.

IPv4 e IPv6

Ambientes com IPv6 parcialmente configurado podem apresentar atrasos ou falhas. Não force IPv4 sem diagnosticar. Teste conectividade para ambas as famílias e observe a ordem das respostas.

DNS e segurança

Entradas DNS podem mudar. Ao buscar URLs fornecidas pelo usuário, validar apenas o hostname antes da resolução não impede SSRF. O domínio pode resolver para IP privado ou mudar entre verificações. Valide endereços finais e controle redirecionamentos.

O artigo sobre segurança em aplicações web apresenta outros controles.

Não bloqueie o thread pool

Muitas chamadas de lookup() concorrentes podem competir com operações que usam o thread pool. Meça filas e latência. Consultas com resolve* usam a implementação de DNS do Node.js e possuem características diferentes.

Observabilidade

Registre hostname lógico, tipo de consulta, duração, código de erro, servidor usado e quantidade de respostas. Evite registrar domínios contendo dados pessoais ou tokens. Monitore aumento de timeout, SERVFAIL e respostas vazias.

Testando

Não dependa apenas do DNS público nos testes. Injete uma função de resolução ou use um servidor controlado. Teste múltiplos IPs, TTL curto, NXDOMAIN, timeout, IPv6 e alteração de registros.

Erros comuns

  • Confundir lookup e resolve: resultados e caminho de resolução diferem.
  • Ignorar TTL: cache mantém IP antigo por tempo demais.
  • Não limitar cache: hostnames arbitrários consomem memória.
  • Tratar todo erro como ENOTFOUND: diagnóstico fica incorreto.
  • Escolher sempre o primeiro SRV: prioridade e peso são ignorados.
  • Confiar em PTR para autenticação: o registro não prova identidade.
  • Validar hostname mas não IP final: SSRF continua possível.
  • Forçar IPv4 sem medir: compatibilidade futura é reduzida.

Boas práticas para produção

  • Escolha conscientemente entre lookup() e resolve().
  • Respeite TTL e limite caches.
  • Aplique timeout e tentativas limitadas.
  • Trate códigos de erro separadamente.
  • Teste IPv4 e IPv6.
  • Valide IP final em operações sensíveis.
  • Monitore latência e falhas do resolvedor.
  • Use Resolver separado quando precisar de servidores próprios.
  • Considere reconexão após mudanças de DNS.
  • Não use DNS como autenticação.

Conclusão

O DNS no Node.js oferece funções para resolver hosts e consultar registros específicos. lookup() integra-se ao resolvedor do sistema, enquanto resolve* permite consultas DNS detalhadas.

Uma implementação confiável combina timeout, cache com TTL, tratamento de erros e suporte a múltiplos endereços. Com observabilidade e validação de segurança, a resolução de nomes deixa de ser uma dependência invisível e passa a ser uma parte controlada da aplicação.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita