SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-28

Como configurar uma VPN WireGuard no seu VPS

Configure WireGuard no VPS Linux com chaves, wg0.conf, NAT, encaminhamento IP, DNS e AllowedIPs. Veja por que falhas de handshake não geram resposta.

O que está a configurar

Uma VPN WireGuard num servidor que controla requer cerca de quarenta linhas de configuração: um par de chaves, um ficheiro de interface, um sysctl, uma regra NAT e uma exceção na firewall. A instalação é simples. Por isso, a maior parte deste guia aborda as falhas mais comuns, as permissões das chaves, AllowedIPs, o encaminhamento e o DNS.

O WireGuard é um túnel de camada 3 no kernel e faz parte do kernel principal desde o Linux 5.6. Por isso, Ubuntu 24.04 e Debian 13 incluem-no sem um módulo externo. Não existe negociação de cifras, autoridade de certificação nem etapa de nome de utilizador e palavra-passe. Um peer é uma chave pública e os endereços IP que essa chave pode utilizar. Um pacote que falhe a verificação MAC é descartado sem resposta. Por isso, a porta não responde a análises. A contrapartida é que não existe um servidor de autenticação. Para remover o acesso, elimine o peer no servidor.

Verifique primeiro a virtualização

O WireGuard precisa de um kernel no qual possa carregar um módulo. Num VPS KVM, funciona sem configuração adicional. Em virtualização por contentores que partilha o kernel do host, como OpenVZ ou LXC, o primeiro comando falha com RTNETLINK answers: Operation not supported. Nesse caso, use como alternativa a implementação em userspace wireguard-go. Verifique primeiro com sudo modprobe wireguard && echo ok.

Gere chaves sem as expor

Uma /etc/wireguard/server.key legível por todos equivale a não ter VPN. A linha comum umask 077 && wg genkey | sudo tee ... não é fiável, porque sudo aplica o seu próprio umask ao ficheiro que tee cria. Defina explicitamente o modo.

sudo apt update && sudo apt install -y wireguard nftables
sudo install -d -m 700 /etc/wireguard
sudo sh -c 'umask 077; wg genkey > /etc/wireguard/server.key'
sudo sh -c 'wg pubkey < /etc/wireguard/server.key > /etc/wireguard/server.pub'
sudo chmod 600 /etc/wireguard/server.key

Gere o par do cliente da mesma forma. wg genpsk adiciona uma chave pré-partilhada opcional, uma linha em cada configuração.

A interface do servidor: /etc/wireguard/wg0.conf

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>

[Peer]
PublicKey = <laptop public key>
PresharedKey = <psk, optional>
AllowedIPs = 10.8.0.2/32

chmod 600; um aviso de arranque a informar que o ficheiro está acessível a todos significa que ignorou esse passo. Address é o endereço do servidor dentro do túnel, com a máscara de toda a sub-rede da VPN. Escolha um intervalo que não encontre noutras redes, porque 192.168.1.0/24 entra em conflito com metade dos routers domésticos onde os seus clientes estão ligados, e o túnel perde silenciosamente para a rota local.

O AllowedIPs de um peer no lado do servidor é um /32, o único endereço do túnel que esse cliente possui. Se atribuir o mesmo IP permitido a dois peers, esse IP passa para o peer configurado por último, e o primeiro deixa de receber tráfego sem que seja apresentado qualquer erro. Deixe SaveConfig por configurar, ou wg-quick down reescreve este ficheiro a partir do estado em execução.

Transforme o servidor num router

Um servidor Linux descarta os pacotes que não lhe são destinados. O encaminhamento e o NAT de origem não estão ativos por predefinição.

printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
  | sudo tee /etc/sysctl.d/99-wireguard.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward

Um sysctl -w simples funciona até ao próximo reboot e depois deixa de funcionar silenciosamente. O NAT precisa da interface de egress, a NIC que chega à Internet, e não de wg0. Não assuma eth0; obtenha o valor correto em ip route show default, porque as imagens atuais usam nomes como enp1s0 ou ens3.

Firewall: a porta e o caminho de encaminhamento

Um único ficheiro nftables trata do filtro e do NAT. Escreva /etc/nftables.conf. Este comando limpa o conjunto de regras existente, por isso não o execute num sistema já gerido pelo ufw ou pelo Docker.

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    iif lo accept
    tcp dport 22 accept
    udp dport 51820 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "enp1s0" accept
  }
}

table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat; policy accept;
    ip saddr 10.8.0.0/24 oifname "enp1s0" masquerade
  }
}

