VPN WireGuard en pfSense: acceso remoto seguro a un clúster Kubernetes, paso a paso
\nMuchas infraestructuras comienzan con algunos puertos abiertos \"solo por ahora\": un RDP para la VM de soporte, un SSH para el servidor de aplicaciones, un puerto de la API de Kubernetes. Lo provisional se vuelve permanente y el borde de la red se convierte en una lista de excepciones que nadie revisa.
\nEn este artículo mostramos, con un caso real anonimizado, cómo sustituir ese modelo por una VPN WireGuard en pfSense, conectar un cliente Linux y liberar el acceso a un clúster Kubernetes de homologación. También mostramos la resolución de problemas que apareció en el camino. Los problemas reales enseñan más que el guion ideal.
\nEl escenario
\n-
\n
- \n
Firewall: pfSense CE 2.8.1, funcionando como VM, con IP público directo en la WAN.
\n
- \n
Red interna:
10.20.0.0/16, gateway10.20.0.1(el propio pfSense). \n
- \n
Destino del acceso: un clúster Kubernetes de homologación (3 control-planes, 3 workers) y un Nginx de borde que publica el portal (
443) y la API de Kubernetes (6443). \n
- \n
Cliente: un escritorio Linux (Linux Mint Debian Edition, base Debian 13) en otra ciudad, detrás de un router doméstico común.
\n
- \n
Situación anterior: acceso mediante port forwards en la WAN (RDP y SSH abiertos a cualquier origen) y mediante un gateway de acceso remoto web.
\n
Objetivo: acceder a la red interna y al clúster como si el cliente estuviera en el sitio, sin exponer servicios administrativos en internet.
\nTopología
\nflowchart LR\n subgraph Remoto[\"Cliente remoto\"]\n C[\"Desktop Linux<br/>LAN 192.168.1.0/24<br/>wg0: 10.200.0.2/32\"]\n end\n subgraph Site[\"Site principal\"]\n FW[\"pfSense<br/>WAN: 203.0.113.10<br/>LAN: 10.20.0.1/16<br/>tun_wg0: 10.200.0.1/24\"]\n NG[\"nginx-proxy<br/>10.20.0.10<br/>:443 portal · :6443 API\"]\n M[\"k8s-master-01..03<br/>10.20.0.21-23\"]\n W[\"k8s-worker-01..03<br/>10.20.0.31-33\"]\n end\n C -- \"UDP 51820<br/>(WireGuard)\" --> FW\n FW --> NG\n FW --> M\n FW --> W\n
\n\nRegla de oro del direccionamiento: la red del túnel no puede colisionar con la LAN del firewall ni con la red desde la que se conecta el cliente. Rangos como
\n10.200.0.0/24suelen quedar fuera de las redes domésticas y corporativas más comunes.
Por qué WireGuard (y cuándo preferir OpenVPN)
\npfSense ofrece OpenVPN, IPsec y WireGuard. Para este caso, con un operador y pocos dispositivos, WireGuard ganó con holgura:
\nResumen: WireGuard para administradores, pocos dispositivos y site-to-site. OpenVPN cuando hay muchos usuarios, requisito de MFA o autenticación centralizada, o clientes en redes que bloquean UDP.
\nParte 1: configurando pfSense
\n1.1 Instalar el paquete
\nSystem → Package Manager → Available Packages, busque wireguard y haga clic en Install → Confirm. Espere a que el log termine con Success.
1.2 Crear el túnel
\nVPN → WireGuard → Tunnels → Add Tunnel
\nSave Tunnel → Apply Changes.
\n\n\n¿Túnel asignado o no? Para acceso remoto simple, no es necesario asignar el túnel a una interfaz. La dirección queda en el propio túnel y las reglas van en la pestaña WireGuard del firewall. Asignar la interfaz solo es necesario en escenarios con gateway, enrutamiento por política o NAT por interfaz.
\n
1.3 Habilitar el servicio
\nVPN → WireGuard → Settings → ☑ Enable WireGuard → Save → Apply Changes. Mantenga Hide Secrets activado para que las claves privadas no queden visibles en la interfaz.
\n1.4 Registrar el cliente (peer)
\nPara este paso, necesita la clave pública del cliente, generada en la Parte 2. En la práctica, genere las claves en el cliente y vuelva aquí.
\nVPN → WireGuard → Peers → Add Peer
\nEl campo Allowed IPs del lado del servidor tiene doble función: filtra qué IPs de origen se aceptan de ese peer y define hacia qué peer se enruta el tráfico destinado a esa IP. Use un /32 exclusivo por cliente.
1.5 Reglas de firewall
\nRegla 1: permitir WireGuard en la WAN (Firewall → Rules → WAN → Add)
\nRegla 2: permitir el tráfico que sale del túnel (Firewall → Rules → WireGuard → Add)
\nSin la segunda regla, el túnel establece el handshake normalmente, pero todo el tráfico hacia la LAN se bloquea. Este es uno de los errores más comunes.
\nParte 2: configurando el cliente Linux
\n2.1 Instalación
\nsudo apt update\nsudo apt install wireguard wireguard-tools resolvconf -y\n
El resolvconf permite que wg-quick aplique la directiva DNS = de la configuración.
2.2 Generar las claves en el propio cliente
\nsudo -i\ncd /etc/wireguard\numask 077\nwg genkey | tee cliente.key | wg pubkey > cliente.pub\ncat cliente.pub # chave PÚBLICA → cadastre no peer do pfSense\n
\n\nBuena práctica de seguridad: genere la clave privada en el dispositivo que va a usarla. Nunca debe viajar por correo electrónico, chat, ticket o por la interfaz del firewall. El
\numask 077garantiza que solo root pueda leer los archivos.
2.3 Archivo de configuración
\nEl siguiente comando crea /etc/wireguard/wg0.conf e inyecta la clave privada directamente desde el archivo, sin copiar y pegar:
cat > /etc/wireguard/wg0.conf <<EOF\n[Interface]\nPrivateKey = $(cat /etc/wireguard/cliente.key)\nAddress = 10.200.0.2/32\nDNS = 10.20.0.1\n\n[Peer]\nPublicKey = <CHAVE_PUBLICA_DO_SERVIDOR>\nEndpoint = 203.0.113.10:51820\nAllowedIPs = 10.200.0.0/24, 10.20.0.0/16\nPersistentKeepalive = 25\nEOF\nchmod 600 /etc/wireguard/wg0.conf\n
2.4 Levantar y validar
\nwg-quick up wg0\nwg show\n
El resultado esperado es este:
\npeer: <CHAVE_PUBLICA_DO_SERVIDOR>\n endpoint: 203.0.113.10:51820\n allowed ips: 10.200.0.0/24, 10.20.0.0/16\n latest handshake: 20 seconds ago\n transfer: 9.23 KiB received, 7.54 KiB sent\n persistent keepalive: every 25 seconds\n
Los dos indicadores que importan:
\n-
\n
- \n
latest handshakepresente significa que el túnel fue negociado; \n
- \n
received> 0 significa que el servidor está respondiendo. \n
ping -c 4 10.200.0.1 # pfSense pelo túnel\nping -c 4 10.20.0.1 # pfSense pela LAN\n
En nuestro caso, la latencia se mantuvo estable en torno a 29 ms entre las dos ciudades, con 0% de pérdida.
\nParte 3: lo que salió mal (y cómo lo resolvimos)
\nUn guion sin problemas enseña poco. Estos fueron los cuatro tropiezos reales de esta implantación, en orden.
\nProblema 1: sin handshake, 0 B received
\n
El túnel subía en el cliente, pero wg show no mostraba latest handshake y los pings fallaban.
Causa: el endpoint tenía un dígito equivocado en la IP pública. Se había transcrito de una captura de pantalla en baja resolución y los paquetes iban a otra dirección.
\nCorrección:
\nsed -i 's/<IP_ERRADO>/203.0.113.10/' /etc/wireguard/wg0.conf\nwg-quick down wg0 && wg-quick up wg0\n
Lección: copie la IP de la WAN como texto, en Status → Interfaces en pfSense. Nunca transcriba de una imagen. WireGuard no da error cuando el destino es incorrecto: simplemente no recibe respuesta.
\nProblema 2: \"¿será que estoy probando desde dentro de la red?\"
\nAntes de culpar al firewall, confirme desde dónde sale el cliente. Probar una VPN desde dentro de la propia LAN que protege genera falsos negativos debido al hairpin NAT y al conflicto de rutas.
\nip -4 -br addr # IP local do cliente\ncurl -4 -s ifconfig.me # IP público de saída\n
Si la IP local está en la LAN remota o la IP pública es la del propio firewall, la prueba no es válida. Use otra red, como el 4G del móvil, por ejemplo.
\nProblema 3: el puerto 443 funciona, el puerto 6443 da No route to host
\n
Con la VPN activa, el portal en el Nginx de borde respondía, pero la API de Kubernetes, en el mismo host, devolvía No route to host inmediatamente.
Diagnóstico: si un puerto del host responde, la ruta está correcta. Un No route to host instantáneo es la firma de un firewall local (firewalld, por defecto) rechazando con icmp-host-prohibited. Los hosts aceptaban la LAN (10.20.0.0/16), pero no el origen de la VPN (10.200.0.0/24).
Había dos caminos:
\nPara un entorno de homologación, elegimos el NAT.
\nFirewall → NAT → Outbound
\n-
\n
- \n
Cambie el modo a Hybrid Outbound NAT → Save.
\n
- \n
Agregue un mapeo:
\n
-
\n
- \n
Save → Apply Changes y limpie los estados antiguos en Diagnostics → Command Prompt:
\n
pfctl -k 10.200.0.2\n
Resultado: nc -vz 10.20.0.10 6443 pasó a devolver succeeded.
\n\nErrores comunes en esa pantalla: dejar Address Family en IPv4+IPv6, elegir WAN address en lugar de LAN address en la traducción (los hosts verían la IP pública), o escribir la descripción en el campo Port or Range.
\n
\n\nPara producción: prefiera liberar el origen de la VPN en los hosts, por ejemplo
\nfirewall-cmd --permanent --zone=trusted --add-source=10.200.0.0/24. Así se preserva la trazabilidad de quién accedió a qué.
Problema 4: los nodos del clúster no responden
\nIncluso con el NAT, el ping y el SSH a los masters fallaban. Antes de tocar cualquier otra cosa, aislamos el problema probando desde el propio pfSense:
\nping -c 2 -S 10.20.0.1 10.20.0.21; nc -vz -w 3 10.20.0.21 22\n
El pfSense tampoco alcanzaba el nodo. Entonces el problema no era la VPN. La causa era la más simple posible: las VMs del clúster estaban apagadas.
\nLección: antes de ajustar el túnel, verifique si el propio firewall alcanza el destino. Si ni siquiera él lo alcanza, la VPN queda fuera de la ecuación.
\nÁrbol de decisión
\nSem handshake?\n ├─ Endpoint e porta corretos?\n ├─ Chaves públicas trocadas corretamente (cliente ↔ servidor)?\n ├─ Regra UDP 51820 na WAN, acima de bloqueios?\n └─ Diagnostics → Packet Capture (WAN, UDP 51820) mostra pacotes?\n ├─ Não → IP errado, CGNAT, roteador da operadora na frente, UDP bloqueado na origem\n └─ Sim → chaves ou serviço WireGuard desabilitado\n\nHandshake ok, mas sem acesso?\n ├─ Regra na aba WireGuard liberando a rede do túnel?\n ├─ AllowedIPs do cliente inclui a rede de destino?\n ├─ O próprio pfSense alcança o destino?\n │ └─ Não → destino desligado, outra VLAN/bridge, firewall do host\n └─ Sim → firewall do host filtrando a origem → Outbound NAT ou liberar a origem no host\n
Parte 4: accediendo a Kubernetes por la VPN
\nCon el túnel activo y los nodos encendidos:
\nmkdir -p ~/.kube\nscp [email protected]:/etc/kubernetes/admin.conf ~/.kube/config-homolog\nexport KUBECONFIG=~/.kube/config-homolog\nkubectl get nodes -o wide\n
Si aparece x509: certificate is valid for ..., la dirección en server: no está en los SAN del certificado del apiserver. Apunte a la IP de un master o incluya la IP del balanceador en los SAN del certificado.
Resultados
\nUn detalle importante de WireGuard para quienes cuidan la seguridad: no responde a paquetes que no estén autenticados con una clave conocida. Para un escáner en internet, el puerto 51820 parece cerrado. Es una reducción real de la superficie de ataque en comparación con RDP o SSH expuestos.
\nGobernanza: lo que no puede faltar
\nConfigurar la VPN es la parte fácil. Para que siga siendo segura dentro de un año:
\n-
\n
- \n
Cierre lo que la VPN sustituyó. Valide el acceso equivalente por el túnel y luego desactive los port forwards antiguos. VPN más puertos abiertos es solo un puerto abierto más.
\n
- \n
Inventario de peers. Mantenga una tabla con IP del túnel, dispositivo, responsable y fecha. Peer sin dueño es peer a revocar.
\n
- \n
Una clave por dispositivo, generada en el dispositivo. Nunca reutilice claves entre máquinas ni transmita claves privadas.
\n
- \n
Menor privilegio. Sustituya el Destination: Any de la regla del túnel por alias con las redes y puertos realmente necesarios.
\n
- \n
Trazabilidad. En producción, evite el NAT entre la VPN y la LAN para que los logs de los servidores identifiquen al cliente. Esto pesa en auditorías y en requisitos de LGPD.
\n
- \n
Pre-shared key. Agregar una PSK por peer es sencillo y añade una capa extra de protección, incluso contra amenazas criptográficas futuras.
\n
- \n
DDNS. Si la WAN tiene IP dinámica, use un hostname en el
Endpointpara que la VPN no se detenga cuando el operador cambie la IP. \n
- \n
Backup de la configuración. Después de cualquier cambio: Diagnostics → Backup & Restore.
\n
Referencia rápida
\npfSense
\nPacote ............ WireGuard\nTúnel ............. tun_wg0 · 51820/UDP · 10.200.0.1/24\nPeer .............. admin-desktop · dynamic · 10.200.0.2/32\nRegra WAN ......... Pass UDP any → WAN address:51820\nRegra WireGuard ... Pass any 10.200.0.0/24 → (redes necessárias)\nOutbound NAT ...... Hybrid · LAN · 10.200.0.0/24 → 10.20.0.0/16 → LAN address (opcional, homologação)\n
Cliente Linux
\nwg-quick up wg0 # conectar\nwg-quick down wg0 # desconectar\nwg show # status / handshake\nsystemctl enable --now wg-quick@wg0 # subir no boot\n
¿Necesita apoyo con su infraestructura?
\nNyverra Tecnología trabaja con infraestructura, seguridad de borde, virtualización y monitoreo para empresas de los sectores de salud, industria y servicios. Hacemos desde la revisión de exposición en internet hasta el diseño de acceso remoto auditable. Hable con nosotros a través de [email protected].
Seguir leyendo
Lea también
TutoriaisManual LSI / Broadcom MegaRAID — MegaCli y StorCLI
Con esta guía, su equipo gana autonomía para diagnosticar rebuilds, resolver foreign configurations, gestionar BBU y CacheCade — con escenarios reales de producción documentados.
20 min de leitura
Nginx Cheatsheet
Guía de bolsillo con ejemplos listos para configurar Nginx en producción: desde instalación y virtual hosts hasta ajuste de rendimiento y resolución de problemas.
12 min de leitura
KubernetesCurso Kubernetes 27 — SLO/SLI, on-call y postmortem sin culpa
Qué prometer, cómo medir y qué hacer cuando el error se dispara: SLI, SLO, presupuesto de error, alertas que despiertan a alguien y postmortem sin caza de brujas.
5 min de leitura
Comentarios
Aún sin comentarios
Sea el primero en compartir su opinión sobre este artículo.

Deje un comentario