Joao Brietzke Blog

← voltar

Route 53 e DNS: como um nome vira um endereço

Toda conexão que você abre na internet começa com uma pergunta que ninguém vê. Antes do TCP, antes do TLS, antes do primeiro byte de HTTP, alguém precisa traduzir exemplo.com em 203.0.113.10. Máquinas falam em IP. Pessoas lembram de nomes. O DNS é a peça que faz a ponte.

A tentação é imaginar o DNS como uma agenda telefônica global, um arquivo enorme com todos os nomes do mundo. Não funciona: seria gigante, estaria desatualizado segundos depois de publicado, e cada mudança exigiria sincronizar o planeta inteiro. O que existe no lugar é um banco de dados distribuído, hierárquico e cacheado. Ninguém tem a base toda. Cada organização guarda o próprio pedaço e aponta para o pedaço seguinte.

O Route 53 é a implementação da AWS do lado que guarda os pedaços. Mas ele só faz sentido depois que a mecânica do DNS está clara, então é por aí que este post começa.


A hierarquia dos nomes

Um nome se lê da direita para a esquerda. blog.exemplo.com. é:

.                          raiz (o ponto final invisível)
└── com.                   TLD
    └── exemplo.com.       domínio (o que você registra)
        └── blog.exemplo.com.   subdomínio

Aquele ponto no final é real. Um nome que termina em ponto é um FQDN, um nome totalmente qualificado. Sem ele, o resolver pode anexar sufixos de busca configurados na máquina. O console do Route 53 esconde o ponto, mas ele está nos dados da zona.

Quatro termos que costumam ser embaralhados e vale separar de uma vez:

Termo O que é
Registry Opera um TLD inteiro. A Verisign opera o .com.
Registrar Vende o domínio para você. Route 53 Domains, GoDaddy, Registro.br.
Zona O pedaço da árvore pelo qual um conjunto de servidores é autoritativo.
Apex da zona O nome da própria zona, exemplo.com, sem subdomínio na frente.

O apex vai voltar mais adiante, e vai ser o motivo de metade das decisões de design do Route 53.

Os quatro papéis de uma consulta

  • Stub resolver. O cliente minúsculo dentro do seu sistema operacional. Faz uma pergunta, quer uma resposta pronta. Não tem inteligência nenhuma.
  • Resolver recursivo. Quem faz o trabalho pesado: o DNS do seu provedor, o 8.8.8.8, o 1.1.1.1, ou o resolver da VPC. É aqui que mora o cache.
  • Servidores raiz. Treze identidades lógicas, de a a m.root-servers.net, espalhadas por centenas de instâncias físicas via anycast. Não sabem nada além de onde ficam os TLDs.
  • Servidores autoritativos. Guardam a resposta de verdade de uma zona. O Route 53 é isto.

A distinção que importa: o stub faz uma consulta recursiva, ou seja, "me devolve a resposta final". O resolver então faz consultas iterativas mundo afora, ou seja, "me diz o que você sabe que eu sigo o ponteiro".

Uma resolução inteira, passo a passo

Cache frio, resolvendo blog.exemplo.com:

  navegador
     │ 1. blog.exemplo.com?
     ▼
  resolver recursivo
     │ 2. pergunta à raiz ───────▶ servidor raiz
     │ ◀── "não sei, pergunta aos NS do .com"    (referral)
     │ 3. pergunta ao .com ──────▶ servidor do TLD
     │ ◀── "pergunta a ns-123.awsdns-45.com"     (referral, registros NS)
     │ 4. pergunta a ele ────────▶ Route 53 (autoritativo)
     │ ◀── "A 203.0.113.10"                      (resposta, flag AA ligada)
     ▼
  navegador  ── guarda em cache pelo TTL e abre TCP para 203.0.113.10

Três encaminhamentos e uma resposta. Repare numa coisa sutil: o resolver nunca perguntou "quem é autoritativo por esse nome" como uma pergunta separada. A delegação é o encaminhamento. Não existe um passo de descoberta, existe a árvore sendo descida.

Na camada de transporte, isso trafega em UDP na porta 53, historicamente limitado a 512 bytes por resposta. A extensão EDNS0 aumentou esse teto. Se ainda assim não couber, o servidor liga a flag de truncamento e o resolver refaz a pergunta por TCP. DoT (porta 853) e DoH (porta 443) criptografam o trecho entre o stub e o resolver recursivo, e não mudam absolutamente nada na hierarquia acima. Se a divisão de camadas aqui não estiver fresca, ela está em Modelo OSI e TCP/IP.

Cache e TTL

Cada registro carrega um TTL em segundos. O resolver guarda pelo tempo indicado, e o sistema operacional guarda, e o navegador guarda. Três consequências que valem mais do que a definição:

