Rodando servidor proxy-cache DNS com Unbound
Autor: Patrick Brandão
Motivação: ao rodar qualquer software no Linux, a resolução de DNS e feita pela libresolv, que faz a leitura do /etc/host.conf e /etc/resolv.conf para obter o IP do servidor DNS.
Assim, a resolução de nomes requer envio de pacotes para fora do host e aguarda pela resposta, que pode demorar (latência alta) ou não ser respondida por problemas na rede entre o host e o servidor DNS (remoto)
A libresolv não possui suporte a cache, ou seja, se você precisar consultar um domínio (www.google.com) dezenas de vezes em um segundo, todas as vezes ela terá que enviar a pergunta ao servidor DNS para obter a mesma resposta.
Rodando um servidor proxy-cache DNS no host linux você garante que a libresolv envie os pedidos para um software rodando no mesmo host mas que ficará por conta de consultar 1 ou mais servidores, e salvando os resultados obtidos em cache, economizando banda e tempo nas próximas requisições aos mesmos nomes.
O resultado dessa implementação é uma maior velocidade no inicio das conexões do servidor.
OBS:
Você não está criando um servidor recursivo, pare resoluções de nomes para sua rede!
Mas ao final Rudimar Remontti vai explicar como tornar ele recursivo.
Distribuição utilizada:
Debian 11 (Bullseye) 64 bits instalação mínima
Instalando Unbound
# apt update; apt upgrade # apt install unbound
Configurando
A configuração abaixo visa consumir recursos mínimos e atender somente os softwares do próprio host.
# cat > /etc/unbound/unbound.conf.d/root-auto-trust-anchor-file.conf << EOF server: auto-trust-anchor-file: "/var/lib/unbound/root.key" verbosity: 1 statistics-interval: 20 extended-statistics: yes num-threads: 2 # Caso seja necessário fixar o IP de origem: #outgoing-interface: x.x.x.x # Abrir a porta apenas nos endereços loopback (!!segurança!!) interface: 127.0.0.1 interface: ::1 # Permitir todos os IPs pois abrimos a porta apenas para a loopback access-control: 127.0.0.1/8 allow access-control: ::1 allow outgoing-range: 512 num-queries-per-thread: 128 msg-cache-size: 2m rrset-cache-size: 1m msg-cache-slabs: 4 rrset-cache-slabs: 4 cache-max-ttl: 1200 infra-host-ttl: 60 infra-lame-ttl: 60 infra-cache-numhosts: 128 infra-cache-lame-size: 2k do-ip4: yes do-ip6: yes do-udp: yes do-tcp: yes do-daemonize: yes username: "unbound" directory: "/etc/unbound" logfile: "/var/log/unbound.log" use-syslog: yes pidfile: "/run/unbound.pid" identity: "Unbound-LocalCache" version: "1.0" hide-identity: yes hide-version: yes harden-glue: yes do-not-query-address: 127.0.0.1/8 do-not-query-localhost: yes module-config: "iterator" #zone localhost local-zone: "localhost." static local-data: "localhost. 10800 IN NS localhost." local-data: "localhost. 10800 IN SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" local-data: "localhost. 10800 IN A 127.0.0.1" local-zone: "127.in-addr.arpa." static local-data: "127.in-addr.arpa. 10800 IN NS localhost." local-data: "127.in-addr.arpa. 10800 IN SOA localhost. nobody.invalid. 2 3600 1200 604800 10800" local-data: "1.0.0.127.in-addr.arpa. 10800 IN PTR localhost." remote-control: control-enable: yes control-interface: 127.0.0.1 control-port: 8953 control-use-cert: "no" # Operar 100% em modo forward, informe o ip dos servidores DNSs reais: forward-zone: name: "." forward-addr: 8.8.8.8 forward-addr: 8.8.4.4 # Encaminhar dominio especifico para servidor DNS especifico: forward-zone: name: "slack.com" forward-addr: 1.1.1.1 forward-addr: 1.0.0.1 EOF
Acima criamos um forward do domínio slack.com indo para um DNS diferente (1.1.1.1 e 1.0.0.1) do padrão 8.8.8.8 e 8.8.4.4
Reinicie o serviço para carregar as novas configurações
# systemctl restart unbound
Instale o pacote dnsutils para ter ferramentas de testes
# apt install dnsutils
Testando IPv4
# host google.com 127.0.0.1
Using domain server: Name: 127.0.0.1 Address: 127.0.0.1#53 Aliases: google.com has address 142.250.218.78 google.com has IPv6 address 2800:3f0:4001:81d::200e google.com mail is handled by 10 smtp.google.com.
# dig ANY google.com @127.0.0.1
; <<>> DiG 9.16.27-Debian <<>> ANY google.com @127.0.0.1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 893 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;google.com. IN ANY ;; ANSWER SECTION: google.com. 129 IN A 142.250.218.78 google.com. 129 IN AAAA 2800:3f0:4001:81d::200e google.com. 51 IN MX 10 smtp.google.com. ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Wed Jun 01 15:59:35 -03 2022 ;; MSG SIZE rcvd: 104
Testando IPv6
# host google.com ::1
Using domain server: Name: ::1 Address: ::1#53 Aliases: google.com has address 142.250.218.78 google.com has IPv6 address 2800:3f0:4001:81d::200e google.com mail is handled by 10 smtp.google.com.
# dig ANY google.com @::1
; <<>> DiG 9.16.27-Debian <<>> ANY google.com @::1 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56485 ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ;; QUESTION SECTION: ;google.com. IN ANY ;; ANSWER SECTION: google.com. 106 IN A 142.250.218.78 google.com. 281 IN AAAA 2800:3f0:4001:81d::200e google.com. 281 IN MX 10 smtp.google.com. ;; Query time: 0 msec ;; SERVER: ::1#53(::1) ;; WHEN: Wed Jun 01 16:03:30 -03 2022 ;; MSG SIZE rcvd: 104
Configurando o Linux para usar o servidor DNS na loopback como servidor DNS
# echo "nameserver 127.0.0.1" > /etc/resolv.conf # echo "nameserver ::1 " >> /etc/resolv.conf
Tornando recursivo
Contribuição extra por: Rudimar Remontti
Caso deseje tornar recursivo para os demais hosts da sua rede este servidor, primeira coisa que você deve ter em mente que se este servidor conter IPs públicos o mesmo será responsivo para todo o planeta terra e alguns "aliGenigenas". Então o mínimo que você deve ter é um firewall, protegendo a porta 53 tcp/udp para responder apenas para sua rede.
# vim /etc/unbound/unbound.conf.d/root-auto-trust-anchor-file.conf
Abaixo de:
# abrir a porta apenas nos enderecos loopback (seguranca) interface: 127.0.0.1 interface: ::1
Adicione
# abrir a porta para os ips de interface (risco) interface: 200.200.200.200 interface: 2000:bebe:cafe::f07e
Abaixo de:
# Permitir todos os IPs pois abrimos a porta apenas para a loopback access-control: 127.0.0.1/8 allow access-control: ::1 allow
Adicione os prefixos da sua rede
access-control: 192.168.0.0/16 allow access-control: 172.16.0.0/12 allow access-control: 100.64.0.0/10 allow access-control: 10.0.0.0/8 allow access-control: 200.200.0.0/22 allow access-control: 2001:db8::/32 allow
Desta forma abrindo conexão para os IPs da interface "200.200.200.200" e "2000:bebe:cafe::f07e"
Reinicie o serviço para carregar as alterações
# systemctl restart unbound
Pode consultar se as porta estão sendo ouvidas:
# ss -putan | grep LISTEN | grep :53
tcp LISTEN 0 256 200.200.200.200:53 0.0.0.0:* users:(("unbound",pid=6079,fd=16)) tcp LISTEN 0 256 127.0.0.1:53 0.0.0.0:* users:(("unbound",pid=6079,fd=12)) tcp LISTEN 0 256 200.200.200.200:53 0.0.0.0:* users:(("unbound",pid=6079,fd=8)) tcp LISTEN 0 256 127.0.0.1:53 0.0.0.0:* users:(("unbound",pid=6079,fd=4)) tcp LISTEN 0 256 [::1]:53 [::]:* users:(("unbound",pid=6079,fd=6)) tcp LISTEN 0 256 [2000:bebe:cafe::f07e]:53 [::]:* users:(("unbound",pid=6079,fd=10)) tcp LISTEN 0 256 [::1]:53 [::]:* users:(("unbound",pid=6079,fd=14)) tcp LISTEN 0 256 [2000:bebe:cafe::f07e]:53 [::]:* users:(("unbound",pid=6079,fd=18))
Firewall
Porém mesmo que você tenha setados seus prefixos em access-control a porta 53 estará respondendo para todo o mundo. Para fechar elas use o nfttables que por padrão já vem no Debian 11 no lugar do iptables. Você pode instalar o mesmo com apt se necessário.
Edite o arquivo do nftables
# vim /etc/nftables.conf
Ajuste para ficar assim e em elements insira todos seus prefixos autorizados.
#!/usr/sbin/nft -f flush ruleset table inet filter { set acesso-dns4 { flags interval type ipv4_addr elements = { 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 100.64.0.0/10, 200.200.200.0/22 } } set acesso-dns6 { flags interval type ipv6_addr elements = { ::1, 2001:db8::/32 } } chain input { type filter hook input priority 0; # Permite Acesso DNS na porta 53 ip saddr @acesso-dns4 udp dport 53 counter accept ip saddr @acesso-dns4 tcp dport 53 counter accept ip6 saddr @acesso-dns6 udp dport 53 counter accept ip6 saddr @acesso-dns6 tcp dport 53 counter accept udp dport 53 counter drop tcp dport 53 counter drop type filter hook input priority 0; } chain forward { type filter hook forward priority 0; } chain output { type filter hook output priority 0; } }
Habilite o mesmo para iniciar com o boot e reinicie.
# systemctl enable nftables # systemctl restart nftables
Consulte se seu firewall foi carregado com o comando:
# nft list ruleset
Retorno:
table inet filter { set acesso-dns4 { type ipv4_addr flags interval elements = { 10.0.0.0/8, 100.64.0.0/10, 127.0.0.1, 172.16.0.0/12, 192.168.0.0/16, 200.200.200.0/22 } } set acesso-dns6 { type ipv6_addr flags interval elements = { ::1, 2001:db8::/32 } } chain input { type filter hook input priority filter; policy accept; ip saddr @acesso-dns4 udp dport 53 counter packets 0 bytes 0 accept ip saddr @acesso-dns4 tcp dport 53 counter packets 0 bytes 0 accept ip6 saddr @acesso-dns6 udp dport 53 counter packets 0 bytes 0 accept ip6 saddr @acesso-dns6 tcp dport 53 counter packets 0 bytes 0 accept udp dport 53 counter packets 0 bytes 0 drop tcp dport 53 counter packets 0 bytes 0 drop } chain forward { type filter hook forward priority filter; policy accept; } chain output { type filter hook output priority filter; policy accept; } }
Pronto espero que tenha gostado! Agradeço ao meu parceiro Patrick!
Se quiser fazer uma doação para o café ficarei muito feliz pelo seu reconhecimento!
Se não puder doar pode deixar seu agradecimento nos comentário também ficarei feliz em saber que ajudei. Se tiver qualquer pergunta deixe-a também. Se preferir entrar em Contato clique aqui.
Abraço!
Como faria para bloquear sites no unbound?
material show de bola.
Hola .. Cuando coloco
# abrir a porta para os ips de interface (risco)
interface: 200.200.200.200
interface: 2000:bebe:cafe::f07e
Tengo error al iniciar unbound, que pidria ser
creio que vc não tenha o endereço IP 200.200.200.200 configurado em nenhuma interface de rede
Pq quando dou o comando nft list ruleset no debian 12 ele retorna “comando não encontrado”, e ja no ubuntu 22.04 ele retorna as regras confome no tutorial
tenta “/sbin/nft list rulest” se der certo, precisa corrigir o PATH do seu .bash
systemctl restart unbound
Job for unbound.service failed because the control process exited with error code.
See “systemctl status unbound.service” and “journalctl -xeu unbound.service” for details.
entra no arquivo .conf do unbount e apaga o os linha repetidas no começo
eu ja fiz isso e não resolveu.
alterar no cabeçalho das configurações unbound os nome repetidos tava com es
se erro tambem
olá, em /etc/unbound/ na .conf não tem absolutamente nada repetido, porem não da restart, poderia ser mais claro, obrigado.
creio que deve haver alguma linha que esteja causando o erro , com o comando jounalctl -200 vc pode ver as ultimas 200 linhas e checar se informa algum erro
Fiquei em duvida em relação ao Tamanho do cache, pelo que vi aqui no blog, ficou no padrão
msg-cache-size: 2m
rrset-cache-size: 1m
Mas não seria interessante deixar uma quantidade maior de armazenamento ? 200mb ou 1GB ?
Se alguém puder comentar sobre agradeço.
coloca 100m em cada mais que suficiente
A adição de um DNS autoritativo melhora a latência ou a velocidade da consulta?
Como habilitar o DNSSEC?
Já fiz de tudo e não funciona.
Olá Anderson.
como proxy-cache a performance é melhor, pois alem de fazer cache local vc se aproveita do cache já alimentado nos servidores de DNS apontados no forward. Se você optar pelos hints (servidores raiz) a latência irá aumentar um pouco pois para cada nome a ser resolvido seu DNS local terá que consultar toda a árvore de DNS mundial, com acessos internacionais com latencia acima de 120ms.
Nesse link há explicações desenhadas:
http://manual.slackmini.com.br/#dns-client
Obrigado pela explicação e parabéns pelo tutorial. Já até coloquei em produção.
Patrick,
Entendi a questão do forward e tal.
Qual seria a vantagem em usar o recursivo pelo hints (servidores raiz) ? Ou não tem nenhuma vantagem?
Parabéns pelo material.
pode deixar pelo servidores raiz em vez do forward-zone?
E qual e a vantagem com e sem forward-zone?
Boa pergunta, tbm fiquei curioso
Seria esta resposta, para sua pergunta!
como proxy-cache a performance é melhor, pois alem de fazer cache local vc se aproveita do cache já alimentado nos servidores de DNS apontados no forward. Se você optar pelos hints (servidores raiz) a latência irá aumentar um pouco pois para cada nome a ser resolvido seu DNS local terá que consultar toda a árvore de DNS mundial, com acessos internacionais com latencia acima de 120ms.
Nesse link há explicações desenhadas:
http://manual.slackmini.com.br/#dns-client