Dia 16: DNS Server no Linux — Bind9, unbound e Zonas
/etc/hosts são essenciais para este artigo.
O DNS (Domain Name System) é o sistema que traduz nomes de máquina em endereços IP e vice-versa. Em Linux, os dois servidores DNS mais utilizados são o BIND9 (servidor autoritativo e recursivo, mantido pela ISC) e o unbound (resolver recursivo e caching, mantido pela NLnet Labs). Este artigo mostra como instalar e configurar ambos, criar zonas forward e reverse, e diagnosticar problemas comuns — numa abordagem que serve tanto Ubuntu/Debian como RHEL/Rocky/Alma.
sudo para instalar pacotes e editar configuração.
Neste artigo
- Como Funciona o DNS no Linux
- Componentes de um DNS Server
- Instalar Bind9 e unbound
- Configurar Bind9 — named.conf
- Zona Forward — Resolução de Nomes
- Zona Reverse — PTR e IP para Nome
- Configurar unbound como Caching Resolver
- Testar e Verificar com dig e named-checkconf
- Erros Comuns e Soluções
- Checklist de Configuração
Como Funciona o DNS no Linux
O DNS opera em camadas. Quando uma aplicação precisa de resolver servidor.exemplo.pt, o resolvedor local (geralmente a libc via /etc/resolv.conf) envia a query ao servidor DNS configurado. Esse servidor pode agir como resolver recursivo (pergunta aos root servers, depois aos TLD servers, depois ao servidor autoritativo) ou como servidor autoritativo (responde diretamente porque é o responsável pela zona).
A hierarquia DNS começa nos 13 root servers (letras A a M), desce para os TLDs (.pt, .com), e chega aos servidores autoritativos de cada domínio. Cada nível delega autoridade para o nível inferior através de registos NS (Name Server). A especificação original do DNS está nos RFC 1034 (conceitos) e RFC 1035 (implementação e sintaxe).
Em Linux, o fluxo típico é: aplicação → libc resolver → /etc/resolv.conf → servidor DNS (Bind9 ou unbound) → Internet. O /etc/hosts tem prioridade sobre o DNS para nomes locais — o sistema consulta-o primeiro antes de qualquer query DNS, controlado pela diretiva files em /etc/nsswitch.conf.
Componentes de um DNS Server
Antes de instalar, é importante perceber a diferença entre os três papéis que um servidor DNS pode desempenhar. Um servidor pode ter um ou vários destes papéis em simultâneo, embora em produção seja boa prática separá-los.
| Papel | Função | Software típico |
|---|---|---|
| Autoritativo | Responde definitivamente para as zonas que domina (ex: exemplo.pt) |
BIND9, NSD, PowerDNS |
| Recursivo / Caching | Resolve nomes para os clientes, guarda respostas em cache para acelerar queries futuras | unbound, BIND9, dnsmasq |
| Forwarder | Recebe queries dos clientes e reencaminha-as para outro resolver (ex: 8.8.8.8, 1.1.1.1) | unbound, BIND9, dnsmasq |
Neste artigo configuramos o BIND9 como servidor autoritativo (com zonas forward e reverse) e o unbound como caching resolver. Esta separação é o padrão recomendado para redes de PME — o BIND9 responde pelos domínios internos, o unbound faz cache das queries externas para acelerar a navegação.
Instalar Bind9 e unbound
A instalação varia conforme a distribuição. Em Ubuntu/Debian o pacote chama-se bind9, em RHEL/Rocky/Alma chama-se bind. O unbound tem o mesmo nome em ambas as famílias.
Ubuntu / Debian:
sudo apt update
sudo apt install bind9 bind9utils bind9-doc dnsutils unbound
RHEL / Rocky / Alma:
sudo dnf install bind bind-utils unbound
O pacote dnsutils (Ubuntu) ou bind-utils (RHEL) fornece as ferramentas dig, nslookup e host, essenciais para testar a configuração. Depois de instalar, confirmar que o serviço está ativo:
sudo systemctl status named
sudo systemctl status unbound
No Ubuntu/Debian o serviço chama-se bind9, no RHEL chama-se named. Ambos correspondem ao mesmo binário (/usr/sbin/named), apenas o nome do serviço systemd difere.
Configurar Bind9 — named.conf
A configuração do BIND9 está no ficheiro named.conf. Em Ubuntu/Debian, este ficheiro está em /etc/bind/named.conf e inclui outros três: named.conf.options (opções globais), named.conf.local (zonas locais) e named.conf.default-zones (zonas pré-definidas). Em RHEL/Rocky, tudo fica num único /etc/named.conf. A documentação de referência está em BIND9 Reference (ISC).
Passo 1 — Configurar as opções globais (named.conf.options em Ubuntu/Debian ou secção options {} em RHEL):
options {
directory "/var/cache/bind";
// Rede interna autorizada a fazer queries recursivas
allow-query { localhost; 192.168.1.0/24; };
// Rede autorizada a fazer transferencia de zona (AXFR)
allow-transfer { 192.168.1.20; };
// Nao permitir recursao para redes externas
recursion no;
// DNSSEC validation
dnssec-validation auto;
listen-on-v6 { none; };
};
Parâmetros principais:
allow-query— define quais redes podem enviar queries ao servidor. Restringir a localhost e LAN evita open resolvers, que são explorados em ataques DDoS de amplificação.allow-transfer— controla quais servidores podem fazer transferência de zona (AXFR). Apenas o servidor secundário deve estar aqui. Nunca deixar aberto — expõe toda a zona.recursion no— desliga a recursão no BIND9 autoritativo. A recursão fica no unbound, que é mais eficiente para isso.dnssec-validation auto— valida respostas DNSSEC usando trust anchors geridos pelo BIND. Recomendado para ambientes com Internet.
Passo 2 — Declarar as zonas em named.conf.local (Ubuntu/Debian) ou no final de /etc/named.conf (RHEL):
zone "exemplo.pt" {
type master;
file "/etc/bind/zones/db.exemplo.pt";
};
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.192.168.1";
};
A primeira zona é a forward (resolução nome → IP), a segunda é a reverse (IP → nome). O nome da zona reverse é o endereço de rede invertido com sufixo in-addr.arpa — para a rede 192.168.1.0/24, fica 1.168.192.in-addr.arpa.
Zona Forward — Resolução de Nomes
A zona forward contém os registos que mapeiam nomes em IPs. O ficheiro de zona usa o formato definido no RFC 1035 — cada linha é um registo DNS com tipo específico (A, CNAME, MX, TXT, etc.).
Criar o diretório e o ficheiro de zona forward:
sudo mkdir -p /etc/bind/zones
sudo nano /etc/bind/zones/db.exemplo.pt
Conteúdo do ficheiro de zona forward:
$TTL 86400
@ IN SOA ns1.exemplo.pt. admin.exemplo.pt. (
2026072401 ; Serial (AAAA-MM-DD-NN)
3600 ; Refresh (1h)
1800 ; Retry (30min)
604800 ; Expire (7 dias)
86400 ) ; Minimum TTL (24h)
; Servidores de nomes
@ IN NS ns1.exemplo.pt.
@ IN NS ns2.exemplo.pt.
; Registos A (nome -> IPv4)
ns1 IN A 192.168.1.10
ns2 IN A 192.168.1.11
www IN A 192.168.1.20
mail IN A 192.168.1.30
app IN A 192.168.1.40
; Registos CNAME (alias)
blog IN CNAME www.exemplo.pt.
; Registo MX (mail exchange)
@ IN MX 10 mail.exemplo.pt.
; Registo TXT (SPF)
@ IN TXT "v=spf1 mx -all"
Tipos de registo nesta zona:
- SOA (Start of Authority) — define o servidor primário, email do administrador (com ponto em vez de @), número de série e temporizadores de sincronização. O serial deve incrementar a cada alteração — convenção
YYYYMMDDNN. - NS — lista os servidores autoritativos para a zona. Cada servidor NS precisa de um registo A correspondente.
- A — mapeia um nome num endereço IPv4. Para IPv6 usa-se AAAA.
- CNAME — cria um alias (apelido) que aponta para outro nome. Útil quando vários nomes servem o mesmo host.
- MX — indica qual servidor recebe email para o domínio, com prioridade (número menor = prioridade maior).
- TXT — texto arbitrário, usado para SPF, DKIM, verificação de domínio, etc.
ns1.exemplo.pt.) é obrigatório em registos fully qualified. Sem o ponto, o BIND9 anexa o nome da zona e fica ns1.exemplo.pt.exemplo.pt. — um erro silencioso que causa falhas de resolução.
Zona Reverse — PTR e IP para Nome
A zona reverse faz o caminho inverso: dado um IP, devolve o nome associado. Isto é essencial para serviços de email (muitos servidores SMTP rejeitam correio de IPs sem registo PTR válido), logging legível e ferramentas de diagnóstico. A zona é denominada com o endereço de rede invertido e o sufixo in-addr.arpa.
sudo nano /etc/bind/zones/db.192.168.1
Conteúdo do ficheiro de zona reverse:
$TTL 86400
@ IN SOA ns1.exemplo.pt. admin.exemplo.pt. (
2026072401 ; Serial
3600 ; Refresh
1800 ; Retry
604800 ; Expire
86400 ) ; Minimum TTL
; Servidores de nomes
@ IN NS ns1.exemplo.pt.
@ IN NS ns2.exemplo.pt.
; Registos PTR (IP -> nome)
10 IN PTR ns1.exemplo.pt.
11 IN PTR ns2.exemplo.pt.
20 IN PTR www.exemplo.pt.
30 IN PTR mail.exemplo.pt.
40 IN PTR app.exemplo.pt.
No registo PTR, o número à esquerda é o último octeto do endereço IP. Para o IP 192.168.1.20, na zona 1.168.192.in-addr.arpa, escreve-se apenas 20 — o BIND9 completa com o prefixo da zona. Para redes /16 ou /8, a lógica é a mesma: inverter os octetos correspondentes ao tamanho da máscara.
Depois de criar os ficheiros de zona, ajustar as permissões para o BIND9 conseguir ler:
sudo chown -R bind:bind /etc/bind/zones
sudo chmod 644 /etc/bind/zones/db.*
Em RHEL/Rocky o utilizador do BIND9 chama-se named em vez de bind: sudo chown -R named:named /etc/named/zones.
Configurar unbound como Caching Resolver
O unbound é um resolver recursivo moderno com caching agressivo, DNSSEC por defeito e boa performance. É ideal como DNS interno para os clientes da LAN — faz cache das queries externas e reencaminha as queries internas para o BIND9 autoritativo. A documentação de referência está em NLnet Labs — unbound.conf.
O ficheiro principal fica em /etc/unbound/unbound.conf (Ubuntu/Debian e RHEL). Editar:
server:
# Interface onde o unbound escuta
interface: 192.168.1.10
interface: 127.0.0.1
# Porta 53 (predefinida)
port: 53
# Redes autorizadas a usar o resolver
access-control: 127.0.0.0/8 allow
access-control: 192.168.1.0/24 allow
# DNSSEC validation
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Esconder versao
hide-version: yes
# Esconder identidade
hide-identity: yes
# Nao responder por zonas onde o BIND9 e autoritativo
local-zone: "exemplo.pt." redirect
local-data: "exemplo.pt. 3600 IN NS ns1.exemplo.pt."
stub-zone:
name: "exemplo.pt."
stub-addr: 192.168.1.10@53
# Forwarders para queries externas
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 8.8.8.8
Parâmetros principais do unbound:
interface— endereço IP onde o unbound escuta. Se o BIND9 já está na porta 53 no mesmo IP, o unbound tem de escutar noutro IP ou noutro porto. Numa configuração típica, o BIND9 corre em 192.168.1.10:53 e o unbound em 127.0.0.1:53 ou noutro servidor.access-control— lista de controlo de acesso. Apenas as redes listadas podem usar o resolver. Restringir para evitar open resolvers.stub-zone— reencaminha queries paraexemplo.ptao BIND9 autoritativo. Isto une o resolver e o autoritativo sem precisar de dois servidores distintos.forward-zone— envia todas as outras queries para um resolver público (1.1.1.1, 8.8.8.8). O unbound faz cache das respostas, reduzindo latência.auto-trust-anchor-file— caminho para o trust anchor DNSSEC. O unbound valida assinaturas DNSSEC automaticamente.
Antes de iniciar o unbound, gerar o root trust anchor para DNSSEC:
sudo unbound-anchor -a /var/lib/unbound/root.key
sudo unbound-checkconf
sudo systemctl enable --now unbound
O unbound-checkconf valida a sintaxe do ficheiro antes de arrancar — se houver erro, indica a linha exata.
Testar e Verificar com dig e named-checkconf
Depois de configurar, é preciso verificar a sintaxe e testar a resolução. O BIND9 inclui ferramentas de validação próprias — named-checkconf valida o ficheiro de configuração e named-checkzone valida cada ficheiro de zona. Referência em BIND9 Administration Tools.
Passo 1 — Validar a configuração do BIND9:
sudo named-checkconf /etc/bind/named.conf
sudo named-checkzone exemplo.pt /etc/bind/zones/db.exemplo.pt
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1
Se não houver erros, o output é zone exemplo.pt/IN: loaded serial 2026072401 OK. Se houver, indica a linha e o problema.
Passo 2 — Reiniciar o BIND9 e testar com dig:
sudo systemctl restart bind9 # Ubuntu/Debian
sudo systemctl restart named # RHEL/Rocky
# Testar resolucao forward
dig @192.168.1.10 www.exemplo.pt
# Testar resolucao reverse
dig @192.168.1.10 -x 192.168.1.20
# Testar registo MX
dig @192.168.1.10 exemplo.pt MX
# Verificar com nslookup
nslookup app.exemplo.pt 192.168.1.10
Output esperado para dig @192.168.1.10 www.exemplo.pt:
;; ANSWER SECTION:
www.exemplo.pt. 86400 IN A 192.168.1.20
;; Query time: 0 msec
;; SERVER: 192.168.1.10#53(192.168.1.10)
A presença da secção ANSWER SECTION com o registo A e o IP correto confirma que a zona forward está a funcionar. Para a zona reverse, dig -x 192.168.1.20 deve devolver 20.1.168.192.in-addr.arpa. IN PTR www.exemplo.pt..
Passo 3 — Testar o unbound:
# Query interna (deve resolver via stub-zone para BIND9)
dig @127.0.0.1 www.exemplo.pt
# Query externa (deve resolver via forwarders)
dig @127.0.0.1 kbase.pt
# Verificar DNSSEC
dig @127.0.0.1 dnssec.works +dnssec
A flag +dnssec faz o dig pedir registos DNSSEC. Se o unbound estiver a validar corretamente, a resposta inclui a flag ad (Authentic Data) no cabeçalho.
Passo 4 — Configurar os clientes para usar o novo DNS:
# Ubuntu/Debian com netplan
sudo nano /etc/netplan/01-netcfg.yaml
# Adicionar sob o interface desejado:
# nameservers:
# addresses: [192.168.1.10, 192.168.1.11]
sudo netplan apply
# RHEL/Rocky com nmcli
sudo nmcli connection modify eth0 ipv4.dns "192.168.1.10 192.168.1.11"
sudo nmcli connection up eth0
# Verificar resolver ativo
cat /etc/resolv.conf
Erros Comuns e Soluções
Durante a configuração de um DNS Server em Linux, alguns problemas aparecem com frequência. A tabela seguinte reúne os mais comuns e como resolver.
| Problema | Causa | Solução |
|---|---|---|
named-checkzone reporta “missing final dot” |
Nome fully qualified sem ponto final (ex: ns1.exemplo.pt em vez de ns1.exemplo.pt.) |
Acrescentar o ponto final em todos os nomes fully qualified nos registos SOA, NS, MX e CNAME |
| Serial não incrementa após alteração | O serial do SOA não foi alterado — o servidor secundário não detecta mudança | Incrementar o serial com convenção YYYYMMDDNN e reiniciar o BIND9 |
dig devolve SERVFAIL |
Erro de sintaxe no ficheiro de zona ou permissões incorretas | Correr named-checkconf e named-checkzone; verificar /var/log/syslog ou journalctl -u bind9 |
| Conflito de porta 53 entre BIND9 e unbound | Ambos tentam escutar na porta 53 do mesmo IP | Configurar BIND9 em 192.168.1.10:53 e unbound em 127.0.0.1:53 ou noutro IP; ou desativar recursão no BIND9 e deixar só o unbound |
| Resolução externa lenta ou falha no unbound | Forwarders indisponíveis ou DNSSEC a falhar (relógio desactualizado) | Verificar forwarders com dig @1.1.1.1 kbase.pt; sincronizar relógio com NTP; validar root.key com unbound-anchor |
| Registo PTR não resolve | Zona reverse não declarada no named.conf ou octeto errado |
Confirmar que a zona reverse está em named.conf.local e que o octeto no PTR corresponde ao último octeto do IP |
systemd-resolved interfere na porta 53 |
Ubuntu/Debian tem systemd-resolved a ouvir na 127.0.0.53:53 |
Desativar: sudo systemctl disable --now systemd-resolved e remover /etc/resolv.conf simbólico |
Checklist de Configuração
Antes de considerar o DNS Server pronto para produção, verificar todos os itens seguintes. Esta checklist funciona tanto para um laboratório como para uma rede corporativa interna.
- Confirmar que
named-checkconfpassa sem erros - Confirmar que
named-checkzonepassa para a zona forward e reverse - Verificar que todos os registos fully qualified terminam com ponto final
- Confirmar que o serial do SOA foi incrementado após cada alteração
- Testar resolução forward com
dig @server nome A - Testar resolução reverse com
dig @server -x IP - Verificar
allow-queryrestrito à LAN (não open resolver) - Verificar
allow-transferrestrito ao servidor secundário - Confirmar que
unbound-checkconfpassa sem erros - Testar DNSSEC com
dig @127.0.0.1 dnssec.works +dnssec(flagadpresente) - Configurar os clientes para usar o novo DNS em
/etc/resolv.confou via netplan/nmcli - Abrir porta 53 (TCP e UDP) na firewall — ver Dia 9: Firewalls Linux
Artigos Relacionados
- Dia 8: Redes Linux — ip, ss, nmcli e DNS — fundamentos de rede e DNS que este artigo expande
- Dia 9: Firewalls Linux — iptables, nftables, UFW e firewalld — abrir porta 53 para o DNS Server funcionar
- Dia 7: Systemd no Linux — Services, Timers e journalctl — gerir serviços named e unbound com systemd
- Dia 15: Apache e Nginx — Web Server e Virtual Hosts — virtual hosts baseados em nome dependem de DNS correto
- Dia 5: Processos e Jobs no Linux — diagnosticar processos named/unbound e sinais