Você não consegue tornar uma mudança de DNS instantânea. Só consegue ter configurado um TTL baixo antes. É uma decisão que precisa ser tomada com dias de antecedência, não na hora da migração.

A receita de migração é ao contrário do intuitivo. Baixe o TTL para 60 segundos, espere o TTL antigo expirar por completo (para que todo mundo já tenha buscado a versão de 60 segundos), só então troque o registro, e depois suba o TTL de volta.

Resposta negativa também é cacheada. Um NXDOMAIN fica guardado pelo tempo definido no campo minimum do SOA, conforme a RFC 2308. É por isso que aquele registro que você acabou de corrigir continua "não existindo" por mais um tempo.

TTL alto é mais barato, mais rápido e mais resiliente. TTL baixo é mais ágil. Registros de alias apontando para um ELB herdam um TTL de 60 segundos que você não pode alterar, exatamente por causa desse equilíbrio.

Os tipos de registro

Um registro é nome | TTL | classe | tipo | valor. Os que importam:

Tipo Valor Para que serve, e o que morde
A IPv4 (32 bits) Nome para endereço. O cavalo de batalha.
AAAA IPv6 (128 bits) Mesma função, IPv6. Quatro vezes mais bits, daí o nome.
CNAME outro nome Apelido. O resolver recomeça a busca no alvo.
NS nome de um servidor Delegação. Onde vive o galho de baixo.
SOA metadados da zona Serial, refresh, retry, expire e o TTL negativo. Um por zona.
MX servidor de e-mail + prioridade Número menor ganha. Aponta para nome, nunca para IP.
TXT texto livre SPF, DKIM, DMARC, provas de posse de domínio.
SRV serviço + protocolo + porta _sip._tcp.exemplo.com. Porta dentro do DNS.
PTR um nome Reverso, de IP para nome, embaixo de in-addr.arpa.
CAA qual autoridade pode emitir certificado Barra emissão indevida de certificado.

As regras do CNAME, que causam a maioria dos incidentes reais

  1. Um CNAME não pode coexistir com nenhum outro registro no mesmo nome. Está na RFC 1034. Se www é um CNAME, ele não pode ter também um TXT ou um MX.
  2. Logo, um CNAME nunca pode ficar no apex da zona. O apex é obrigado a carregar SOA e NS, e a regra 1 proíbe a convivência. exemplo.com não pode ser CNAME. www.exemplo.com pode.
  3. Cadeia custa viagem. a → b → c → A são três resoluções encadeadas antes de qualquer byte útil.

A regra 2 parece uma tecnicalidade de RFC. Não é. Ela é a razão de existir de um recurso inteiro do Route 53, como veremos.

Delegação e glue records

Os registros NS aparecem duas vezes: na zona pai (o .com dizendo "exemplo.com fica nesses servidores") e dentro da própria zona filha, como cópia autoritativa. A cópia do pai é o que os resolvers seguem, e ela não é dado autoritativo, e é justamente por isso que ela chega como encaminhamento e não como resposta.

Existe uma dependência circular escondida aí. Se o servidor de nomes de exemplo.com se chama ns1.exemplo.com, você precisa da zona para achar a zona. A solução é o glue record: o pai publica, junto da delegação, um registro A para ns1.exemplo.com. Essa cola quebra o ciclo. Quando os servidores estão em outro domínio, como acontece com o Route 53 (ns-123.awsdns-45.com), não há ciclo e não há cola.

Route 53

O serviço de DNS da AWS é três coisas independentes empacotadas junto, e a maior parte da confusão inicial vem de tratá-las como uma só:

  • Registro de domínio, a função de registrar, comprar e renovar exemplo.com.
  • Hosted zone, o container dos dados autoritativos.
  • Health checks e políticas de roteamento, a lógica de tráfego por cima dos registros.

Você pode registrar o domínio em qualquer lugar e hospedar a zona no Route 53, ou o inverso. O fio que liga as duas pontas é a delegação NS colada no registrar.

O Route 53 é um serviço global, não regional. Uma hosted zone não mora em us-east-1. Os servidores de nome dele são anycast, e o serviço carrega um SLA de 100% de disponibilidade, o único da AWS com esse número.

Public hosted zone

Responde a consultas do mundo inteiro. Ao criar uma, o Route 53 devolve um delegation set de 4 servidores de nome, deliberadamente espalhados por TLDs diferentes (.com, .net, .org, .co.uk), para que a queda de um TLD não isole a sua zona.

A falha mais comum do serviço inteiro é operacional, não técnica: criar a hosted zone e nunca colar os NS no registrar. A variação cruel é apagar e recriar a zona, porque a nova zona ganha um delegation set novo, e o domínio continua apontando para servidores que não respondem mais por ele.

Registros de alias: a resposta da AWS para o problema do apex

