Como configurar WireGuard VPN no Linux VPS
Aprenda a configurar o WireGuard no seu VPS Linux. Guia prático sobre geracao de chaves, configuracao wg0.conf, regras de NAT, encaminhamento IP e resolucao de falhas.
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
Um /etc/wireguard/server.key legível por todos equivale a não ter VPN. A linha comum umask 077 && wg genkey | sudo tee ... funciona: a menos que o sudoers defina umask_override, que está desativado por predefinição, sudo combina o seu umask com o valor predefinido 0022 e nunca o torna menos restritivo, pelo que o ficheiro criado por tee fica com o modo 600. As chaves ficam expostas quando executa esse pipe sem umask 077, com um umask normal de 022, ou num sistema cujo sudoers ativa umask_override. Defina o modo explicitamente para eliminar essa diferença.
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.keyGere o par do cliente da mesma forma. wg genpsk adiciona uma chave pré-partilhada opcional, com 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/32chmod 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_forwardUm 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 ficheiro nftables abrange o filtro e o NAT. Escreva /etc/nftables.conf; o comando liberta o conjunto de regras existente, por isso não o execute num servidor 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. Repare no que a cadeia forward não permite: wg0 para wg0. Os peers têm acesso à Internet, mas não uns aos outros; adicione iifname "wg0" oifname "wg0" accept para uma VPN peer-to-peer. O que um peer pode aceder no próprio servidor não é responsabilidade desta cadeia: os pacotes destinados ao servidor passam pelo hook input, nunca pelo forward. Por isso, a cadeia input decide, e, tal como está escrita, permite que um peer aceda a SSH e a mais nada, nem sequer faça ping a 10.8.0.1. Adicione iifname "wg0" icmp type echo-request accept nessa cadeia, além de uma regra iifname "wg0" por serviço que queira tornar acessível apenas através do túnel. Isto é importante quando o servidor também funciona como uma máquina de desenvolvimento remoto que executa Claude Code em tmux e prefere não expor essa componente publicamente.
Num servidor com ufw: ufw allow 51820/udp, DEFAULT_FORWARD_POLICY="ACCEPT" em /etc/default/ufw e uma regra POSTROUTING MASQUERADE *nat no início de /etc/ufw/before.rules.
Ative-o com o systemd
sudo systemctl enable --now wg-quick@wg0
sudo wg showwg-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 = 25AllowedIPs 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 as mensagens apresentadas
O handshake nunca termina. 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 é aceite. Verifique, pela seguinte ordem: se UDP 51820 está aberto na firewall do VPS e na firewall de rede do fornecedor, que é um controlo separado na maioria dos painéis; se o endereço e a porta Endpoint estão corretos; e se as chaves estão 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 os pacotes chegam. O módulo do kernel não regista nada por predefinição. As mensagens do WireGuard aparecem em dmesg apenas depois de ativar o debug dinâmico (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control). Com esta opçã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 é bem-sucedido, mas ping 1.1.1.1 excede o tempo limite: falta o encaminhamento ou o NAT. Confirme se sysctl net.ipv4.ip_forward apresenta 1. Depois, observe 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 é bem-sucedido e curl https://example.com devolve Could not resolve host. Falta a linha DNS ou esta especifica 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 elemento intermédio da ligação descarta os pacotes demasiado grandes sem enviar uma mensagem ICMP de volta. Defina MTU no [Interface] do cliente. Numa ligação normal de 1500 bytes, wg-quick já escolhe 1420 (1500 menos os seus 80 bytes de overhead), portanto escrever 1420 não altera nada. Experimente 1380 e depois 1280. Se reduzir o MTU resolver as paragens, mas o débito continuar abaixo do esperado, não continue a testar valores redondos. Siga o procedimento para encontrar o MTU real do caminho por bisseção e limitar o MSS de TCP, que também exclui as causas que não estão relacionadas com o túnel.
A interface recusa-se a iniciar. Address already in use significa que outro processo está a usar UDP 51820. Cannot find device wg0 depois de um up falhar normalmente significa que a configuração foi rejeitada. Leia 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 (sudo tar czf wg-backup.tgz -C /etc wireguard, com modo 600, guardada fora do servidor) e poderá reconstruí-lo num VPS novo em poucos minutos. Se perder a chave privada do servidor, terá de emitir novamente a configuração de todos os clientes, porque estes fixam a chave pública do servidor. As atualizações consistem num apt upgrade normal e num reboot para atualizações do kernel; wg-quick@wg0 volta a iniciar sozinho se o tiver ativado.
O estado de cada peer é pequeno e a criptografia é executada no kernel. Por isso, o limite é a capacidade de CPU e de largura de banda do VPS, e não qualquer elemento desta configuração. Meça o desempenho com iperf3 através do túnel, em vez de confiar num valor publicado. Em escala, o que causa limitações é a operação. Cada peer precisa de um IP de túnel exclusivo, e editar manualmente sessenta blocos [Peer] é uma forma de introduzir AllowedIPs duplicados. Gere as configurações com um script. Um servidor corresponde a um endpoint UDP e a um ponto único de falha, e 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 possui cada chave e como revogar uma chave. Quando essa gestão deixa de caber num ficheiro de texto, a resposta habitual é 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 configurar manualmente. Se executar esse control plane for mais um servidor do que pretende gerir, o Tailscale aloja um por si. O seu plano Personal gratuito abrange seis utilizadores com dispositivos de utilizador ilimitados e, inicialmente, até 50 recursos identificados, como servidores, o suficiente para que a maioria das infraestruturas pessoais nunca tenha de pagar. Acima desse limite, o custo depende de pessoas, não de máquinas. Por isso, o que uma família ou uma equipa pequena paga efetivamente depende do número de pessoas com credenciais, não do número de peers que teria de editar manualmente em wg0.conf. Nesse modelo, a gestão AllowedIPs do split tunnel passa a ser a divulgação das suas redes privadas a partir de um subnet router, anunciada uma vez por um VPS e aprovada centralmente, em vez de ser colada no ficheiro de cada cliente. A vantagem dessa troca depende do que o control plane alojado pode efetivamente alcançar. Ele nunca possui as chaves que encriptam o seu tráfego, embora decida quais os peers que ficam a conhecer-se.
Tudo isto exige um servidor Linux sob o seu controlo, um IP público, um kernel no qual possa carregar um módulo e uma firewall que controle integralmente.
FAQ
Por que o handshake do WireGuard nunca é concluído?
wg show listar 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 tanto na firewall da VPS como na firewall de rede separada do seu fornecedor, confirme o Endpoint host e a porta, e depois verifique se as chaves não estão trocadas; o bloco [Peer] do cliente deve conter a chave pública do servidor. sudo tcpdump -ni any udp port 51820 no servidor mostra se os pacotes chegam de todo; dmesg apenas reporta falhas de handshake do WireGuard depois de ativar o debug dinâmico (echo module wireguard +p | sudo tee /sys/kernel/debug/dynamic_debug/control), e então uma incompatibilidade de chaves aparece como um descarte 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 esgota o tempo limite aponta para problemas de encaminhamento ou NAT. Confirme se sysctl net.ipv4.ip_forward contém 1 e se está definido em /etc/sysctl.d/, e não apenas com um sysctl -w que desaparece após o reboot. Depois, verifique se a regra de masquerade usa o nome real da sua interface de saída obtido com ip route show default, enp1s0 ou ens3, raramente eth0.
Preciso da linha DNS = na configuração do meu cliente?
Com um túnel completo e sem a linha DNS =, o cliente mantém o resolvedor que aprendeu na rede local, e essas consultas saem em texto simples pela ligação local enquanto tudo o resto é enviado pelo túnel. Aponte DNS para um resolvedor público, ou execute unbound/dnsmasq vinculado a 10.8.0.1 e abra udp dport 53 iifname "wg0" na cadeia de entrada (input chain).
O que é que AllowedIPs controla realmente?
Desempenha duas funções. No tráfego de saída, é uma tabela de encaminhamento: o tráfego que corresponde ao AllowedIPs de um peer é encriptado e enviado para esse peer. No tráfego de entrada, é uma lista de controlo de acesso: um pacote desencriptado cuja origem esteja fora do AllowedIPs desse peer é descartado. É por isso que 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?
Numa VPS KVM, funciona com o módulo no kernel sem configuração adicional. Em virtualização de contentores que partilha o kernel do hospedeiro, como OpenVZ ou LXC, modprobe wireguard falha com Operation not supported e a alternativa é a implementação em espaço de utilizador wireguard-go. Execute sudo modprobe wireguard && echo ok antes de qualquer outra coisa.