Aplique-o com sudo systemctl enable --now nftables e mantenha uma segunda sessão SSH aberta: policy drop, juntamente com um erro de digitação na regra SSH, pode bloquear o acesso ao seu próprio servidor. Observe o que a cadeia de encaminhamento não permite, wg0 para wg0. Os pares conseguem aceder à Internet, mas não uns aos outros; adicione iifname "wg0" oifname "wg0" accept para uma VPN entre pares. A mesma cadeia controla o que um par pode aceder no próprio servidor. Isto é importante quando o sistema também funciona como uma máquina de desenvolvimento remoto que executa o Claude Code no tmux e prefere não expor essa parte publicamente.

Num sistema com ufw: ufw allow 51820/udp, DEFAULT_FORWARD_POLICY="ACCEPT" em /etc/default/ufw e uma regra POSTROUTING MASQUERADE no topo de /etc/ufw/before.rules com *nat.

Ative-o com o systemd

sudo systemctl enable --now wg-quick@wg0
sudo wg show

wg-quick cria a interface, adiciona os endereços e instala as rotas derivadas de AllowedIPs. enable --now é a parte importante: um wg-quick up wg0 executado manualmente desaparece após o próximo reboot, e as atualizações do kernel implicam reboots. Uma unidade que não volte a arrancar depois de um desses reboots permanece silenciosa até alguém tentar ligar-se, por isso um drop-in OnFailure= em wg-quick@wg0, apontado para o seu próprio servidor ntfy, é a forma mais simples de receber o alerta no telemóvel, em vez de depender de um utilizador impedido de iniciar sessão.

A configuração do cliente e a opção que todos configuram incorretamente

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

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

AllowedIPs desempenha duas funções diferentes ao mesmo tempo. Confundi-las é a origem da maioria das dúvidas sobre o WireGuard.

Na saída, funciona como uma tabela de encaminhamento. Um pacote cujo destino corresponda a AllowedIPs de um peer é cifrado e enviado para esse peer. 0.0.0.0/0, ::/0 envia tudo pelo túnel: é um túnel completo, com o servidor como rota predefinida. Um túnel dividido usa uma lista mais restrita: AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 transporta o tráfego da VPN e uma rede privada atrás do servidor; todo o restante mantém a rota local. Essa lista restrita permite manter serviços completamente fora da Internet pública. Por exemplo, uma instância privada do Nextcloud num VPS associada ao endereço do túnel, ou as VMs do laboratório de virtualização aninhada em execução no mesmo equipamento, continuam acessíveis aos peers e invisíveis para todos os outros.

Na entrada, funciona como uma lista de controlo de acesso. Um pacote desencriptado de um peer cujo endereço de origem não esteja em AllowedIPs desse peer é descartado. Por isso, o servidor lista 10.8.0.2/32 para o portátil: uma entrada 0.0.0.0/0 nesse campo permitiria a esse cliente falsificar qualquer endereço do túnel.

PersistentKeepalive destina-se a clientes atrás de NAT, onde o router mantém o mapeamento UDP aberto apenas enquanto houver tráfego de pacotes. Quando o mapeamento expira, o servidor deixa de conseguir alcançar o cliente. PersistentKeepalive = 25 mantém o mapeamento aberto. Configure-o no cliente, não num servidor com um endereço IP público.

DNS e o vazamento que ninguém percebe

Com AllowedIPs = 0.0.0.0/0 e sem uma linha DNS =, o cliente mantém o resolvedor que aprendeu com a rede local, o router do café em 192.168.1.1. Essa rota é mais específica do que a rota predefinida. Por isso, as consultas DNS saem pela ligação local em texto simples, enquanto todo o restante tráfego é encaminhado pelo túnel. O tráfego é privado; a lista de nomes não é.

Há duas opções corretas. Aponte DNS para um resolvedor público (DNS = 9.9.9.9). Assim, as consultas percorrem o túnel e saem pelo seu servidor, embora esse resolvedor continue a vê-las. Ou execute unbound ou dnsmasq associado a 10.8.0.1, defina DNS = 10.8.0.1 e adicione udp dport 53 iifname "wg0" accept à cadeia de entrada. Defina essa linha e esqueça o resolvedor. Nesse caso, nada é resolvido.

Nos clientes Linux, wg-quick aplica DNS através de resolvconf. Se estiver ausente, obterá resolvconf: command not found. Instale openresolv ou defina PostUp = resolvectl dns %i 10.8.0.1 num cliente que use systemd-resolved.

Adicionando e removendo peers sem interromper o túnel

Reiniciar a interface para adicionar um utilizador desconecta todos os utilizadores ligados. Anexe o bloco [Peer] a wg0.conf e, em seguida, recarregue o conjunto de peers sem interromper a interface.

sudo bash -c 'wg syncconf wg0 <(wg-quick strip wg0)'

