Apresento a vocês um tutorial simples de como criar um servidor DNS recursivo (usado para cache DNS de navegação local e navegação de usuários).
Leitura de outras dicas recomendadas:
- Criação da maquina virtual VMware com ajustes finos;
- Instalação do Debian 12 netinstall x86_64 (amd64);
- Instalação de programas básicos;
- Data/hora via NTP;
- Ajuste fino no kernel Linux;
Instalando Unbound
Os procedimentos abaixo foram feitos e pensados para uma nova instalação limpa, não recomendo que você as execute em um servidor que já esteja rodando o Unbound.
# Instalar Unbound:
apt-get -y install unbound
# Instalar ferramentas de DNS:
apt-get -y install dnsutils
# Ativar no systemd para subir durante o boot:
systemctl enable unbound
# Baixar lista de root-servers atualizada:
mkdir -p /etc/unbound
wget https://www.internic.net/domain/named.root -4 -O /etc/unbound/named.cache
Precisamos obter a lista de root-servers atualizadas, os root-servers são servidores espalhados globalmente e possuem os dominos TLDN (.br, .com, .net, .io, .arpa., etc…) e possuem a zona raiz apontando para todos os servidores de segundo nível do mundo (.br aponta para registro.br no Brasil, .ar aponta para os servidores da Argentina, etc…).
# Baixar lista de root-servers atualizada:
mkdir -p /etc/unbound
wget https://www.internic.net/domain/named.root -4 -O /etc/unbound/named.cache
# Produzir listas em formato intercambiável para uso nos
# scripts diversos e de monitoramento
cat /etc/unbound/named.cache | egrep -v '^;' > /tmp/nc-nocmts.txt
cat /tmp/nc-nocmts.txt | egrep -v NS > /tmp/nc-ipaddr.txt
cat /tmp/nc-ipaddr.txt | awk '{print $1";"$4}' > /tmp/nc-table.dat
cat /tmp/nc-table.dat | cut -f2 -d';' > /tmp/nc-iponly.dat
# Arquivos finais:
cat /tmp/nc-table.dat > /etc/unbound/root-servers-table.dat
cat /tmp/nc-iponly.dat > /etc/unbound/root-servers-ips.dat
cat /tmp/nc-iponly.dat | egrep -v ':' > /etc/unbound/root-servers-ipv4.dat
cat /tmp/nc-iponly.dat | egrep ':' > /etc/unbound/root-servers-ipv6.dat
Configurando Unbound do zero
Vamos limpar a configuração padrão e criar tudo do zero.
# Garantir config padrao no formato /etc/unbound/unbound.conf.d/
mkdir -p /etc/unbound/unbound.conf.d
rm -f /etc/unbound/unbound.conf.d/* 2>/dev/null
# Recriar todas as configs do zero:
# - Config principal:
(
echo
echo 'server:'
echo ' module-config: "respip validator iterator"'
echo
echo 'include-toplevel: "/etc/unbound/unbound.conf.d/*.conf"'
echo
) > /etc/unbound/unbound.conf
Leia os comentários e altere de acordo com as suas necessidades, em seguida cole os blocos de código no terminal.
# - Chave pública da raiz do DNS (Root Zone Key), usado para DNSSEC:
(
echo
echo 'server:'
echo
echo ' auto-trust-anchor-file: "/var/lib/unbound/root.key"'
echo
) > /etc/unbound/unbound.conf.d/21-root-auto-trust-anchor-file.conf
# - Gerador de estatísticas:
(
echo 'server:'
echo ' statistics-interval: 0'
echo ' extended-statistics: yes'
echo ' statistics-cumulative: no'
echo
) > /etc/unbound/unbound.conf.d/31-statisticas.conf
# - Protocolos - ativar todos
# - Nota: coloque "no" no do-ip6 se você não tem IPv6 no servidor
(
echo
echo 'server:'
echo
echo ' do-ip4: yes'
echo ' do-ip6: yes'
echo ' do-udp: yes'
echo ' do-tcp: yes'
echo
) > /etc/unbound/unbound.conf.d/41-protocols.conf
# - ACL de uso - IPs locais (loopback e privados) confiaveis
# - Nota: IPs privados definidos em RFC para IPv4:
# rfc 922, rfc 919, rfc 1112, rfc 1122,
# rfc 1918, rfc 2544, rfc 3068, rfc 3171,
# rfc 3330, rfc 3927, rfc 5735, rfc 5736,
# rfc 5737, rfc 6598,
#
# - Nota: IPs privados/não-globais definidos em RFC para IPv6:
# rfc 3849, rfc 9637
#
(
echo
echo 'server:'
echo
echo ' # Loopback'
echo ' access-control: 127.0.0.1/32 allow'
echo ' access-control: ::1/128 allow'
echo
echo ' # Todas as faixas privadas RFCs'
echo ' access-control: 0.0.0.0/8 allow'
echo ' access-control: 10.0.0.0/8 allow'
echo ' access-control: 100.64.0.0/10 allow'
echo ' access-control: 127.0.0.0/8 allow'
echo ' access-control: 169.254.0.0/16 allow'
echo ' access-control: 172.16.0.0/12 allow'
echo ' access-control: 192.0.0.0/24 allow'
echo ' access-control: 192.0.2.0/24 allow'
echo ' access-control: 192.88.99.0/24 allow'
echo ' access-control: 192.168.0.0/16 allow'
echo ' access-control: 198.18.0.0/15 allow'
echo ' access-control: 198.51.100.0/24 allow'
echo ' access-control: 203.0.113.0/24 allow'
echo ' access-control: 224.0.0.0/4 allow'
echo ' access-control: 240.0.0.0/4 allow'
echo ' access-control: 255.255.255.255/32 allow'
echo ' # Faixas IPv6 privadas'
echo ' access-control: 2001:db8::/32 allow'
echo
echo ' # Faixas IPv6 nao-globais'
echo ' access-control: ::/3 allow'
echo ' access-control: 4000::/2 allow'
echo ' access-control: 8000::/1 allow'
echo
) > /etc/unbound/unbound.conf.d/51-acls-locals.conf
# - ACL de uso - IPs locais públicos (IPv4) e globais (IPv6)
# - Nota: Coloque seus prefixos de IPs publicos,
# prefixos de IPs delegados pelo seu provedor,
# prefixos de IPs do seu ASN,
# informe IPv4 e IPv6, mesmo se não usar o IPv6
#
(
echo
echo 'server:'
echo
echo ' # IPs publicos (IPv4) delegados e proprios:'
echo ' access-control: 45.255.128.0/29 allow'
echo
echo ' # IPs globais (IPv6) delegados e proprios:'
echo ' access-control: 2804:cafe::/126 allow'
echo
) > /etc/unbound/unbound.conf.d/52-acls-trusteds.conf
# - ACL padrao - descartar tudo de IPs nao confiaveis
# - Nota: nao use "refuse" como padrão pois ele gera resposta
# e pode fazer seu DNS ser explorado em DDoS
# usar "deny" pois ele descarta silenciosamente
# os pacotes de IPs desconhecidos
(
echo
echo 'server:'
echo
echo ' # Nao responder para IPs desconhecidos'
echo ' access-control: 0.0.0.0/0 deny'
echo ' access-control: ::/0 deny'
echo
) > /etc/unbound/unbound.conf.d/59-acls-default-policy.conf
# Parametros gerais (tuning) - padrao para 4 nucleos, 64M de RAM
(
echo
echo 'server:'
echo ' outgoing-range: 8192'
echo ' outgoing-port-avoid: 0-1024'
echo ' outgoing-port-permit: 1025-65535'
echo ' num-threads: 4'
echo ' num-queries-per-thread: 1024'
echo ' msg-cache-size: 64m'
echo ' msg-cache-slabs: 4'
echo ' rrset-cache-size: 8m'
echo ' rrset-cache-slabs: 4'
echo ' cache-min-ttl: 60'
echo ' cache-max-ttl: 7200'
echo ' infra-host-ttl: 60'
echo ' infra-lame-ttl: 120'
echo ' infra-cache-numhosts: 10000'
echo ' infra-cache-lame-size: 10k'
echo ' infra-cache-slabs: 4'
echo ' key-cache-slabs: 4'
echo ' rrset-roundrobin: yes'
echo
echo ' hide-identity: yes'
echo ' hide-version: yes'
echo ' harden-glue: yes'
echo ' harden-algo-downgrade: yes'
echo ' harden-below-nxdomain: yes'
echo ' harden-dnssec-stripped: yes'
echo ' harden-large-queries: yes'
echo ' harden-referral-path: no'
echo ' harden-short-bufsize: yes'
echo ' do-not-query-address: 127.0.0.1/8'
echo ' do-not-query-localhost: yes'
echo ' edns-buffer-size: 1472'
echo ' aggressive-nsec: yes'
echo ' delay-close: 10000'
echo ' neg-cache-size: 4M'
echo ' qname-minimisation: yes'
echo ' deny-any: yes'
echo ' ratelimit: 1000'
echo ' unwanted-reply-threshold: 10000'
echo ' use-caps-for-id: yes'
echo ' val-clean-additional: yes'
echo ' minimal-responses: yes'
echo ' prefetch: yes'
echo ' prefetch-key: yes'
echo ' serve-expired: yes'
echo ' so-reuseport: yes'
echo
) > /etc/unbound/unbound.conf.d/61-configs.conf
# Informar em quais enderecos IP locais o unbound deve abrir
# a porta 53/tcp e 53/udp para escuta de requisicoes
# - Escutar sempre nos ips de loopback
(
echo
echo 'server:'
echo ' interface: 127.0.0.1'
echo ' interface: ::1'
echo
) > /etc/unbound/unbound.conf.d/62-listen-loopback.conf
# - Escutar sempre nos ips externos
# * usar 0.0.0.0 não é uma boa ideia, embora funcione
# essa config causa assincronia no ip de resposta
# nos casos em que o servidor tem mais de um IP
# * correto: crie uma linha 'interface:' para cada IP
# publico ou de loopback
(
echo
echo 'server:'
echo ' interface: 0.0.0.0'
echo ' interface: ::'
echo
) > /etc/unbound/unbound.conf.d/63-listen-interfaces.conf
# - Hyperlocal Cache (opcional)
# -- Requer lista de root-servers do inicio do tutorial!
if [ -f /etc/unbound/root-servers-ips.dat ]; then
(
echo
echo 'server:'
echo ' auth-zone:'
echo ' name: "."'
for addr in $(cat /etc/unbound/root-servers-ips.dat); do
echo " master: $addr"
done
echo ' fallback-enabled: yes'
echo ' for-downstream: no'
echo ' for-upstream: yes'
echo ' zonefile: ""'
echo
) > /etc/unbound/unbound.conf.d/89-hyperlocal-cache.conf
fi
# - Controle remoto local do processo:
# - Nota: somente localhost, por isso nao precisa de certificado
(
echo
echo 'remote-control:'
echo ' control-enable: yes'
echo ' control-interface: 127.0.0.1'
echo ' control-port: 953'
echo ' control-use-cert: "no"'
echo ' control-interface: /run/unbound.ctl'
echo
) > /etc/unbound/unbound.conf.d/99-remote-control.conf
Testando e executando
Até aqui temos a configuração de um servidor Unbound para DNS Recursivo de alta qualidade. Vamos testar antes de continuar para a fase 2.
# Conferir se a configuração está OK:
unbound-checkconf /etc/unbound/unbound.conf
# precisa retornar:
# unbound-checkconf: no errors in /etc/unbound/unbound.conf
# Rodar e testar:
service unbound stop
service unbound start
# Verificar status de execução:
service unbound status
Homologação de DNS
Com o Unbound rodando, vamos testar se ele resolve nomes:
# Testar DNS enviando requisição para o ip de Loopback
# usando varias ferramentas de DNS:
nslookup www.google.com 127.0.0.1
host www.google.com 127.0.0.1
dig @127.0.0.1 www.google.com
# Caso tenha ativado o IPv6 em "do-ip6", teste tambem:
nslookup www.google.com ::1
host www.google.com ::1
dig @::1 www.google.com
# Nota: ping não é ferramenta de teste de DNS!
Caso você enfrente problemas ao resolver nomes, confira se os pacotes estão sendos respondidos, se seu servidor tem acesso a DNS na Internet, testes pontuais (ping e traceroute não são ferramentas de teste de DNS).
Testando acesso externo de DNS para homologação
# 1 - Testar usando servidores de DNS recursivo abertos
# 1.1 - Usando UDP:
dig @1.0.0.1 www.google.com
dig @1.1.1.1 www.google.com
dig @4.2.2.2 www.google.com
dig @4.2.2.6 www.google.com
dig @8.8.4.4 www.google.com
dig @8.8.8.8 www.google.com
dig @9.9.9.9 www.google.com
# 1.2 - Usando TCP:
dig @1.0.0.1 +tcp www.google.com
dig @1.1.1.1 +tcp www.google.com
dig @4.2.2.2 +tcp www.google.com
dig @4.2.2.6 +tcp www.google.com
dig @8.8.4.4 +tcp www.google.com
dig @8.8.8.8 +tcp www.google.com
dig @9.9.9.9 +tcp www.google.com
# 2 - Testar acesso ao root-server a.root-server.net
dig @198.41.0.4 -t ns root-server.net
dig @198.41.0.4 +tcp -t ns root-server.net
Se você encontrar algum problema nos testes acima, investigue e arrume-o antes de continuar.
Implementando AnaBlock
O AnaBlock é uma API de automação de bloqueios judiciais, essa API é hospedada no site anablock.net.br e requer cadastro para ter o acesso, acesse o site https://anablock.net.br/ para se cadastrar.
Nota: somente provedores cadastrados na Anatel (com dispensa ou outorga) devidamente notificados pela Anatel para realizar bloqueios podem ter acesso a API pois os dados retornados possuem segredo de justiça.
Após cadastrar e liberar seus IPs (IPv4 e/ou IPv6) na API do AnaBlock, teste se a API está operacional:
# Testar se a liberação foi realizada:
# Teste de liberacao via IPv4:
curl -4 https://anablock.net.br/acl.php
# Teste de liberacao via IPv6:
curl -6 https://anablock.net.br/acl.php
# Forcar testar apenas IPv4:
curl http://v4.anablock.net.br/acl.php
# Forcar testar apenas IPv6:
curl http://v6.anablock.net.br/acl.php
# Testar se a lista de domínios está sendo enviada
mkdir /etc/anablock
ABLIST="/etc/anablock/anablock.domains"
ABURL="https://api.anablock.net.br/api/domain/all"
curl -v -o $ABLIST $ABURL
# Verificar a contagem de domínios na lista
cat /etc/anablock/anablock.domains | wc -l
Se tudo deu certo até aqui, chegou a hora de colocar o Unbound para bloquear automaticamente os domínios ordenados pela justiça/Anatel.
Crie a configuração do AnaBlock no Unbound:
# Criar arquivo de cache RPZ
mkdir -p /var/lib/unbound
touch /var/lib/unbound/anablock-rpz.zone
chown unbound:unbound /var/lib/unbound/anablock-rpz.zone
# Criar entrada na config do Unbound:
(
echo
echo 'server:'
echo ' rpz:'
echo ' name: "anablock"'
echo ' zonefile: "/var/lib/unbound/anablock-rpz.zone"'
echo
echo 'auth-zone:'
echo ' name: "anablock"'
echo ' url: "https://api.anablock.net.br/domains/rpz"'
echo ' for-downstream: no'
echo ' for-upstream: yes'
echo ' fallback-enabled: no'
echo ' zonefile: "/var/lib/unbound/anablock-rpz.zone"'
echo
) > /etc/unbound/unbound.conf.d/91-anablock.conf
Testar se a nova configuração entrou harmonicamente no Unbound:
# Conferir se a configuração está OK:
unbound-checkconf /etc/unbound/unbound.conf
# precisa retornar:
# unbound-checkconf: no errors in /etc/unbound/unbound.conf
# Reiniciar, escolha uma das ocoes:
# 1 - Reiniciar sem perder o cache de DNS:
unbound-control reload_keep_cache
# 2 - Reiniciar unbound completamente e rapido:
service unbound restart
# 3 - Parar totalmente, esperar e iniciar do zero:
service unbound stop
service unbound start
# Verificar status de execução:
service unbound status
Testar bloqueios do AnaBlock
A API do AnaBlock fornece um nome de teste: blocktest.anablock.net.br
Se este nome for resolvido, o AnaBlock não está em operação, mas se apresentar erro NXDOMAIN (domínio não existe), o bloqueio foi implementado com sucesso.
# Teste de bloqueio:
host blocktest.anablock.net.br 127.0.0.1
Using domain server:
Name: 127.0.0.1
Address: 127.0.0.1#53
Aliases:
Host blocktest.anablock.net.br not found: 3(NXDOMAIN)
Com isso temos nosso bloqueio judicial 100% em conformidade com o jurídico da empresa via AnaBlock e um DNS de altíssima velocidade com Unbound.
Um abraço a todos,
Patrick Brandão, patrickbrandao@gmail.com