// En 30 segundos
# Salida real del script de despliegue
$ ./deploy_tunnel.sh --provider vps01 --mode full
[+] Dependencias instaladas: WireGuard, udp2raw, redsocks, dnscrypt-proxy, dnsmasq
[+] WireGuard configurado: Nodo A (10.100.0.1) <-> Nodo B (10.100.0.2)
[+] udp2raw activo: faketcp + XOR -> puerto 443 (simulando HTTPS)
[+] redsocks conectado: SOCKS5 residencial -> IP salida: 203.0.113.x (residencial)
[+] DNS blindado: dnscrypt-proxy -> Cloudflare DoH (TCP-only)
[+] iptables aplicado: DNAT entrada + REDSOCKS_TCP salida
[OK] Despliegue completado en: 87 segundos
13. Arquitectura: defensa en profundidad en dos capas
El diseño pivota sobre un modelo de dos nodos con funciones radicalmente separadas, conectados únicamente por el túnel privado ofuscado. Esa separación tiene una consecuencia directa: el nodo que aloja los servicios reales nunca muestra su IP a Internet — y con ella se derrumba la mayor parte de la superficie de ataque.
Nodo A — puerta de enlace pública
Único punto de entrada visible. Acepta las conexiones entrantes en puertos no convencionales, las empuja hacia el nodo B por el túnel y no expone más que lo estrictamente operativo. Para el mundo exterior, su IP es la única que existe.
Nodo B — servicios reales
Aquí viven los servicios internos, con una regla dura: ningún puerto abierto a Internet salvo el acceso administrativo. Todo el tráfico legítimo le llega desde A por el túnel; su salida a Internet se disfraza tras proxies residenciales, con resolución DNS cifrada (DoH).
💡
Principio de diseño
Separar «puerta de enlace» de «servidor de aplicaciones» es defensa en profundidad de manual. Si cae el nodo A, quien ataca no gana acceso inmediato a los servicios ni a los datos del nodo B. Si cae el nodo B, su IP real jamás aparece en logs públicos. La misma filosofía de aislamiento se aplica en el laboratorio SOC/honeypot con Proxmox y OPNsense .
Arquitectura completa generada con PlantUML — Los dos VPS, el túnel WireGuard encapsulado en TCP falso por udp2raw, las reglas DNAT con iptables, la salida gestionada por redsocks tras el proxy residencial y el resolver DNS sobre HTTPS (dnscrypt-proxy + dnsmasq).
14. Túnel privado: WireGuard sobre TCP falso con udp2raw
El problema del UDP en entornos restrictivos
WireGuard habla UDP nativo, y eso duele en dos frentes a la vez: firewalls restrictivos que descartan UDP no solicitado y sistemas de inspección profunda de paquetes (DPI) capaces de reconocer y bloquear el handshake por su firma.
udp2raw: encapsulación TCP con ofuscación XOR
udp2raw mata ambos pájaros de un tiro: toma el UDP nativo de WireGuard, lo envuelve en una conexión TCP y le añade una capa de ofuscación con clave compartida. Lo que sale por el cable es un flujo TCP que para cualquier observador externo no delata ser un túnel VPN; al viajar por el puerto 443, se funde visualmente con el HTTPS legítimo de media Internet.
bash# Nodo A: servidor udp2raw (escucha en TCP:443 y entrega a WireGuard UDP)
udp2raw -s \
--listen 0.0.0.0:443 \
--target 127.0.0.1:51820 \
--key "clave-compartida" \
--cipher-mode xor \
--auth-mode simple \
--raw-mode faketcp
# Nodo B: cliente udp2raw (conecta al Nodo A TCP:443 y expone UDP local)
udp2raw -c \
--listen 127.0.0.1:51820 \
--target <IP_NODO_A>:443 \
--key "clave-compartida" \
--cipher-mode xor \
--auth-mode simple \
--raw-mode faketcp
Con udp2raw corriendo, WireGuard en el nodo B apunta a 127.0.0.1:51820 — su extremo local — sin saber que cada paquete realmente cruza la red convertido en TCP falso hacia el puerto 443 del nodo A, uno de esos puertos que sobreviven incluso a las redes más quisquillosas.
Configuración de WireGuard: enrutamiento selectivo
En el nodo B hay un matiz decisivo: la directiva AllowedIPs. No quiero volcar todo el tráfico al túnel (0.0.0.0/0); solo interesa alcanzar la IP privada del nodo A:
ini# WireGuard en Nodo B: solo enruta la IP privada del Nodo A
[Peer]
PublicKey = <CLAVE_PUBLICA_NODO_A>
Endpoint = 127.0.0.1:51820
AllowedIPs = 10.100.0.1/32
PersistentKeepalive = 25
⚠
¿Por qué no enrutar todo por el túnel?
Volcar toda la salida del nodo B hacia el nodo A provocaría dos efectos indeseados a la vez: (1) el tráfico saliente delataría la IP real del nodo A, y (2) se perdería la opción de usar un proxy residencial independiente para esa salida. El enrutamiento selectivo mantiene ambos canales en carriles separados: entrada por el túnel, salida por el proxy.
15. Entrada de tráfico: redirección con iptables (DNAT)
Que un cliente externo alcance los servicios del nodo B sin conocer su IP se resuelve con reglas de iptables en el nodo A que ejecutan DNAT de los puertos de entrada hacia las IPs y puertos correspondientes dentro del túnel:
bash# Nodo A: redirección de puertos hacia el túnel WireGuard
iptables -t nat -A PREROUTING -p tcp --dport 80 \
-j DNAT --to-destination 10.100.0.2:80
iptables -t nat -A PREROUTING -p tcp --dport 443 \
-j DNAT --to-destination 10.100.0.2:443
iptables -t nat -A PREROUTING -p tcp --dport 5522 \
-j DNAT --to-destination 10.100.0.2:22
El recorrido de una conexión entrante queda así: Internet → Nodo A:80 → [DNAT] → 10.100.0.2:80 (Nodo B) . Gracias al MASQUERADE en POSTROUTING, el nodo B percibe la petición como venida de la IP privada del nodo A; para el cliente externo, la única IP que ha existido nunca es la del nodo A.
16. Salida de tráfico: proxy residencial y DNS blindado
Cuando es el nodo B quien inicia conexiones hacia Internet, necesita borrar su propia IP del mapa. Tres componentes encadenados:
dnscrypt-proxy: DNS sobre HTTPS (DoH)
Configurado como resolver DNS contra Cloudflare sobre HTTPS, escucha en 127.0.0.1:5353 y obliga todas las consultas a circular por TCP. Las fugas DNS por UDP desaparecen y los nombres viajan siempre cifrados. Como el tráfico TCP de dnscrypt-proxy acaba capturado por redsocks, las consultas DNS también salen por el proxy residencial.
dnsmasq: forwarder local
Reenviador sencillo hacia dnscrypt-proxy escuchando en 127.0.0.1:53. Como /etc/resolv.conf apunta a 127.0.0.1, todas las aplicaciones adoptan este resolver local sin configurar nada.
redsocks: transproxy SOCKS5
Daemon a la escucha en 127.0.0.1:12345 que transforma cualquier tráfico TCP redirigido a ese puerto en conexiones SOCKS5 hacia el proxy residencial. Los parámetros llegan dinámicamente desde una API externa:
conf# redsocks.conf (valores obtenidos dinámicamente vía API)
redsocks {
local_ip = 127.0.0.1;
local_port = 12345;
ip = <IP_PROXY_RESIDENCIAL>;
port = <PUERTO_SOCKS5>;
type = socks5;
login = "<USUARIO>";
password = "<PASSWORD>";
}
iptables: redirección selectiva a redsocks
En la tabla nat creo la cadena REDSOCKS_TCP: manda hacia el puerto local de redsocks todo el TCP saliente — salvo el destinado al propio proxy, el dirigido a redes privadas y el SSH. Las sesiones administrativas quedan fuera del proxy y se evitan bloqueos accidentales.
bash# Reglas clave de redirección en Nodo B
iptables -t nat -N REDSOCKS_TCP
iptables -t nat -A REDSOCKS_TCP -d <IP_PROXY> -j RETURN
iptables -t nat -A REDSOCKS_TCP -p tcp --dport 22 -j RETURN
iptables -t nat -A REDSOCKS_TCP -p tcp -j REDIRECT --to-ports 12345
iptables -t nat -A OUTPUT -p tcp -j REDSOCKS_TCP
Recorrido de una conexión saliente: Nodo B (aplicación) → [iptables REDSOCKS_TCP] → redsocks → proxy SOCKS5 residencial → Internet. El destino ve la IP del proxy residencial; ni el nodo B ni el nodo A aparecen. Este detalle es crítico en contextos de threat intelligence e investigación de campañas activas , donde una IP de origen inoportuna basta para alertar al adversario.
17. Control de acceso y firewall mínimo
Ambos nodos llevan UFW con política por defecto cerrada:
Nodo Puertos permitidos (entrada) Propósito
Nodo A 22/tcp, 80/tcp, 443/tcp, 5522/tcp SSH administrativo, HTTP/S redirigidos, SSH alternativo para túnel
Nodo B 22/tcp Únicamente SSH administrativo directo
El nodo B puede permitirse no exponer el 51820/udp porque el túnel lo establece udp2raw en dirección nodo B → nodo A: una conexión saliente, nunca entrante. La superficie de ataque queda reducida al mínimo sin sacrificar la gestión.
18. Automatización del despliegue en 90 segundos
Desde la instalación de dependencias hasta la verificación final, todo cabe en un script bash que completa el ciclo en torno a 90 segundos:
Instalación de dependencias: WireGuard, iptables, UFW, udp2raw (compilado desde fuente), redsocks, dnsmasq, dnscrypt-proxy, jq, curl.
WireGuard + udp2raw en Nodo A: claves, servicio systemd para udp2raw en modo servidor y reenvío de paquetes habilitado.
WireGuard + udp2raw en Nodo B: claves, servicio udp2raw en modo cliente y WireGuard con enrutamiento selectivo.
Vinculación de peers: intercambio de claves públicas y alta del peer en el servidor.
DoH + proxy de salida: dnscrypt-proxy contra Cloudflare solo-TCP, dnsmasq como forwarder, proxy residencial por API y redsocks con sus reglas.
Verificación: conectividad bidireccional, test de un servidor web a través del túnel y confirmación de que la IP de salida es la del proxy residencial.
⚙
Infraestructura como código (IaC)
El script es apenas el primer escalón hacia una gestión declarativa. La evolución lógica es convertirlo en playbook de Ansible o módulo de Terraform — camino que ya se explora en el laboratorio SOC con despliegue IaC , complemento defensivo natural de esta arquitectura.
19. Mejoras futuras y líneas de trabajo
Failover con IPs adicionales: contratar IPs extra en el proveedor del nodo A para alta disponibilidad; con dos IPs ya cabe un balanceador inverso (nginx/HAProxy) repartiendo conexiones entrantes.
Monitorización y alertas: Zabbix u homólogo para detectar caídas del túnel o fallos del proxy, avisando por Telegram, Slack o correo.
Enrutamiento por proceso: tabla de rutas aparte con reglas de política (ip rule) para que solo el tráfico de procesos concretos pase por el proxy; evita que apt o curl filtren información sin querer.
Infraestructura como código: migrar todo a un playbook Ansible o cloud-init capaz de reconstruir la infraestructura desde cero en minutos si un nodo cae comprometido o toca escalar.
20. Conclusión: una base sólida para operaciones que requieren anonimato
Este diseño resuelve a la vez varios dolores clásicos: exposición de IPs, bloqueo de VPN por DPI, fugas DNS y trazabilidad de la salida. La pareja «nodo de entrada + nodo de servicios», unida al túnel ofuscado y al proxy residencial independiente, constituye una base firme para operaciones donde el anonimato y la resiliencia no son opcionales. Automatizar el despliegue completo recorta el error humano y permite replicar la infraestructura exacta en minutos.
Y sobre este túnel descansa todo lo demás que publico: cada triaje de malware del laboratorio con analystty , cada campaña analizada en la recopilación de threat hunting y cada deconstrucción de infraestructura criminal salió de un entorno blindado exactamente por esta arquitectura.
21. Referencias