wg-quick strip imprime a configuração sem as chaves exclusivas do wg-quick (Address, DNS, PostUp), e syncconf aplica a diferença enquanto as sessões ativas continuam. A atualização aplica-se apenas aos peers: uma alteração em Address ainda requer um ciclo completo de down/up. Revogue com sudo wg set wg0 peer <public key> remove e, em seguida, elimine o bloco do ficheiro; caso contrário, ele será restaurado no próximo reload.

Modos de falha e mensagens apresentadas

O handshake nunca é concluído. wg show lista o peer sem latest handshake, e os logs do cliente mostram:

Handshake for peer 1 (10.0.0.10:51820) did not complete after 5 seconds, retrying (try 2)

Não está a chegar nada ou nada está a ser aceite. Verifique, por esta ordem: se a porta UDP 51820 está aberta na firewall da VPS e na firewall de rede do seu fornecedor, que é um controlo separado na maioria dos painéis; se o endereço e a porta de Endpoint estão corretos; e se as chaves foram trocadas. A chave no bloco [Peer] do cliente tem de ser a chave pública do servidor e vice-versa. Colar uma chave privada ou a chave pública do próprio cliente produz exatamente este sintoma. sudo tcpdump -ni any udp port 51820 no servidor mostra se chegam pacotes. O módulo do kernel não regista nada por predefinição. As mensagens do WireGuard aparecem em dmesg apenas depois de ativar a depuração dinâmica (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control). Com essa depuração ativa, uma incompatibilidade de chaves aparece como uma rejeição por MAC inválido.

O handshake funciona, mas não há Internet. ping 10.8.0.1 é concluído, mas ping 1.1.1.1 excede o tempo limite: falta encaminhamento ou NAT. Verifique se sysctl net.ipv4.ip_forward devolve 1. Depois, monitorize os contadores enquanto o cliente faz ping, com sudo nft list ruleset ou sudo iptables -t nat -L POSTROUTING -n -v. Zero pacotes na regra de masquerade significa que o nome da interface de saída está errado. Um contador crescente sem respostas aponta para a política da cadeia de encaminhamento.

A Internet funciona, mas os nomes não. ping 1.1.1.1 é concluído e curl https://example.com devolve Could not resolve host. Falta a linha DNS ou esta indica um resolver inacessível a partir do interior do túnel.

Alguns sites HTTPS ficam bloqueados. SSH e ping funcionam, mas as páginas grandes ficam paradas. Isto indica um problema de MTU do caminho: o túnel acrescenta overhead e algum segmento intermédio descarta os pacotes demasiado grandes sem devolver uma mensagem ICMP. Reduza MTU no [Interface] do cliente, experimente 1420, depois 1380 e, por fim, 1280. Se reduzir o MTU resolver os bloqueios, mas o débito continuar abaixo do esperado, não continue a adivinhar valores redondos. Siga encontrar o MTU real do caminho por bisseção e limitar o TCP MSS. Isto também elimina as causas que não estão relacionadas com o túnel.

A interface recusa iniciar. Address already in use significa que outro processo detém a porta UDP 51820. Cannot find device wg0 depois de um up falhado normalmente significa que a configuração foi rejeitada. Consulte journalctl -u wg-quick@wg0 -n 50.

Migrando do Streisand ou OpenVPN

O Streisand não é mantido e o seu repositório foi arquivado. Executar uma VPN baseada em automação abandonada cria um problema de segurança que se agrava com o tempo. Não existe uma atualização direta. A PKI do OpenVPN não pode ser convertida: o WireGuard não usa certificados nem CA e não tem expiração. Por isso, cada cliente recebe um novo par de chaves.

Faça a migração em paralelo. O WireGuard em UDP 51820 pode coexistir com o OpenVPN na porta 1194 no mesmo servidor. Configure wg0, migre os clientes um de cada vez e depois pare o serviço antigo. O modelo de nome de utilizador, palavra-passe e revogação do OpenVPN não é transferido. Se precisar de contas ou de um registo de auditoria, adicione essa camada acima do WireGuard.

Backups, atualizações e o que causa limitações em escala

/etc/wireguard é o servidor. Faça uma cópia de segurança dele (sudo tar czf wg-backup.tgz -C /etc wireguard, modo 600, guardada fora do servidor) e poderá reconstruí-lo num VPS novo em minutos. Se perder a chave privada do servidor, terá de emitir novamente a configuração de todos os clientes, porque os clientes fixam a chave pública do servidor. As atualizações consistem normalmente num apt upgrade e num reboot para atualizações do kernel. O wg-quick@wg0 volta a funcionar sozinho se o tiver ativado.

