Doze construções

Um servidor WireGuard endurecido com IPv6 que realmente roteia

Construa um endpoint WireGuard que fornece aos clientes um endereço v4 privado e um prefixo IPv6 genuinamente roteado, atrás de uma política nftables que descarta tudo o que não foi solicitado.

O que isto constrói

Uma instância executando WireGuard, entregando a cada cliente um endereço IPv4 privado, um endereço IPv6 roteado do seu próprio /48 e um resolvedor que vive dentro do túnel para que consultas DNS nunca tomem um caminho diferente do resto do tráfego. O firewall é drop por padrão em ambas as direções. O encaminhamento é habilitado apenas para a interface do túnel, e somente de saída.

Testado em um R-4 no AMS-01 com Debian 13. WireGuard é de fluxo único e do lado do kernel, então mais núcleos não compram nada até você empurrar vários gigabits através dele. O que importa muito mais é o local: escolha o mais próximo de onde você realmente está, porque cada milissegundo que você adiciona aqui você adiciona a cada pacote.

Antes de começar

  • Uma instância implantada e root via SSH.
  • O add-on IPv6 /48 habilitado no painel. O /64 incluído funciona para um único cliente, mas sub-redes por cliente fora de um único /64 significa fazer proxy de descoberta de vizinhos, e isso é um hobby em vez de uma configuração.
  • Um hostname apontando para a instância. Tudo abaixo usa vpn.example.com.
  • Cada endereço 2001:db8: aqui é espaço de documentação. Substitua o prefixo pelo mostrado na página da sua instância.

1. Pacotes e configurações do kernel

apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br link

Esse último comando imprime o nome da sua interface voltada para fora. Nas nossas imagens KVM é ens3; se o seu for diferente, substitua em todos os lugares abaixo. Agora o kernel:

cat > /etc/sysctl.d/99-wireguard.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.ens3.accept_ra = 2
net.ipv4.conf.all.rp_filter = 1
EOF
sysctl --system

A linha accept_ra = 2 é a que as pessoas esquecem. Ativar o encaminhamento IPv6 faz o kernel parar de aceitar anúncios de roteador, a rota padrão desaparece em dez minutos e a máquina fica invisível em v6 enquanto ainda responde em v4. Definir para dois mantém a aceitação de anúncios em um host de encaminhamento.

2. Chaves

install -d -m 700 /etc/wireguard
umask 077
wg genkey | tee /etc/wireguard/server.key | wg pubkey > /etc/wireguard/server.pub
wg genkey | tee /etc/wireguard/laptop.key | wg pubkey > /etc/wireguard/laptop.pub
wg genpsk > /etc/wireguard/laptop.psk

A chave pré-compartilhada não é opcional nesta construção. Não custa nada, é uma linha em cada configuração e é a diferença entre um túnel que é meramente seguro hoje e um que permanece seguro contra um adversário gravando tráfego agora para descriptografar depois.

3. A interface do servidor

Escreva /etc/wireguard/wg0.conf, colando o conteúdo das chaves onde marcado:

[Interface]
Address = 10.7.0.1/24, 2001:db8:1a2b:7::1/64
ListenPort = 51820
PrivateKey = <contents of /etc/wireguard/server.key>
MTU = 1420

[Peer]
# laptop
PublicKey = <contents of /etc/wireguard/laptop.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
AllowedIPs = 10.7.0.2/32, 2001:db8:1a2b:7::2/128

No lado do servidor AllowedIPs é uma tabela de roteamento, não uma lista de permissões. Dê a cada peer exatamente os endereços que ele possui e nada mais amplo, ou dois clientes vão brigar pela mesma rota e o perdedor simplesmente parará de receber pacotes.

chmod 600 /etc/wireguard/wg0.conf

4. Um resolvedor dentro do túnel

Apontar clientes para um resolvedor público desfaz boa parte do objetivo. Unbound já está instalado; dê a ele /etc/unbound/unbound.conf.d/tunnel.conf:

server:
  interface: 10.7.0.1
  interface: 2001:db8:1a2b:7::1
  access-control: 10.7.0.0/24 allow
  access-control: 2001:db8:1a2b:7::/64 allow
  do-ip6: yes
  prefetch: yes
  hide-identity: yes
  hide-version: yes
  qname-minimisation: yes

Unbound falhará ao iniciar antes que o túnel exista, porque esses endereços ainda não estão ativos. Sequencie isso corretamente em vez de lutar contra:

