Problema
En muchos homelabs el acceso externo se hace a través de un VPS que actúa como punto de entrada. El VPS abre los puertos 80/443, crea un túnel WireGuard hacia la red doméstica y reenvía el tráfico a un reverse proxy (Nginx, HAProxy, etc.) que ya está gestionando los contenedores Docker. El inconveniente típico es que, al usar NAT (por ejemplo iptables -t nat -A POSTROUTING -j MASQUERADE) en el VPS, la dirección IP que llega al reverse proxy es la del túnel, no la del cliente original.
Esto impide que herramientas de seguridad basadas en IP, como CrowdSec, identifiquen y bloqueen a los atacantes, y también dificulta los logs de auditoría. La solución debe conservar la IP real del cliente mientras se mantiene la arquitectura de túnel y el reverse proxy centralizado.
Causa
- Masquerade NAT – Cuando el VPS reenvía paquetes a través del túnel, el origen se reescribe con la IP del extremo WireGuard. El reverse proxy solo ve esa IP y no puede distinguir entre usuarios legítimos y malos.
- Forwarding a nivel L4 – Un simple
iptables -j DNATo-j REDIRECTactúa antes de que el tráfico HTTP sea inspeccionado, por lo que no hay capa 7 disponible para CrowdSec. - Falta de Proxy Protocol o Real‑IP – Los servidores web pueden recibir la IP original si el balanceador la incluye en un encabezado o en el Proxy Protocol, pero el reverse proxy debe estar configurado para leerlo.
- Configuración de WireGuard – Si la directiva
AllowedIPsdel peer del VPS está limitada a la subred del reverse proxy, el tráfico de clientes externos nunca llega al túnel con su IP original.
Solución
1. Mantener la IP del cliente con Proxy Protocol
El método más limpio es que el VPS envíe el tráfico a través de HAProxy (o Nginx con listen ... proxy_protocol) y habilite el PROXY protocol. HAProxy conserva la IP original en la cabecera binaria y la pasa al reverse proxy que, a su vez, la interpreta mediante el módulo real_ip de Nginx.
Paso a paso
- Instala HAProxy en el VPS y configúralo como punto de entrada único.
- Habilita el modo
tcpconsend-proxy-v2. - En el reverse proxy (Nginx) activa
real_ip_header proxy_protocol;y define la lista de IPs de confianza (el IP del VPS).
Esta arquitectura permite que CrowdSec se ejecute en el VPS (captura eventos L7) y también en el reverse proxy (analiza logs de Nginx) sin perder la IP original.
2. Alternativa: Nginx + real_ip + X-Forwarded-For
Si prefieres evitar HAProxy, puedes dejar que el VPS haga DNAT sin masquerade y que Nginx añada el encabezado X-Forwarded-For. El cliente necesita que el VPS conserve la IP original en el paquete, lo que se logra con:
iptables -t nat -A PREROUTING -p tcp -d <VPS_PUBLIC_IP> --dport 80 -j DNAT --to-destination <HOME_IP>:80
iptables -t nat -A PREROUTING -p tcp -d <VPS_PUBLIC_IP> --dport 443 -j DNAT --to-destination <HOME_IP>:443
iptables -A FORWARD -p tcp -d <HOME_IP> --dport 80 -j ACCEPT
iptables -A FORWARD -p tcp -d <HOME_IP> --dport 443 -j ACCEPT
En Nginx del hogar:
set_real_ip_from <VPS_PUBLIC_IP>;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Con esta configuración, CrowdSec en el hogar recibe la IP real y puede actuar. La desventaja es que el VPS ya no puede inspeccionar tráfico L7; solo actúa como router.
3. Ejecutar CrowdSec en ambos extremos
Para máxima cobertura:
- VPS: instala CrowdSec con el bouncer
httppara bloquear peticiones antes de que entren al túnel. - Home Reverse Proxy: instala CrowdSec con el bouncer
nginxpara bloquear a nivel de aplicación y registrar intentos de fuerza bruta.
Los dos bouncers comparten la misma base de decisiones mediante el collection de crowdsec (por ejemplo, usando la API de CrowdSec). Así, una IP baneada en el VPS se replica automáticamente en el hogar.
4. Evitar doble terminación SSL
Si el VPS ya termina TLS (certificado válido), no es necesario volver a hacerlo en el reverse proxy. Configura HAProxy/Nginx en modo TCP passthrough (mode tcp) y deja que el reverse proxy haga la terminación solo para los servicios que lo requieran (por ejemplo, Vaultwarden). Esto reduce la carga de CPU y elimina la complejidad de certificados duplicados.
Cuándo aplicar esta solución
- Preservar IP real es crítico: auditorías, listas de bloqueo, o cualquier herramienta que dependa de la IP del cliente.
- CrowdSec o cualquier WAF está en uso y necesita datos de capa 7.
- El homelab tiene un VPS de salto por CGNAT o restricciones de ISP.
- Se desea centralizar la gestión de certificados en el VPS para evitar duplicación.
No es necesario si:
- Solo se exponen servicios internos a la LAN y no hay acceso externo.
- La política de seguridad no requiere bloqueo por IP (por ejemplo, autenticación basada en tokens).
- El rendimiento del VPS es limitado y no puede ejecutar HAProxy o CrowdSec simultáneamente.
Código
# VPS: instalar HAProxy
apt-get update && apt-get install -y haproxy
# /etc/haproxy/haproxy.cfg (fragmento esencial)
frontend wg_frontend
bind *:80 accept-proxy
bind *:443 accept-proxy ssl crt /etc/haproxy/certs/vps.pem
mode tcp
default_backend wg_backend
backend wg_backend
mode tcp
server home_proxy <HOME_WG_IP>:80 send-proxy-v2
server home_proxy_ssl <HOME_WG_IP>:443 send-proxy-v2
# Home Nginx (reverse proxy) – habilitar Proxy Protocol
listen 80 proxy_protocol;
listen 443 ssl proxy_protocol;
set_real_ip_from <VPS_PUBLIC_IP>;
real_ip_header proxy_protocol;
real_ip_recursive on;
# Ejemplo de bloque server
server {
server_name vaultwarden.example.com;
location / {
proxy_pass http://vaultwarden:80;
}
}
Verificación
- Comprobar la IP en los logs
curl -s http://<HOME_PUBLIC_IP>/ipinfo # El log debe mostrar la IP pública del cliente, no la del VPS. - CrowdSec: generar una regla de prueba que bloquee una IP y observar que el bloqueo ocurre tanto en el VPS como en el hogar.
- HAProxy: usar
haproxyctl show infopara confirmar queaccept-proxyestá activo y que los contadores de conexiones aumentan al hacer peticiones externas. - TLS: ejecutar
openssl s_client -connect <VPS_PUBLIC_IP>:443 -servername vaultwarden.example.comy verificar que el certificado corresponde al VPS (si se termina allí) o al servicio interno (si se pasa).
Notas adicionales
- Firewall en el VPS: permite solo los puertos 80/443 desde Internet y bloquea todo lo demás hacia la interfaz WireGuard.
- MTU: los túneles WireGuard pueden requerir ajuste de MTU (por ejemplo, 1420) para evitar fragmentación que rompa el Proxy Protocol.
- Sincronización de decisiones CrowdSec: usa la API de CrowdSec (
cscli bouncers add) para que ambos agentes compartan la misma lista de IP baneadas. - Monitorización: agrega un panel de Grafana que muestre métricas de HAProxy (
haproxy_exporter) y de CrowdSec (crowdsec_exporter) para detectar picos de ataques. - Backup de configuraciones: versiona los archivos
haproxy.cfgy los bloquesnginx.confcon Git; cualquier cambio en la lista deset_real_ip_fromdebe replicarse rápidamente.