O cenário é banal. Você quer que exemplo.com aponte para um Application Load Balancer. O ALB só te dá um nome DNS, porque os IPs dele mudam sozinhos conforme ele escala, como discutido em Load balancer. Apontar um nome para outro nome é trabalho de CNAME. Mas CNAME é proibido no apex. Beco sem saída no DNS padrão.

O Route 53 resolve isso com um registro proprietário, o Alias. Por dentro ele é um ponteiro. Mas quando a consulta chega, o Route 53 resolve o alvo por conta própria e devolve ao cliente um A ou AAAA comum. O cliente nunca fica sabendo que havia um ponteiro no meio. É uma indireção que existe só do lado do servidor autoritativo, e por isso escapa das regras da RFC.

CNAME Alias
Permitido no apex Não Sim
O cliente recebe um CNAME um A / AAAA
Alvo qualquer nome recursos AWS e registros da mesma zona
Custo por consulta cobrado grátis para alvos AWS
TTL você define herdado do alvo
Avalia saúde do alvo não sim, via Evaluate Target Health

Alvos válidos: ELB, CloudFront, endpoint de site do S3, API Gateway, VPC interface endpoint, Global Accelerator, Elastic Beanstalk e outro registro da mesma hosted zone. Não vale apontar alias para uma instância EC2. Para EC2, o caminho é um registro A para o Elastic IP, que é o endereço que não muda, pela razão explicada em IP privado, público e elástico.

Quando usar alias e quando usar CNAME

A regra prática não é "domínio interno usa alias e externo usa CNAME". A pergunta certa é o que está do outro lado:

Alvo Registro
Recurso AWS (ELB, CloudFront, site no S3, API Gateway) Alias
Outro registro da mesma hosted zone Alias
Hostname externo (Netlify, Vercel, GitHub Pages, qualquer SaaS) CNAME
Um IP que é seu (Elastic IP, servidor on-premises) A

Num subdomínio apontando para recurso AWS, os dois funcionam, e ainda assim o alias ganha: uma resolução em vez de duas e consulta não cobrada. Num subdomínio apontando para fora da AWS, o alias sequer aparece como opção no console, porque não existe onde colocar um hostname que a AWS não enxerga.

A armadilha aparece quando essas duas condições se cruzam. Se você quiser o apex exemplo.com servido pelo Netlify, não existe combinação possível dentro do Route 53: CNAME é proibido no apex e alias não alcança alvo externo. As saídas reais são delegar a zona ao DNS do próprio Netlify, apontar um registro A para o IP de load balancer que eles publicam, ou colocar um CloudFront na frente e voltar ao caminho feliz do alias.

E vale corrigir uma confusão comum: DNS não redireciona. Apontar www.exemplo.com para exemplo.com entrega o usuário no servidor certo, mas o navegador continua exibindo www.exemplo.com na barra de endereços. Trocar a URL é trabalho de HTTP, uma regra de redirect no listener do ALB, uma function no CloudFront ou um return 301 no servidor web. O registro de DNS continua sendo necessário nos dois casos, porque o redirect só pode acontecer depois que a conexão foi estabelecida.

O alias não é invenção da AWS, mas o da AWS é o mais restrito

Não existe registro ALIAS em RFC nenhuma. Ele nunca trafega na rede e nenhum resolver jamais recebeu um. É sempre o mesmo truque: o servidor autoritativo resolve o alvo por dentro e responde um A comum. Como é uma jogada do lado do servidor, cada provedor precisou implementar a sua, e cada um batizou de um jeito:

Provedor Nome que dá Aceita hostname externo qualquer?
Route 53 Alias Não, só recursos AWS e registros da mesma zona
Cloudflare CNAME flattening Sim
DNSimple ALIAS Sim
easyDNS ANAME Sim
NS1 ALIAS Sim

Ou seja, esperar que o seu provedor de DNS resolva o problema do apex é razoável, é um recurso comum. O que surpreende é que a versão da AWS é a mais limitada da lista. A maioria dos concorrentes achata para qualquer nome da internet, e a AWS restringiu deliberadamente aos próprios recursos.

Isso tem uma consequência operacional que só aparece tarde: registros de alias não sobrevivem a uma migração de provedor. Exportar a zona do Route 53 e importar em outro lugar deixa cada alias como um dado que o destino não sabe representar. CNAME e A migram limpos. Se portabilidade importa, prefira CNAME nos subdomínios e aceite que o apex vai exigir tratamento específico em cada provedor.

Existe uma saída padronizada surgindo. A RFC 9460 define os tipos SVCB e HTTPS, e o HTTPS em modo alias faz aliasing de apex como um registro de verdade, na rede, previsto em norma. Chrome, Safari e Firefox já consultam por ele, e Route 53 e Cloudflare já permitem publicá-lo. Ainda não substituiu os dialetos proprietários, porque um registro novo só ajuda quando todo resolver e todo cliente do mundo entendem, e essa cauda é longa. Mas é o caminho de saída.

