Qué construye esto
Una instancia que ejecuta WireGuard, entregando a cada cliente una dirección IPv4 privada, una dirección IPv6 enrutada de su propio /48, y un resolver que vive dentro del túnel para que las consultas DNS nunca tomen un camino diferente al resto del tráfico. El cortafuegos es de denegación por defecto en ambas direcciones. El reenvío está habilitado solo para la interfaz del túnel, y solo saliente.
Probado en un R-4 en AMS-01 con Debian 13. WireGuard es de flujo único y en el núcleo, por lo que más núcleos no le compran nada hasta que no esté empujando múltiples gigabits a través de él. Lo que importa mucho más es el sitio: elija el más cercano a donde realmente está, porque cada milisegundo que añade aquí lo añade a cada paquete.
Antes de empezar
- Una instancia desplegada y acceso root por SSH.
- El add-on de IPv6 /48 habilitado en el panel. El /64 incluido funciona para un solo cliente, pero subredes por cliente en un solo /64 implica proxy de descubrimiento de vecinos, y eso es un hobby más que una configuración.
- Un nombre de host que apunte a la instancia. Todo lo siguiente usa
vpn.example.com. - Cada dirección
2001:db8:aquí es espacio de documentación. Reemplace el prefijo con el que se muestra en la página de su instancia.
1. Paquetes y ajustes del kernel
apt update && apt full-upgrade -y
apt install -y wireguard-tools nftables unbound qrencode
ip -br linkEse último comando imprime el nombre de la interfaz saliente. En nuestras imágenes KVM es ens3; si el suyo difiere, sustitúyalo en todo el texto. Ahora el 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 --systemLa línea accept_ra = 2 es la que la gente olvida. Activar el reenvío de IPv6 hace que el kernel deje de aceptar anuncios de router, la ruta por defecto desaparece en diez minutos, y la máquina se apaga en v6 mientras sigue respondiendo en v4. Ponerlo a dos mantiene la aceptación de anuncios en un host de reenvío.
2. Claves
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.pskLa clave precompartida no es opcional en esta construcción. No cuesta nada, es una línea en cada configuración, y es la diferencia entre un túnel que es meramente seguro hoy y uno que se mantiene seguro contra un adversario que graba tráfico ahora para descifrarlo después.
3. La interfaz del servidor
Escriba /etc/wireguard/wg0.conf, pegando los contenidos de las claves donde se marque:
[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/128En el lado del servidor AllowedIPs es una tabla de enrutamiento, no una lista de permisos. Dé a cada par exactamente las direcciones que posee y nada más amplio, o dos clientes peleará por la misma ruta y el perdedor simplemente dejará de recibir paquetes.
chmod 600 /etc/wireguard/wg0.conf4. Un resolver dentro del túnel
Apuntar a los clientes a un resolver público deshace gran parte del propósito. Unbound ya está instalado; dele /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: yesUnbound fallará al iniciar antes de que el túnel exista, porque esas direcciones aún no están activas. Secuéncielo adecuadamente en lugar de luchar contra ello:
systemctl edit unbound[Unit]
[email protected]
[email protected]5. El cortafuegos
Reemplace /etc/nftables.conf completamente:
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
}
}Note lo que falta: no hay tabla NAT para IPv6. Los clientes salen con su propia dirección de su /48, que es toda la razón para tomar el /48 en primer lugar. La línea iifname "wg0" oifname "wg0" drop evita que los pares se alcancen entre sí, lo cual quiere a menos que esté construyendo deliberadamente una malla.
systemctl enable --now nftables
nft list ruleset | head -206. Inícielo
systemctl enable --now wg-quick@wg0
systemctl restart unbound
wg show wg07. El 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 = 25Para un teléfono, convierta eso en un código QR en el servidor y fotografíe la terminal:
qrencode -t ansiutf8 < /root/laptop.confEn un cliente Debian o Ubuntu, la línea DNS = necesita openresolv instalado, de lo contrario wg-quick imprime una advertencia y deja silenciosamente su antiguo resolver en su lugar. Esa es la causa más común de un túnel que funciona perfectamente y filtra cada consulta.
Verifíquelo
Cuatro comprobaciones, en orden. Cualquier cosa que falle le dice a qué paso volver.
# on the server, after connecting the client
wg show wg0 latest-handshakes
wg show wg0 transferUna marca de tiempo de handshake dentro de los últimos dos minutos y contadores distintos de cero en ambas direcciones significan que la criptografía y el enrutamiento están bien.
# on the client
ping -c3 10.7.0.1
ping -c3 2001:db8:1a2b:7::1
dig @10.7.0.1 paragonvps.com AAAA +shortEl tercer comando demuestra que el resolver del túnel responde. Si se agota el tiempo, unbound se inició antes de que wg0 existiera; reinícielo.
La última comprobación es la única que demuestra que su tráfico sale a donde usted cree, y necesita una segunda máquina. Cualquier otra instancia en la flota servirá, en cualquier ciudad:
# 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/El listener imprime la dirección de origen de cada conexión. Su intento v4 debería llegar desde el servidor WireGuard, porque fue enmascarado. El intento v6 debería llegar desde la propia dirección del cliente del túnel dentro de su /48, sin tocar, que es lo que significa enrutado y no proxy.
Cuando algo va mal
| Síntoma | Causa | Solución |
|---|---|---|
| El handshake tiene éxito, no pasa tráfico | Reenvío desactivado, o la cadena forward bloquea | sysctl net.ipv4.ip_forward, luego relea la cadena forward |
| Peticiones pequeñas bien, descargas grandes se cuelgan | MTU y descubrimiento de ruta | Baje ambas configuraciones a MTU = 1380 y reintente |
| IPv6 muere unos diez minutos después del arranque | El reenvío mató los anuncios de router | accept_ra = 2 en la interfaz saliente |
| DNS resuelve fuera del túnel | Cliente ignoró DNS = | Instale openresolv en el cliente |
| Todo perdido después de un reinicio | Unidades nunca habilitadas | systemctl enable wg-quick@wg0 nftables unbound |
A partir de aquí, los siguientes pasos sensatos son un segundo punto final en otra región y una pila de monitoreo que le diga cuándo uno de ellos deja de responder. Ambos se tratan en otras partes de las guías; la página de red explica qué hace el borde con su tráfico antes de que llegue a usted.