Split tunneling con namespaces y WireGuard

Aislar el tráfico de laboratorio del tráfico personal en la misma maquina. Lo que sale dentro del namespace va por VPN; el resto del sistema sigue navegando por la conexión normal. Sin maquinas virtuales y sin docker.

El problema

Una VPN tradicional en el host cambia la IP de todo: navegación, correo, SSH y actualizaciones. Si el túnel cae, te quedas sin nada. Y mezcla tráfico de trabajo sucio con sesiones personales, que es exactamente lo que no se debe hacer en una auditoría.

La solución es un network namespace de Linux: una pila de red independiente, con sus interfaces, rutas y DNS, aislada del host. Solo lo que se ejecuta dentro sale por el túnel.

ElementoIdentidadUso
HostIP pública del ISPGestion, SSH, actualizaciones, navegación personal
Namespace hacker_labIP de salida de la VPNEscaneos, pruebas, herramientas ofensivas

Requisitos

sudo apt update
sudo apt install wireguard wireguard-tools resolvconf ntpdate -y
  • wireguard: protocolo VPN moderno, más ligero y rápido que OpenVPN.
  • resolvconf: gestion de DNS en el namespace.
  • ntpdate: WireGuard falla si el reloj se desvia; sincronizar antes de levantar el túnel.

Comprobación previa:

ip netns list            # no debe existir ya hacker_lab
sysctl net.ipv4.ip_forward

Fichero de WireGuard

Se parte del .conf que entrega el proveedor y se ajusta para que funcione dentro del namespace. Los tres cambios que casi siempre hacen falta:

  1. Quitar el DNS del fichero. Se gestiona aparte en /etc/netns/, si no se filtra por el host.
  2. Quitar IPv6 (::/0). En el namespace da RTNETLINK answers: No such device.
  3. Bajar el MTU a 1280-1420. Evita fragmentación en redes inalambricas.
[Interface]
PrivateKey = <CLAVE_PRIVADA_CLIENTE>
Address = 10.10.10.2/32
MTU = 1280
 
[Peer]
PublicKey = <CLAVE_PUBLICA_SERVIDOR>
Endpoint = <IP_SERVIDOR>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

AllowedIPs = 0.0.0.0/0 solo IPv4: todo el tráfico del namespace va por el túnel. PersistentKeepalive mantiene el NAT abierto en redes restrictivas.

Construcción del namespace

# 1. Namespace
sudo ip netns add hacker_lab
 
# 2. Par veth (cable virtual con dos extremos)
sudo ip link add veth_host type veth peer name veth_guest
sudo ip link set veth_guest netns hacker_lab
 
# 3. Direccionamiento: 10.10.10.0/24 solo para el enlace
sudo ip addr add 10.10.10.1/24 dev veth_host
sudo ip netns exec hacker_lab ip addr add 10.10.10.2/24 dev veth_guest
 
# 4. Levantar interfaces (incluido loopback, que dentro esta bajado)
sudo ip link set veth_host up
sudo ip netns exec hacker_lab ip link set veth_guest up
sudo ip netns exec hacker_lab ip link set lo up
 
# 5. Ruta por defecto del namespace hacia el host
sudo ip netns exec hacker_lab ip route add default via 10.10.10.1
 
# 6. NAT en el host para dar salida
sudo iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
sudo sysctl -w net.ipv4.ip_forward=1

Sustituir eth0 por la interfaz real del host (ip route get 1.1.1.1 lo indica).

DNS aislado

Sin esto, el namespace hereda el /etc/resolv.conf del host y cada consulta revela al ISP los dominios analizados.

sudo mkdir -p /etc/netns/hacker_lab
printf 'nameserver 1.1.1.1\nnameserver 9.9.9.9\n' | sudo tee /etc/netns/hacker_lab/resolv.conf

Todo proceso lanzado con ip netns exec hacker_lab usa ese fichero.

Levantar el túnel dentro del namespace

sudo ip netns exec hacker_lab wg-quick up ./lab.conf
sudo ip netns exec hacker_lab wg show

Verificación: la IP de salida dentro del namespace debe ser distinta de la del host.

curl -s https://api.ipify.org                              # host
sudo ip netns exec hacker_lab curl -s https://api.ipify.org # namespace

Desmontaje

sudo ip netns exec hacker_lab wg-quick down ./lab.conf
sudo ip netns pids hacker_lab | xargs -r sudo kill
sudo ip netns del hacker_lab
sudo iptables -t nat -D POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE

Errores típicos

  • RTNETLINK answers: No such device al levantar WireGuard: queda IPv6 en AllowedIPs.
  • El namespace no tiene salida: falta ip_forward, el MASQUERADE apunta a otra interfaz o falta la ruta por defecto.
  • DNS filtrado: no existe /etc/netns/hacker_lab/resolv.conf, o la herramienta usa su propio resolver (por ejemplo dig @8.8.8.8).
  • WebRTC o aplicaciones con su propia pila de red: escapan del namespace. Esas pruebas van en navegador sin WebRTC o directamente no se hacen.
  • El túnel cae y el tráfico sigue sin cifrar: el namespace no cae con el. Comprobar wg show antes de cada sesión.

Alternativa rápida

firejail --net=... o bwrap sirven para casos puntuales, pero no dan control fino de rutas, DNS y NAT. Para trabajo serio, namespace manual.