O log que descreve você melhor do que o seu histórico de navegação
Antes que a sua máquina consiga enviar um único byte criptografado para um site, ela precisa perguntar a alguém onde esse site mora. Essa pergunta viaja em texto claro, até um resolvedor que você quase certamente não escolheu, e a resposta sobre quem a guarda decide o quanto da sua vida fica registrado. Um histórico de navegação é uma lista de páginas que você optou por manter. Um log de resolvedor é tudo: cada site, cada aplicativo verificando atualizações, cada serviço de nuvem com o qual o seu celular conversa enquanto você dorme, cada domínio em cada e-mail que você abriu, em ordem, com timestamps, esteja ou não um humano olhando para a tela.
Leia uma semana disso e você consegue reconstruir uma pessoa. O banco que ela usa, a companhia aérea que ela acabou de reservar, a farmácia, o aplicativo de namoro, o sistema de rastreamento de candidatos do recrutador, a hora em que ela acorda e a hora em que ela para. Nada disso exige quebrar nenhuma criptografia. Os nomes por si só já revelam isso, e os nomes são a única parte da transação que ainda é, na maioria das configurações, entregue a um terceiro por design.
Hoje esse terceiro é quem quer que a sua concessão de DHCP tenha apontado — o seu provedor de internet, o seu empregador, o café. Quem percebe isso costuma migrar para um resolvedor público, o que é uma melhoria real em integridade e um deslocamento lateral em privacidade: você não removeu o observador, só trocou de qual empresa é, trocando uma operadora de telecomunicações regulada por uma CDN próxima do mercado publicitário ou uma organização sem fins lucrativos cuja política pode mudar junto com o seu financiamento. As boas publicam políticas de retenção honestas, e algumas realmente as cumprem. Mas uma política é uma promessa sobre comportamento, e um arquivo de configuração é uma declaração sobre capacidade. Você não pode auditar uma promessa. Você pode auditar vinte linhas que você mesmo escreveu, em uma máquina que você aluga, em um país que você escolheu.
SP·02O encaminhamento move o log. A recursão o fragmenta.
Quase todo tutorial que diz "rode o seu próprio servidor DNS" termina construindo um encaminhador: um pequeno cache na sua rede que repassa para 1.1.1.1 ou 9.9.9.9 tudo o que não conhece. É uma coisa genuinamente útil — é rápido, são cinco linhas, e impede que a sua rede local fique te observando. Também deixa o log agregado exatamente onde estava. Todo nome que você consulta ainda chega a uma única empresa, agora convenientemente pré-rotulado com o endereço IP único do seu resolvedor, o que torna o fluxo mais fácil de atribuir, não mais difícil.
Um resolvedor recursivo faz o trabalho em vez de delegá-lo. Ao ser perguntado sobre news.example.io, ele consulta um servidor raiz para saber quem administra .io, depois consulta os servidores de .io para saber quem administra example.io, e só então pergunta diretamente a esse operador. Três conversas com três partes não relacionadas, nenhuma delas no ramo da agregação, e — esta é a parte que importa — nenhuma delas jamais vê o seu fluxo completo de consultas. Os operadores da raiz veem um gotejamento de solicitações de TLD. A Verisign vê que alguém no seu endereço tocou em algo sob .com. O servidor autoritativo de um domínio vê o tráfego que sempre iria ver, porque você está de qualquer forma prestes a se conectar a ele.
A minimização de QNAME aprimora isso consideravelmente, e o Unbound moderno faz isso por padrão. Em vez de enviar o nome completo para cada servidor da cadeia — o que os resolvedores fizeram por trinta anos —, ele envia a cada servidor só o rótulo de que precisa para responder: io. para a raiz, example.io. para os servidores de .io, e só então o news.example.io. completo para o operador que tem direito a ele. A hierarquia deixa de ser uma transmissão das suas intenções e passa a ser o que foi desenhada para ser: uma delegação.
A troca é real e vale a pena dizer isso sem rodeios. Uma consulta recursiva a frio leva várias idas e voltas onde um encaminhador leva uma só, então a primeira visita a um domínio desconhecido é mensuravelmente mais lenta. Você herda a responsabilidade por um cache que antes era problema de outra pessoa. E você deixa de se beneficiar de um cache compartilhado, aquecido por milhões de outras pessoas. Em troca, o registro completo, ordenado e com timestamp do que você consultou deixa de existir em qualquer lugar fora do seu próprio disco.
SP·03O que isso esconde, e o que claramente não esconde
O escopo honesto é mais estreito do que o marketing em torno do DNS privado sugere, e conhecer esses limites é o que evita que você tome uma decisão ruim apoiado só em uma boa sensação.
Isso remove uma coisa: o log agregado de nomes mantido por um único observador. Isso é uma coisa grande, porque o agregado é o que tem valor comercial e o que é solicitado em massa. Não é tudo.
Isso não esconde a conexão. Depois que a consulta é resolvida, o seu dispositivo ainda abre uma sessão com esse endereço, e qualquer pessoa observando o seu uplink vê o IP de destino. Para um site em infraestrutura dedicada, o IP é a identidade. Também não esconde o hostname no fio: a menos que as duas pontas suportem Encrypted Client Hello, o handshake TLS ainda carrega o nome do servidor em texto claro, que é a mesma informação que o seu resolvedor teria tido.
Isso não esconde as consultas do seu provedor de hospedagem. Esse é o ponto que as pessoas erram, então merece ser dito sem meias-palavras: o tráfego upstream do seu resolvedor — as perguntas que ele faz à raiz, ao TLD e aos servidores autoritativos — sai do VPS pela porta UDP 53, sem criptografia, e a rede em que o seu servidor está pode ler tudo isso. Não existe DoT até a raiz. Você não eliminou o observador, você o deslocou: de um provedor de internet de consumidor que vende dados e responde a intimações no seu próprio país, para uma rede de hospedagem em uma jurisdição que você escolheu deliberadamente, vendo um fluxo fragmentado graças à minimização de QNAME. Isso é uma melhoria genuína, e é um argumento sobre qual lei se aplica ao fio, não algo que um arquivo de configuração possa resolver.
E isso não te dá uma multidão. Um resolvedor usado por uma única residência atribui cada consulta nele a essa residência sem ambiguidade alguma. Contra um adversário passivo global, um resolvedor compartilhado e movimentado é genuinamente o melhor esconderijo. Contra o seu provedor de internet, o seu empregador, os corretores de dados que compram telemetria de resolvedores, e as solicitações em massa de rotina que realmente acontecem com pessoas comuns, o seu é melhor — desde que o último salto a partir dos seus dispositivos esteja dentro de um túnel. Rode isto junto com o seu próprio túnel WireGuard, não no lugar dele. Por conta própria, um resolvedor privado principalmente realoca os seus metadados. Atrás de um túnel, ele fecha o único canal que o túnel deixa aberto.
SP·04O erro que transforma o seu resolvedor na arma de outra pessoa
Existe exatamente uma forma de fazer isso terrivelmente errado, é fácil fazer por acidente, e as consequências caem sobre estranhos antes de caírem sobre você.
Um resolvedor que responde a qualquer um é um resolvedor aberto, e um resolvedor aberto é um amplificador. O DNS roda sobre UDP, os endereços de origem UDP são falsificados com trivial facilidade, e uma consulta pequena pode gerar uma resposta muitas vezes maior. Um atacante envia à sua máquina uma pergunta de 60 bytes com o endereço de uma vítima falsificado como remetente; a sua máquina, obediente, envia à vítima uma resposta dezenas de vezes maior. Faça isso a partir de alguns milhares de resolvedores abertos ao mesmo tempo e a vítima sai do ar, tendo recebido uma inundação que aparenta — com precisão, no nível do pacote — estar vindo de você. Você não é o alvo. Você é a arma, e o tráfego no relatório do incidente é seu.
O que vem depois não tem nada de glamouroso: relatórios de abuso de redes de que você nunca ouviu falar, um provedor que aplica um null route ao seu endereço para proteger o próprio trânsito, e uma conversa sobre a sua conta que você preferiria não ter. Você termina do lado de quem causa exatamente o tipo de evento descrito no nosso runbook da primeira hora de DDoS, e não existe versão dessa história em que o seu uptime sobrevive.
Dois travamentos independentes evitam isso, e você quer os dois, porque cada um cobre a falha do outro. O primeiro é o próprio access-control do Unbound, que deve refuse a internet inteira nas duas famílias de IP e só então allow explicitamente o loopback e a sub-rede do seu túnel — uma lista de bloqueio padrão, não uma lista de permissão com uma cauda permissiva. O segundo é onde o daemon escuta, ponto: vincule-o a 127.0.0.1 e ao endereço do túnel, nunca a 0.0.0.0, e mantenha a porta 53 fechada na interface pública, no firewall.
A armadilha é fazer só o primeiro. Uma regra de access-control não faz a porta desaparecer; uma consulta recusada ainda é um pacote recebido e um pacote enviado, o seu endereço ainda aparece nos escaneamentos que mapeiam resolvedores abertos, e uma edição futura na seção errada transforma uma recusa em uma resposta. Vincular e colocar no firewall tornam o erro estruturalmente impossível, em vez de a uma linha de configuração de distância. Se a máquina também roda contêineres, releia como o Docker publica portas contornando o seu firewall antes de presumir que a regra que você escreveu é a regra em vigor.
Os padrões do Unbound são sensatos. Não são privados.
O Unbound vem ajustado para correção e estabilidade, o que é o padrão certo para um software que é implantado principalmente por provedores de internet. Um punhado de configurações o transforma em algo construído para a pessoa que o está rodando. Nenhuma delas é exótica; elas só vêm desligadas, ou sem opinião definida, de fábrica.
Pare de responder perguntas sobre você mesmo. Por padrão, um resolvedor relata alegremente a sua versão de software e o seu hostname através da classe CHAOS — version.bind e hostname.bind — o que é reconhecimento de graça para qualquer um decidindo se a sua máquina vale a atenção. hide-identity e hide-version não custam nada e removem um fingerprint.
Falhe fechado, não aberto. A validação DNSSEC é a diferença entre um resolvedor que detecta uma resposta falsificada e um que a entrega. harden-dnssec-stripped se recusa a aceitar uma resposta não assinada para uma zona que deveria ser assinada, harden-glue e harden-below-nxdomain fecham duas vias clássicas de envenenamento de cache, e aggressive-nsec deixa o resolvedor responder nomes inexistentes direto de registros de negação em cache, em vez de perguntar de novo. use-caps-for-id adiciona capitalização aleatória como entropia extra contra spoofing às cegas — barato, e ocasionalmente incompatível com um servidor autoritativo malfeito, o que vale a pena saber antes de gastar uma tarde inteira em um domínio que não resolve.
Não registre nada. O Unbound não registra consultas a menos que seja pedido, mas as configurações que fariam isso estão a uma linha descomentada de distância, e alguns pacotes de distribuição vêm com um padrão mais tagarela. Defina verbosity: 0 e declare log-queries: no explicitamente, para que a intenção fique visível no arquivo em vez de inferida pela sua ausência. Depois lembre-se da parte que não é uma configuração: o próprio cache é um registro. O unbound-control dump_cache, em uma máquina rodando, imprime um histórico recente do que essa máquina consultou, e ele vive na memória de uma máquina que as mãos de outra pessoa podem alcançar. Ele expira por conta própria, o que é o motivo pelo qual vida curta de cache e privacidade estão em leve tensão, e é o motivo para não manter um resolvedor vivo por meses em um host em que você não confia nem um pouco.
Faça cache de propósito. Toda resposta servida do cache é uma observação que nunca acontece a montante, então um cache saudável é um recurso de privacidade, e não só de velocidade. O prefetch renova os registros populares antes de expirarem, então o caso comum para de tocar a rede por completo; o serve-expired te mantém online quando um servidor autoritativo fica brevemente inalcançável. Aumentar o cache-min-ttl reduz ainda mais a conversa a montante, mas isso sobrepõe escolhas deliberadas dos operadores de domínio — TTLs baixos são como CDNs e failover funcionam — então um piso de um ou dois minutos é sensato, e uma hora eventualmente vai te deixar preso em um endereço morto.
Duas portas de entrada: o túnel, ou o DNS-over-TLS
Os seus dispositivos precisam alcançar o resolvedor de algum jeito, e a escolha entre as duas opções sensatas é basicamente uma questão do que você está disposto a publicar.
O túnel é a melhor resposta para quase todo mundo. Se o seu laptop e o seu celular já mantêm uma sessão WireGuard com esse servidor, o resolvedor pode escutar no endereço do túnel e falar DNS comum na porta 53. O tráfego já está criptografado e já autenticado pelo túnel, então não há certificado para obter, nenhuma porta nova aberta para a internet, nenhuma pilha TLS exposta a estranhos, e — a parte subestimada — nenhum hostname em lugar nenhum. O guia de WireGuard deste site deixa os clientes apontando para DNS = 9.9.9.9 justamente porque não havia nada melhor para colocar ali ainda. Isto é o que vai nessa linha em vez disso: o endereço de túnel do seu próprio servidor.
O DNS-over-TLS é para o dispositivo que não consegue manter um túnel. O campo de DNS Privado do Android é o caso mais forte para isso — ele se aplica a todo o sistema, sobrevive a reinicializações, e cobre aplicativos que você não conseguiria alcançar de outra forma. O custo é um hostname com um certificado válido, e um certificado significa uma entrada pública e permanente nos logs de Certificate Transparency vinculando esse nome ao momento em que você o criou. O DNS passivo então vai ligar o nome ao endereço do servidor. Se o objetivo do exercício era manter o seu nome fora da infraestrutura, use um hostname que não leve a nada perto de você e registre-o com o cuidado descrito em registrar um domínio de forma anônima — não um subdomínio do domínio que você usa para tudo o mais, o que ligaria os dois permanentemente.
Existe um segundo custo, mais sutil. Um endpoint de DoT que celulares em roaming conseguem alcançar não pode ser restringido por endereço de origem, então ele é, por definição, um resolvedor que estranhos podem usar se descobrirem o nome. Ele não é um amplificador — TLS sobre TCP exige um handshake completo, então a origem não pode ser falsificada e não há nada para refletir — mas é capacidade que você está cedendo de graça, e um serviço que vale a pena escanear em busca. Mantenha os limites de taxa por IP ativados, escolha um hostname que ninguém vai adivinhar, e trate isso como uma exceção deliberada para um ou dois dispositivos, não como a porta padrão.
O DNS-over-HTTPS é uma terceira opção, e normalmente a errada aqui. Ele precisa de um servidor web na frente do resolvedor, o que é mais peças em movimento e uma superfície de ataque maior, pelo único benefício de ser indistinguível do tráfego web comum. Esse benefício é decisivo se você está contornando uma rede que bloqueia o DoT, e irrelevante se não está.
SP·07Bloqueio é um produto diferente; decida antes de acoplá-lo
Mais cedo ou mais tarde alguém sugere adicionar listas de bloqueio, e a proposta é genuinamente atraente: filtrar no resolvedor cobre todo dispositivo no túnel, incluindo a smart TV e os aplicativos de celular onde nenhuma extensão consegue chegar. No celular, em particular, é o único lugar prático para intervir. É também o recurso mais capaz de fazer você desconfiar silenciosamente da sua própria infraestrutura, e vale entender por que antes de acontecer, não durante.
O primeiro custo é que as falhas não se parecem com falhas. Um resolvedor quebrado se anuncia; um domínio bloqueado se apresenta como um botão de checkout que não faz nada, um aplicativo travado em uma roda giratória, um e-mail que nunca chega. O sintoma aparece semanas depois que você instalou a lista, em um dispositivo que você nem estava considerando, e nada liga isso a uma decisão de DNS que você tomou em outro mês. Toda lista de bloqueio que você instala é uma política escrita por um estranho e aplicada silenciosamente sobre a sua residência. Se você adicionar uma, anote que fez isso, mantenha-a pequena e confiável, e mantenha uma forma de desligá-la com um único comando — o primeiro passo de depuração para qualquer coisa inexplicada na sua rede passa a ser "contornar o filtro e tentar de novo", e esse passo precisa ser barato.
O segundo custo é que isso não faz o que as pessoas esperam. Um aplicativo com um endereço de resolvedor fixo no código, ou com o próprio cliente DoH embutido, nunca pergunta nada ao seu resolvedor; ele abre uma conexão para um IP fixo e pronto. Navegadores cada vez mais resolvem pelo próprio DoH, a menos que configurados para o contrário. O bloqueio de DNS é uma camada de higiene que remove bastante ruído de rastreamento e publicidade de baixo esforço, e não é um controle de segurança, porque qualquer coisa adversária contorna isso por design.
Se você quiser mesmo assim, prefira uma pequena zona local no Unbound a um segundo daemon — local-zone: "tracker.example." always_nxdomain não precisa de software extra, nenhuma UI web em uma porta que você então tem que defender, e nenhum serviço novo que possa cair e levar a sua resolução de nomes junto. Mantenha a descrição de trabalho da máquina em uma linha: ela resolve nomes. Cada responsabilidade adicional que você dá a ela é mais uma forma de tudo parar de funcionar de uma vez.
Um resolvedor que você roda é uma dependência que você possui
Quando um site que você hospeda cai, algumas pessoas não conseguem ler algo. Quando o seu resolvedor cai, nada funciona — nem o navegador, nem o e-mail, nem o gerenciador de pacotes, nem o aplicativo que ia te avisar que o servidor está fora do ar. É o serviço mais estrutural que você pode colocar em uma máquina barata, e ele falha de formas que não parecem DNS.
Vale a pena conhecer com antecedência os modos de falha realistas, porque cada um tem uma assinatura diferente. O VPS reinicia e o Unbound nunca foi habilitado na inicialização, então tudo funciona até o primeiro reinício não planejado. Uma lista de bloqueio grande empurra o cache para o swap em uma instância de 1 GB e o OOM killer escolhe o resolvedor. Uma zona em algum lugar quebra as próprias assinaturas DNSSEC, e o seu resolvedor corretamente configurado recusa a resposta enquanto todo mundo em um resolvedor que não valida continua navegando — a sua máquina está certa e o site ainda parece quebrado para você, o que são cinco minutos confusos se você esqueceu que valida. Ou o túnel cai, e como DNS = 10.66.0.1 só existe dentro do túnel, o dispositivo não tem resolvedor nenhum e informa que está offline.
As mitigações são misericordiosamente baratas. Habilite o serviço na inicialização e realmente teste isso com um reinício, em vez de presumir. Dê aos clientes um resolvedor secundário para que um túnel morto degrade em vez de parar — um resolvedor público nesse lugar é um compromisso de privacidade pequeno e explícito que só se aplica enquanto o seu está inalcançável, e geralmente é a troca certa. Mantenha o serve-expired ativado para que uma breve queda upstream não se torne a sua queda. Verifique o resolvedor a partir de outro lugar, não da própria máquina, que é a única forma de notar a diferença entre "fora do ar" e "inalcançável".
E guarde uma cópia da configuração. A coisa toda são algumas dezenas de linhas que levaram uma tarde para você acertar e que você não vai lembrar dentro de um ano; ela pertence aos seus backups criptografados fora do site, junto com as chaves do WireGuard, para que reconstruir seja vinte minutos, e não uma segunda tarde. Esse é o resumo honesto de todo esse exercício: uma máquina pequena fazendo um único trabalho, pelo preço do plano mais barato da lista, substituindo uma promessa sobre retenção por um arranjo em que o registro simplesmente nunca é criado.
SP·09Passo a passo
-
01
Comece a partir de uma máquina já protegida
Um resolvedor é um serviço pequeno e discreto, o que torna tentador instalá-lo em qualquer máquina que esteja disponível. Não faça isso — essa máquina vai ver cada nome que cada dispositivo no seu túnel consultar, então ela merece o mesmo tratamento que qualquer outra coisa que guarda segredos. Implante o plano mais barato que você quiser; 1 GB de RAM é mais do que suficiente para uma residência, já que os tamanhos de cache abaixo são medidos em dezenas de megabytes. Passe pela primeira hora após a implantação antes de qualquer outra coisa: um usuário nomeado, SSH só por chave, bloqueio padrão nas duas famílias de IP, atualizações de segurança automáticas.
Depois instale o Unbound. O pacote da distribuição já vem com as dicas de raiz e a âncora de confiança raiz do DNSSEC, e configura a renovação automática dessa âncora, o que é um dos poucos casos em que a versão empacotada realmente te salva de uma classe inteira de problemas futuros.
sudo apt update && sudo apt install -y unbound dnsutils unbound -V | head -n 3 # the packaged trust anchor the resolver will validate against sudo ls -l /var/lib/unbound/root.key
Se o
root.keyestiver faltando, o seu pacote não executou ounbound-anchor, e a validação vai falhar fechada em tudo. Gere-o uma vez comsudo -u unbound unbound-anchor -a /var/lib/unbound/root.keyantes de continuar. -
02
Retome a porta 53 do systemd-resolved
Na maioria das distribuições atuais, alguma coisa já é dona da porta 53: o
systemd-resolvedroda um stub listener em127.0.0.53, e o/etc/resolv.confé um symlink apontando para ele. O Unbound vai se recusar a iniciar, ou vai iniciar e não vincular nada útil, até que isso seja resolvido. Olhe antes de editar.ss -ulpn 'sport = :53' ls -l /etc/resolv.conf
Leia este parágrafo antes de rodar o próximo bloco: entre desativar o stub e iniciar o Unbound, esta máquina não tem DNS funcional nenhum. Termine os passos 3 e 4 na mesma sessão, e não dispare uma operação
aptem outra janela antes disso — ela vai travar em uma consulta de nome e você vai diagnosticar errado, achando que é o resolvedor que você ainda não iniciou.# stop resolved from holding the port (appends inside the [Resolve] section) printf 'DNSStubListener=no\n' | sudo tee -a /etc/systemd/resolved.conf sudo systemctl restart systemd-resolved # point the host at the resolver it is about to run sudo rm -f /etc/resolv.conf printf 'nameserver 127.0.0.1\noptions edns0 trust-ad\n' | sudo tee /etc/resolv.conf # the port should now be free ss -ulpn 'sport = :53'
-
03
Escreva uma configuração que faz recursão e esquece
Deixe a configuração empacotada em paz e adicione o seu próprio arquivo no diretório drop-in, para que uma atualização de pacote nunca revogue silenciosamente as suas decisões. Cada linha abaixo é sobre recusar estranhos, fazer recursão a partir da raiz, ou não guardar registros. Substitua
10.66.0.1e10.66.0.0/24pelo endereço e sub-rede do túnel do seu próprio servidor WireGuard, se forem diferentes.sudo tee /etc/unbound/unbound.conf.d/private-resolver.conf > /dev/null <<'EOF' server: # listen for the host itself and for the tunnel — never on 0.0.0.0 interface: 127.0.0.1 interface: 10.66.0.1 port: 53 # default-deny: refuse the internet, then allow what you trust access-control: 0.0.0.0/0 refuse access-control: ::/0 refuse access-control: 127.0.0.0/8 allow access-control: 10.66.0.0/24 allow # recurse from the root and send each server only the label it needs qname-minimisation: yes harden-dnssec-stripped: yes harden-below-nxdomain: yes harden-glue: yes aggressive-nsec: yes use-caps-for-id: yes # answer nothing about the software or the host hide-identity: yes hide-version: yes # keep no query log, and say little to the journal verbosity: 0 log-queries: no log-replies: no # a warm cache is an upstream observation that never happens cache-min-ttl: 120 cache-max-ttl: 86400 prefetch: yes prefetch-key: yes serve-expired: yes # belt and braces if a rule above is ever loosened ratelimit: 1000 ip-ratelimit: 100 # sizing for a small instance num-threads: 2 so-reuseport: yes msg-cache-size: 32m rrset-cache-size: 64m EOFNote o que não está no arquivo: não existe nenhum
forward-zone. A ausência dele é o que faz disto um resolvedor recursivo, em vez de um cache na frente do de outra pessoa. Se depois você colar um trecho de um tutorial que adiciona um, você desfez silenciosamente o ponto inteiro do exercício. -
04
Inicie, depois prove que o DNSSEC realmente valida
Verifique a sintaxe antes de reiniciar qualquer coisa — em uma máquina cujo próprio
resolv.confagora aponta para o Unbound, um erro de configuração significa nenhuma resolução de nomes enquanto você depura o problema.sudo unbound-checkconf sudo systemctl enable --now unbound systemctl --no-pager status unbound | head -n 5
Agora verifique os dois comportamentos que importam, porque um resolvedor que responde não é o mesmo que um resolvedor que valida. Um nome assinado precisa voltar com a flag
ad— dados autenticados — e um nome com assinaturas deliberadamente quebradas precisa falhar fechado comSERVFAILem vez de resolver.# should show: flags: qr rd ra ad dig @127.0.0.1 example.com +dnssec | grep -E '^;; flags' # should show: status: SERVFAIL (not NOERROR, not an address) dig @127.0.0.1 dnssec-failed.org | grep -E '^;; ->>HEADER' # and a normal name should simply work dig @127.0.0.1 +short cloudflare.com
Se a zona quebrada resolver para um endereço, a validação não está rodando: verifique se o
/var/lib/unbound/root.keyexiste e é legível pelo usuáriounbound. Se tudo forSERVFAIL, a causa costumeira é um relógio seriamente errado — assinaturas têm janelas de validade, e uma máquina várias horas fora de sincronia rejeita a internet inteira. -
05
Feche a porta pública, abra só o túnel
A configuração já recusa estranhos. Este passo garante que não haja nada para um estranho alcançar, para começo de conversa — o segundo dos dois travamentos, e o que sobrevive a uma futura edição do primeiro.
# DNS is reachable from the tunnel interface only sudo ufw allow in on wg0 to any port 53 proto udp sudo ufw allow in on wg0 to any port 53 proto tcp sudo ufw status verbose
Depois verifique isso da única forma que conta, a partir de uma máquina diferente. Testar a partir do próprio servidor não prova absolutamente nada — o loopback é permitido de propósito. Rode isto a partir do seu laptop com o túnel desligado, ou a partir de qualquer outro host que você tenha.
# must time out. an answer here means you are running an open resolver. dig @SERVER_PUBLIC_IP example.com +time=3 +tries=1 # same question over IPv6, which is the half people forget dig -6 @SERVER_IPV6 example.com +time=3 +tries=1
Se qualquer um dos dois retornar uma resposta, pare e corrija agora, em vez de depois do relatório de abuso. As causas costumeiras são um
interface: 0.0.0.0deixado em um arquivo de configuração empacotado, uma regra de firewall permitindo a porta 53 globalmente de um experimento anterior, ou o Docker publicando uma porta de contêiner que contorna oufwpor completo. -
06
Aponte os seus dispositivos para ele
Do lado do cliente, isso é uma mudança de uma linha só. Na configuração do cliente WireGuard, a linha
DNSpassa a ser o endereço de túnel do seu servidor, em vez de um resolvedor público — esta é a edição que aposenta oDNS = 9.9.9.9do guia de WireGuard.[Interface] PrivateKey = <paste client.key> Address = 10.66.0.2/32, fd86:ea04:1115::2/128 DNS = 10.66.0.1 [Peer] PublicKey = <paste server.pub> Endpoint = YOUR_SERVER_IP:51820 AllowedIPs = 0.0.0.0/0, ::/0 PersistentKeepalive = 25
Suba o túnel e confirme duas coisas separadas a partir do cliente: que as respostas estão vindo do seu resolvedor, e que a recursão está de fato saindo pelo seu VPS, e não por outro lugar. A segunda verificação é a útil —
whoami.akamai.netretorna o endereço de qualquer resolvedor que tenha perguntado, então deveria imprimir o IP público do seu servidor e nada mais.# answers should come from the tunnel address dig example.com | grep -E 'SERVER:' # should print your VPS public IP — this is the leak test dig +short whoami.akamai.net # and the ad flag should still be there, end to end dig example.com +dnssec | grep -E '^;; flags'
-
07
Adicione DNS-over-TLS só para um dispositivo que não consegue manter o túnel
Pule este passo, a menos que você tenha um dispositivo específico — geralmente um celular Android, através da sua configuração de DNS Privado em todo o sistema — que você queira cobrir sem um túnel permanente. Isso exige um hostname e um certificado, e esse hostname se torna um registro público permanente nos logs de Certificate Transparency, então escolha um que não leve a nada perto das suas outras identidades.
sudo apt install -y certbot sudo ufw allow 80/tcp comment 'certbot, temporarily' sudo certbot certonly --standalone -d dns.example.net sudo ufw delete allow 80/tcp # unbound must be able to read the key sudo usermod -a -G ssl-cert unbound 2>/dev/null || true sudo chgrp -R ssl-cert /etc/letsencrypt/live /etc/letsencrypt/archive sudo chmod -R g+rX /etc/letsencrypt/live /etc/letsencrypt/archive
Adicione o listener TLS como o seu próprio arquivo drop-in, para que você possa apagá-lo em um único movimento se mudar de ideia.
# NOTE: drop-in files are read in alphabetical order and the last # access-control line for a given prefix wins — so this file must # sort AFTER private-resolver.conf, or its refuse rule overrides # the allow below and every DoT client gets REFUSED. sudo tee /etc/unbound/unbound.conf.d/zz-dot.conf > /dev/null <<'EOF' server: interface: 0.0.0.0@853 interface: ::0@853 tls-service-key: "/etc/letsencrypt/live/dns.example.net/privkey.pem" tls-service-pem: "/etc/letsencrypt/live/dns.example.net/fullchain.pem" # roaming clients have no fixed address, so this endpoint must accept any. # safe only because port 53 stays bound to loopback + wg0 and blocked at # the firewall — TLS over TCP cannot be spoofed, so it cannot be reflected. access-control: 0.0.0.0/0 allow access-control: ::/0 allow EOF sudo ufw allow 853/tcp sudo unbound-checkconf && sudo systemctl restart unboundTeste de fora do túnel antes de confiar nisso, depois coloque o hostname no campo de DNS Privado do celular. A renovação é a parte que quebra silenciosamente três meses depois — o certbot substitui o certificado, mas o Unbound mantém o antigo na memória, então adicione um deploy hook que o recarregue.
kdig -d @dns.example.net +tls-ca +tls-host=dns.example.net example.com echo 'systemctl reload unbound' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/unbound.sh sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/unbound.sh