Private hosted zones

Mesmos dados de zona, mas ela só responde dentro das VPCs que você associar a ela. É o jeito de fazer db.interno.exemplo.com resolver para 10.0.4.20 sem expor nada para a internet.

Três requisitos em que todo mundo tropeça uma vez:

  • A VPC precisa de enableDnsSupport e enableDnsHostnames ligados. Os dois, não um.
  • A resolução acontece pelo resolver da Amazon no início do CIDR da VPC mais 2, ou seja, 10.0.0.2 numa VPC 10.0.0.0/16, também alcançável em 169.254.169.253. Uma instância configurada para usar 8.8.8.8 nunca vai enxergar a sua zona privada, por mais correta que ela esteja. O endereçamento dessa VPC está em CIDR e subnets na VPC.
  • Associação entre contas diferentes é possível, mas precisa ser autorizada dos dois lados via CLI ou API, não sai pelo console.

Split-horizon DNS. Você pode ter uma zona pública e uma privada para o mesmo nome. A instância dentro da VPC associada recebe a resposta privada, a internet recebe a pública. Mesmo hostname, resposta diferente conforme o lugar de onde se pergunta. É extremamente útil e é a origem clássica do "funciona na minha máquina mas não na VPC", ou do seu inverso.

Precedência. Entre zonas privadas, a correspondência mais específica ganha, e ganha por completo. Se existem as zonas exemplo.com e api.exemplo.com, uma consulta a api.exemplo.com é respondida inteiramente pela segunda. A primeira não é consultada nem como fallback.

Híbrido. Uma zona privada sozinha não alcança o seu datacenter. Quem faz isso é o Route 53 Resolver, com dois tipos de endpoint:

  • Inbound endpoint: os servidores on-premises encaminham consultas para dentro da AWS e conseguem resolver as zonas privadas.
  • Outbound endpoint mais resolver rules: as instâncias na AWS encaminham consultas de corp.local para fora, ao DNS on-premises.

As políticas de roteamento

Uma camada acima dos registros. Vários registros com o mesmo nome, e o Route 53 escolhe qual devolver:

Política Base da decisão
Simple um registro só, sem lógica
Weighted pesos proporcionais de 0 a 255, peso 0 desliga. É o canário.
Latency menor latência medida até a região AWS
Failover primário até o health check falhar, aí o secundário
Geolocation continente, país ou estado do usuário, mais um default
Geoproximity distância até o recurso, com um bias ajustável
Multivalue answer até 8 registros saudáveis, embaralhados
IP-based blocos CIDR do cliente mapeados para respostas

Duas observações que evitam mau uso. Multivalue answer não é um load balancer. Ele não conhece carga, não termina conexão e depende do cliente escolher um dos endereços devolvidos. Ele é tolerância a falha barata, não distribuição.

E health checks são o que dá vida a metade dessa tabela. Eles sondam um endpoint a partir de verificadores em várias regiões e o consideram saudável quando um número suficiente deles concorda. Também existem em dois formatos menos óbvios: calculated, combinando outros health checks numa expressão booleana, e ancorado num alarme do CloudWatch, que é como se checa a saúde de algo que não tem endpoint público nenhum para sondar.

Como isso se conecta com o resto

O DNS é a camada que torna todo o resto substituível. Em Load balancer, a terceira função listada era abstração: o cliente conhece um endereço estável enquanto as máquinas atrás mudam. O DNS é a camada onde essa estabilidade é declarada, e o alias é o mecanismo que permite declará-la no apex do domínio.

Também é o contraponto exato do Gateway Load Balancer. Lá, o objeto não aparecia em DNS nenhum porque era um desvio de rota, e não um destino. Aqui, tudo é destino: o DNS só sabe responder "para qual endereço", nunca "por onde passar".

E é onde a diferença entre endereço privado e público de IP privado, público e elástico deixa de ser uma propriedade da rede e vira uma decisão de nome: a mesma string, resolvida para o IP privado dentro da VPC e para o público fora dela.

As cinco coisas para levar

  1. DNS é delegação por encaminhamento, não uma tabela de consulta. Os registros NS são as articulações da árvore.
  2. TTL significa que toda mudança é eventualmente consistente. Planeje migrações de trás para frente, a partir dele.
  3. CNAME não pode ficar no apex nem dividir o nome com outro registro. Essa restrição explica a existência inteira do alias.
  4. Alias é exclusivo do Route 53, é grátis, funciona no apex e chega ao cliente como um registro A.
  5. Private hosted zone só funciona pelo resolver .2 da VPC, e split-horizon significa que o mesmo nome pode legitimamente responder coisas diferentes dependendo de onde você pergunta.

Referências