O estado de cada peer é pequeno e a criptografia é executada no kernel. Por isso, o limite é determinado pelo CPU e pelo limite de largura de banda do VPS, e não por algo nesta configuração. Meça-o com iperf3 através do túnel, em vez de confiar num valor publicado. O que causa limitações em escala é a operação. Cada peer precisa de um IP de túnel exclusivo. Editar manualmente sessenta blocos [Peer] é uma forma de introduzir AllowedIPs duplicados. Gere as configurações com um script. Um servidor representa um endpoint UDP e um ponto único de falha. O WireGuard não tem clustering. A redundância exige um segundo servidor com as suas próprias chaves. A rotação de chaves continua a ser manual. Registe quem tem cada chave e como revogar uma chave. Quando esse controlo deixa de caber num ficheiro de texto, a resposta habitual é usar um control plane sobre o mesmo data plane do kernel. Um servidor NetBird autoalojado trata da atribuição de endereços, da distribuição de peers e das setup keys que, de outro modo, teria de gerir manualmente. Se executar esse control plane por sua conta representar mais um servidor do que pretende manter, o Tailscale aloja um por si. O seu plano gratuito inclui seis utilizadores com dispositivos ilimitados, o suficiente para que a maioria das redes pessoais nunca tenha de pagar. A partir desse limite, o custo passa a depender das pessoas e não das máquinas. Por isso, o que uma família ou uma equipa pequena paga efetivamente depende de quantas pessoas têm credenciais de acesso, e não de quantos peers teria de editar manualmente em wg0.conf. Nesse cenário, o controlo AllowedIPs do split tunnel passa a ser anunciar as suas redes privadas a partir de um subnet router. O anúncio é feito uma vez a partir de um VPS e aprovado centralmente, em vez de ser copiado para o ficheiro de cada cliente. A decisão de fazer essa troca depende do que um control plane alojado consegue efetivamente alcançar. Ele nunca tem as chaves que encriptam o seu tráfego, embora determine quais os peers que ficam a conhecer-se.

Tudo isto exige um sistema Linux que controle, um IP público, um kernel no qual possa carregar um módulo e uma firewall que controle de ponta a ponta.

FAQ

Porque é que o handshake do WireGuard nunca é concluído?

Uma wg show que apresenta um peer sem latest handshake significa que os pacotes não estão a chegar ou não estão a ser aceites. Verifique a porta UDP 51820 na firewall do VPS e na firewall de rede separada do fornecedor. Confirme o host e a porta Endpoint. Depois, verifique se as chaves não estão trocadas. O bloco [Peer] do cliente tem de conter a chave pública do servidor. sudo tcpdump -ni any udp port 51820 no servidor mostra se os pacotes chegam. dmesg só comunica falhas de handshake do WireGuard depois de ativar a depuração dinâmica (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control). Uma incompatibilidade de chaves aparece então como uma rejeição por MAC inválido.

O túnel liga-se, mas não tenho Internet. O que falta?

ping 10.8.0.1 a funcionar enquanto ping 1.1.1.1 excede o tempo limite aponta para um problema de encaminhamento ou NAT. Confirme que sysctl net.ipv4.ip_forward apresenta 1 e que está definido em /etc/sysctl.d/, não apenas através de um sysctl -w que desaparece depois de um reboot. Depois, verifique se a regra de masquerade usa o nome real da interface de saída obtido com ip route show default, enp1s0 ou, raramente, ens3 e eth0.

Preciso da linha DNS = na configuração do cliente?

Com um túnel completo e sem a linha DNS =, o cliente mantém o resolver que aprendeu na rede local. Essas consultas saem em texto simples pela ligação local, enquanto todo o restante tráfego passa pelo túnel. Aponte DNS para um resolver público ou execute unbound/dnsmasq associado a 10.8.0.1 e abra udp dport 53 iifname "wg0" na cadeia de entrada.

O que controla realmente AllowedIPs?

Tem duas funções. No tráfego de saída, é uma tabela de encaminhamento: o tráfego que corresponde a AllowedIPs de um peer é cifrado e enviado para esse peer. No tráfego de entrada, é uma lista de controlo de acesso: um pacote decifrado cuja origem esteja fora de AllowedIPs desse peer é rejeitado. Por isso, o lado do servidor lista um /32 por cliente, enquanto o lado do cliente pode listar 0.0.0.0/0.

O WireGuard funciona em qualquer VPS?

Num VPS KVM, funciona com o módulo do kernel e sem configuração adicional. Em virtualização baseada em contentores que partilha o kernel do host, como OpenVZ ou LXC, modprobe wireguard falha com Operation not supported. Nesse caso, a alternativa é a implementação em espaço de utilizador wireguard-go. Execute sudo modprobe wireguard && echo ok antes de qualquer outra coisa.