SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor

Corrigir DNS no WireGuard: 3 falhas comuns

Veja por que o DNS falha no WireGuard: nomes sem resolução, consultas vazando para o roteador local ou configuração substituída após ativar a interface.

Por que o DNS falha assim que o túnel WireGuard é ativado

O DNS sobre WireGuard falha de três formas, e cada uma tem a sua própria correção. Nada é resolvido, os nomes são resolvidos mas as consultas saem da máquina sem passar pelo túnel, ou o próprio gestor do resolvedor do cliente substitui a configuração segundos depois de a interface arrancar. O túnel quase nunca é o problema. O problema está na linha que indica ao cliente qual resolvedor deve consultar e no encaminhamento que determina como os pacotes chegam a esse resolvedor.

O WireGuard transporta pacotes IP e não tem conhecimento de DNS (domain name system, o serviço que converte nomes como example.com em endereços IP). A linha DNS = num bloco de cliente [Interface] não é uma definição do WireGuard. Ela é lida por wg-quick, o wrapper de shell que ativa a interface, e wg-quick altera depois a configuração do resolvedor do cliente enquanto o túnel está ativo e repõe a configuração em wg-quick down. Por isso, todos os problemas abaixo são problemas de encaminhamento ou de wg-quick, nunca problemas de criptografia. Se o túnel ainda não estiver criado, comece por uma VPN WireGuard autoalojada no seu próprio VPS e volte depois a esta página.

Confirme que o túnel está saudável antes de mexer no DNS.

sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1

wg show deve apresentar o peer com um latest handshake recente, e ambos os pings devem responder. Se ping 1.1.1.1 exceder o tempo limite, é provável que tenha um problema de encaminhamento ou NAT (network address translation), e não um problema de DNS. Nenhuma alteração na configuração do resolvedor resolverá a situação. Uma firewall que descarte ICMP produz o mesmo timeout, por isso confirme com curl -sI https://1.1.1.1 antes de alterar as regras de encaminhamento. Se os pings responderem mas o débito cair assim que começar tráfego real, trata-se de um problema separado, e o WireGuard lento quase sempre está relacionado com o MTU e não com algo abordado nesta página. Todos os exemplos aqui usam 10.8.0.0/24 como a sub-rede do túnel e 10.8.0.1 como o endereço do servidor no túnel. Substitua-os pelos seus próprios valores.

Falha 1: nada é resolvido porque o resolver nunca responde

O sintoma é claro. ping 1.1.1.1 funciona, e curl https://example.com devolve isto:

curl: (6) Could not resolve host: example.com

Consulte diretamente o resolver do túnel a partir do cliente. dig faz parte do pacote dnsutils no Ubuntu e no Debian.

dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.com

O primeiro comando devolve um endereço, o que prova que os pacotes chegam à Internet através do túnel. O segundo não devolve nada e apresenta ;; communication timed out; no servers could be reached. O diagnóstico é esse: o cliente está configurado para usar 10.8.0.1, e 10.8.0.1 não responde na porta UDP 53.

Há duas causas possíveis. Ou não existe nenhum resolver em execução no servidor, ou a firewall do servidor descarta a consulta antes de ela chegar. Verifique ambas no servidor.

sudo ss -ulnp | grep ':53'
sudo nft list ruleset

Um resolver em execução e corretamente associado apresenta uma linha com 10.8.0.1:53 ou 0.0.0.0:53. No Ubuntu, a surpresa costuma ser 127.0.0.53:53: trata-se do listener stub do systemd-resolved, que se associa a um endereço de loopback e fica deliberadamente inacessível a partir de outras máquinas. Configurar um cliente VPN para usar um servidor cujo único resolver é esse stub produz exatamente este timeout.

A correção consiste num resolver que escute no endereço do túnel e numa regra de firewall que permita o acesso dos peers.

sudo apt update && sudo apt install -y unbound
printf 'server:\n  interface: 10.8.0.1\n  access-control: 10.8.0.0/24 allow\n' \
  | sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'

Depois, abra a porta apenas para o tráfego do túnel. Com nftables, adicione estas duas linhas à chain input em /etc/nftables.conf e recarregue com sudo systemctl reload nftables.

udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" accept

Com ufw, sudo ufw allow in on wg0 to any port 53 faz o mesmo. Nunca abra a porta 53 à Internet pública. Um resolver recursivo aberto é encontrado por scanners em poucos dias e usado para amplificar ataques de negação de serviço. O seu fornecedor vai detetar esse tráfego antes de si.

Execute novamente dig +short @10.8.0.1 example.com no cliente. Um endereço no resultado significa que o caminho até ao resolver funciona. O cliente só precisa agora de o utilizar. Adicione a linha ao bloco [Interface] do cliente e reinicie a interface com sudo wg-quick down wg0 && sudo wg-quick up wg0.

[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1

Falha dois: fugas de DNS, porque um túnel dividido não encaminha o resolvedor

Esta falha é pior porque tudo parece funcionar. Os nomes são resolvidos, as páginas carregam e as consultas seguem em texto simples pela rede local que não pretendia considerar confiável.

Duas configurações causam este problema. A primeira é um cliente com AllowedIPs = 0.0.0.0/0, ::/0 e sem uma linha DNS =. wg-quick instala a rota predefinida na sua própria tabela de encaminhamento e adiciona uma regra com suppress_prefixlength 0. Isto mantém intencionalmente as rotas locais mais específicas, para que a máquina continue a conseguir aceder à sua impressora. O resolvedor que o cliente obteve por DHCP, normalmente o router em 192.168.1.1, corresponde a uma dessas rotas locais. O seu tráfego passa pelo túnel. A rede local continua a receber a lista completa dos nomes que consulta.

A segunda é um túnel dividido: AllowedIPs = 10.8.0.0/24 com DNS = 9.9.9.9. Como 9.9.9.9 não está dentro de AllowedIPs, o cliente não tem uma rota para esse endereço através do túnel. Por isso, a consulta sai pela ligação local, exatamente como no primeiro caso.

Confirme qual resolvedor está realmente a responder. whoami.akamai.net é um nome de teste público que responde com o endereço IP do resolvedor recursivo que fez a consulta. Assim, pode comparar a resposta com o endereço público do seu servidor.

resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53

resolvectl status imprime um bloco por ligação. Se o bloco da sua ligação Ethernet ou sem fios ainda mostrar Current DNS Server: 192.168.1.1, enquanto o bloco wg0 não mostrar nenhum, existe uma fuga. Se dig +short whoami.akamai.net devolver o endereço da sua ligação de banda larga doméstica em vez do endereço do servidor, isso confirma o problema no extremo remoto. A linha tcpdump é a prova definitiva: numa configuração correta, todos os pacotes destinados à porta 53 que saem da máquina passam por wg0. Numa fuga, passam por wlan0 ou enp3s0. Os pacotes em lo, de ou para 127.0.0.53, são aplicações a comunicar com o stub local do systemd-resolved e não constituem uma fuga.

A correção tem duas partes, e ambas são necessárias. Defina DNS para um endereço dentro do túnel e confirme que esse endereço está dentro de AllowedIPs.

[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/16

10.8.0.1 está dentro de 10.8.0.0/24, por isso a consulta é encriptada e enviada para o servidor. Se insistir em usar um resolvedor público num túnel dividido, adicione-o como uma rota para o host: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. Os pacotes passam então pelo túnel, embora a rede local ainda possa perceber que escolheu esse fornecedor com base em sessões anteriores. Um resolvedor gerido por si evita essa questão.

A atribuição do resolvedor é uma das diferenças visíveis entre WireGuard configurado manualmente e uma rede mesh coordenada. Esta é uma das contrapartidas abordadas em WireGuard comparado com Tailscale. Executar um servidor de controlo Headscale alojado por si fornece essa coordenação sem entregar o seu material de chaves a terceiros. Se essa última parte for o que o preocupa, tenha em conta que Tailscale nunca guarda as chaves que encriptam o seu tráfego e que a questão mais importante é saber o que um servidor de coordenação comprometido ou uma conta de identidade roubada poderia acrescentar à sua rede.

Falha três: resolvconf e systemd-resolved entram em conflito nos clientes Linux

Os clientes macOS, Windows, iOS e Android aplicam DNS = através da aplicação oficial e causam poucos problemas. No Linux, a definição é aplicada por um script de shell que tem de determinar qual dos vários gestores de resolução está em execução.

A primeira falha é evidente. sudo wg-quick up wg0 termina com:

resolvconf: command not found

wg-quick chama resolvconf, mas esse binário não está instalado. No Debian 12 e no Ubuntu 24.04 ou posterior, o comando resolvconf que comunica com systemd-resolved é fornecido pelo pacote systemd-resolved. Instale esse pacote e volte a ativar a interface. O Ubuntu 22.04 não tem um pacote separado para isso. Nesse caso, crie manualmente a ligação de compatibilidade com sudo ln -s /usr/bin/resolvectl /usr/local/bin/resolvconf e ignore a linha de instalação.

sudo apt install -y systemd-resolved
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0

A segunda falha é silenciosa e é a que pode consumir uma noite inteira. A interface é ativada, resolvectl status wg0 mostra corretamente DNS Servers: 10.8.0.1, mas as consultas continuam a chegar ao resolvedor antigo. O systemd-resolved não está a ignorar wg0. Um nome que não corresponde a nenhum domínio de encaminhamento é enviado para os servidores DNS de todas as ligações consideradas como rota predefinida. Uma ligação com servidores DNS e sem um domínio apenas de encaminhamento é considerada uma rota predefinida. Assim, a consulta é enviada simultaneamente para 10.8.0.1 e para o router da ligação sem fios, e a primeira resposta bem-sucedida vence. O router está a um salto de distância e normalmente responde primeiro. De qualquer forma, a consulta já saiu sem encriptação. Os nomes do domínio de pesquisa próprio da ligação sem fios, como lan, são enviados apenas para essa ligação, porque o domínio de encaminhamento mais específico tem prioridade.

Quando wg-quick aplica DNS = através do wrapper resolvconf próprio do systemd, já solicita um domínio de encaminhamento abrangente. Por isso, esta falha ocorre principalmente quando outra implementação de resolvconf ou um gestor de rede aplica a definição. Defini-la explicitamente elimina a ambiguidade.

Defina o resolvedor e assuma o domínio de encaminhamento abrangente no mesmo passo. %i é expandido para o nome da interface, por isso este bloco funciona sem alterações em qualquer interface.

[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %i

Elimine a linha DNS = quando utilizar PostUp desta forma. Caso contrário, dois mecanismos escrevem o estado do resolvedor e apenas um deles faz a limpeza posterior. O argumento ~. é a parte importante: transforma wg0 no domínio apenas de encaminhamento para todos os nomes. Assim, o systemd-resolved deixa de enviar para as outras ligações os nomes que não correspondem a um domínio mais específico. Os nomes do domínio próprio de outra ligação, como lan, continuam a ser enviados para essa ligação, o que normalmente é desejado para os hosts locais. Verifique o resultado.

resolvectl status wg0

Um resultado correto contém DNS Servers: 10.8.0.1 e DNS Domain: ~.. Se ~. estiver ausente, a parte resolvectl domain não foi executada e wg0 voltou a competir com as outras ligações. Não use a flag de rota predefinida como verificação: ela mostra yes (ou +DefaultRoute na linha Protocols, dependendo da versão do systemd) mesmo sem ~., porque uma ligação sem um domínio apenas de encaminhamento já é uma rota predefinida.

Há mais um caso que merece ser identificado. Se /etc/resolv.conf for um ficheiro real em vez de uma ligação simbólica para /run/systemd/resolve/stub-resolv.conf, outro componente é responsável por ele, normalmente o NetworkManager ou um runtime de contentores. Execute ls -l /etc/resolv.conf antes de investigar qualquer outra coisa, porque uma ferramenta que reescreve esse ficheiro a cada alteração de rede irá desfazer o seu trabalho no pior momento.

O upgrade: o seu próprio resolvedor com filtragem através do túnel

Quando as consultas percorrem o túnel de forma fiável, o resolvedor na outra extremidade torna-se um ponto de controlo. Executar o AdGuard Home nesse local fornece filtragem por listas de bloqueio e um registo de consultas a todos os dispositivos ligados, sem software no cliente nem configuração por dispositivo. O script oficial de instalação, verificado em outubro de 2026, é composto por uma linha.

curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

O assistente de configuração escuta na porta 3000 durante a primeira execução. Aceda a ele através do túnel em http://10.8.0.1:3000, em vez de abrir essa porta publicamente, e no assistente defina tanto o endereço de escuta do DNS como o endereço de escuta da administração para 10.8.0.1. Se unbound da falha um ainda mantiver o mesmo endereço, pare-o primeiro com sudo systemctl disable --now unbound, porque os dois entrariam em conflito pela porta UDP 53 no mesmo endereço e o AdGuard Home terminaria com listen udp 10.8.0.1:53: bind: address already in use.

As configurações dos clientes não precisam de alterações se já indicarem DNS = 10.8.0.1. O registo de consultas mostrará agora todas as pesquisas que lhe chegam de todos os peers, exceto se excluir um cliente do registo. Essa exclusão é uma decisão real de privacidade, não um benefício sem custos: transfere a confiança do seu fornecedor de Internet para si, e é você quem tem de manter esse servidor atualizado. Um servidor exposto à Internet precisa primeiro dos requisitos básicos, e os primeiros dez minutos num VPS novo explica-os.

FAQ

Por que o túnel WireGuard liga, mas os nomes não são resolvidos?

O túnel transporta pacotes e não processa nomes. Portanto, um túnel funcional com consultas falhadas indica que o resolvedor configurado não está a responder. Teste com dig +short @10.8.0.1 example.com no cliente. Uma resposta communication timed out significa que não há nenhum resolvedor à escuta nesse endereço do túnel, muitas vezes porque o stub do systemd-resolved está ligado apenas a 127.0.0.53, ou que a firewall do servidor está a descartar tráfego UDP na porta 53 recebido em wg0. Corrija primeiro o listener e depois abra a porta apenas para wg0.

Como verifico se o meu DNS está a vazar pelo WireGuard?

Execute sudo tcpdump -ni any -c 10 port 53 no cliente e monitorize a coluna da interface enquanto navega. Todos os pacotes que saem da máquina devem usar wg0. Os pacotes em lo de ou para 127.0.0.53 são do stub local do systemd-resolved e são normais. Se aparecerem na interface wireless ou ethernet, as consultas estão a sair sem encriptação. dig +short whoami.akamai.net fornece uma segunda verificação, porque responde com o endereço público do resolvedor recursivo que fez a consulta. Assim, uma resposta que não seja o endereço do seu servidor confirma a fuga.

Preciso da linha DNS = se usar um túnel dividido?

Sim. O endereço do resolvedor também tem de estar dentro de AllowedIPs, caso contrário o cliente não tem uma rota para ele. Com AllowedIPs = 10.8.0.0/24, um resolvedor em 10.8.0.1 fica abrangido e a consulta é encriptada. Um resolvedor público como 9.9.9.9 não fica abrangido. Por isso, a consulta sai pela ligação local, mesmo que a linha DNS pareça correta.

Por que o resolvectl mostra o servidor correto, mas as consultas continuam a ser encaminhadas para outro?

O systemd-resolved envia um nome que não corresponde a nenhum domínio de encaminhamento para todas as ligações com rota predefinida ao mesmo tempo, incluindo wg0, e devolve a primeira resposta bem-sucedida. Normalmente, essa resposta vem do router local. Adicione PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. ao bloco [Interface] do cliente e remova a linha DNS =. Em seguida, resolvectl status wg0 deverá indicar DNS Domain: ~., e cada nome que nenhuma outra ligação reclamar com um domínio mais específico será enviado apenas para wg0.

Qual cliente devo corrigir primeiro quando vários estão com problemas?

Corrija primeiro um cliente Linux, porque é a única plataforma que mostra o mecanismo. resolvectl status e tcpdump indicam qual resolvedor respondeu e qual interface transportou o pacote. As aplicações de telemóveis e de desktop aplicam os mesmos valores DNS e AllowedIPs sem mostrarem essa infraestrutura. Assim, depois de o cliente Linux estar correto, basta copiar uma configuração que já foi validada.