systemctl edit unbound
[Unit]
[email protected]
[email protected]

5. O firewall

Substitua /etc/nftables.conf inteiramente:

flush ruleset

table inet filter {
  chain input {
    type filter hook input priority filter; policy drop;
    ct state established,related accept
    ct state invalid drop
    iif lo accept
    ip protocol icmp accept
    ip6 nexthdr icmpv6 accept
    tcp dport 22 accept
    udp dport 51820 accept
    iifname "wg0" udp dport 53 accept
    iifname "wg0" tcp dport 53 accept
  }
  chain forward {
    type filter hook forward priority filter; policy drop;
    ct state established,related accept
    iifname "wg0" oifname "ens3" accept
    iifname "wg0" oifname "wg0" drop
  }
  chain output {
    type filter hook output priority filter; policy accept;
  }
}

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

Observe o que está ausente: não há tabela NAT para IPv6. Clientes saem com seu próprio endereço do seu /48, que é exatamente o motivo de pegar o /48 em primeiro lugar. A linha iifname "wg0" oifname "wg0" drop impede que peers se alcancem, o que você quer a menos que esteja deliberadamente construindo uma malha.

systemctl enable --now nftables
nft list ruleset | head -20

6. Inicie

systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg0

7. O cliente

[Interface]
PrivateKey = <contents of /etc/wireguard/laptop.key>
Address = 10.7.0.2/24, 2001:db8:1a2b:7::2/64
DNS = 10.7.0.1
MTU = 1420

[Peer]
PublicKey = <contents of /etc/wireguard/server.pub>
PresharedKey = <contents of /etc/wireguard/laptop.psk>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

Para um telefone, transforme isso em um código QR no servidor e fotografe o terminal:

qrencode -t ansiutf8 < /root/laptop.conf

Em um cliente Debian ou Ubuntu, a linha DNS = precisa que openresolv esteja instalado, senão wg-quick imprime um aviso e silenciosamente deixa seu resolvedor antigo no lugar. Essa é a causa mais comum de um túnel que funciona perfeitamente e vaza toda consulta.

Verifique

Quatro verificações, em ordem. Qualquer coisa que falhar indica em qual etapa voltar.

# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transfer

Um timestamp de handshake dentro dos últimos dois minutos e contadores diferentes de zero em ambas as direções significam que a criptografia e o roteamento estão ambos bem.

# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +short

O terceiro comando prova que o resolvedor do túnel está respondendo. Se expirar, o unbound iniciou antes do wg0 existir; reinicie-o.

A última verificação é a única que prova que seu tráfego sai de onde você pensa que sai, e precisa de uma segunda máquina. Qualquer outra instância na frota serve, em qualquer cidade:

# on the second instance
nc -lv 9101

# on the client, tunnel up
curl -m5 -4 http://second.example.com:9101/
curl -m5 -6 http://second.example.com:9101/

O ouvinte imprime o endereço de origem de cada conexão. Sua tentativa v4 deve chegar do servidor WireGuard, porque foi mascarada. A tentativa v6 deve chegar do endereço de túnel do próprio cliente dentro do seu /48, intacta, que é o que roteado significa e com proxy não.

Quando dá errado

SintomaCausaCorreção
Handshake bem-sucedido, nenhum tráfego passaEncaminhamento desligado, ou a cadeia forward descartasysctl net.ipv4.ip_forward, depois releia a cadeia forward
Solicitações pequenas OK, downloads grandes travamMTU e descoberta de caminhoReduza ambas as configurações para MTU = 1380 e tente novamente
IPv6 morre cerca de dez minutos após o bootEncaminhamento matou anúncios de roteadoraccept_ra = 2 na interface de saída
DNS resolve fora do túnelCliente ignorou DNS =Instale openresolv no cliente
Tudo sumiu após reinicializaçãoUnidades nunca habilitadassystemctl enable wg-quick@wg0 nftables unbound

A partir daqui, os próximos passos sensatos são um segundo endpoint em outra região e uma pilha de monitoramento que te diga quando um deles parar de responder. Ambos estão cobertos em outro lugar em os guias; a página de rede explica o que a borda faz com seu tráfego antes de chegar até você.

Pronto quando você estiver

Escolha uma cidade. Escolha um tamanho. Pague em cripto.

Sem formulários sobre quem você é, sem esperar aprovação de um humano, sem ligação para verificar nada. O pagamento é confirmado e as credenciais chegam na sua caixa de entrada.