Problema

En entornos donde los nodos de Kubernetes dependen de un firewall/router como OPNsense, una configuración errónea del gateway DHCP o la ausencia de reglas de NAT saliente puede dejar al clúster sin acceso a Internet sin generar alertas visibles. Los síntomas típicos son:

  • Pods que no pueden descargar imágenes de contenedores aunque el DNS responda.
  • kubectl get pods muestra contenedores en estado ImagePullBackOff o CrashLoopBackOff.
  • Herramientas de diagnóstico dentro del nodo (por ejemplo ping a direcciones externas) fallan, mientras que el firewall sigue respondiendo a pings locales.
  • La red interna funciona (comunicación entre pods y servicios) pero cualquier tráfico que requiera salir del LAN se pierde.

Este patrón se repite en homelabs y pequeñas infraestructuras donde la configuración de red se gestiona de forma automática y los cambios de DHCP pueden pasar desapercibidos durante semanas.

Causa

1. Gateway DHCP incorrecto

Cuando la interfaz WAN de OPNsense está configurada para obtener su dirección mediante DHCP, el router aprende el “router option” que el servidor DHCP ofrece. Si ese servidor está mal configurado o es un dispositivo obsoleto, OPNsense puede registrar una IP de gateway que no corresponde al router real. El firewall seguirá enviando tráfico a esa IP, que normalmente responde con Destination Net Unreachable. El problema se mantiene oculto porque:

  • Los nodos internos no necesitan salir a Internet para la mayoría de sus operaciones diarias.
  • No hay alertas proactivas en OPNsense para un gateway que responde pero no enruta.

2. Regla de NAT saliente ausente

OPNsense genera reglas de NAT saliente de forma automática cuando el modo está en Automatic outbound NAT rule generation. En versiones específicas o con configuraciones de WAN inusuales, el motor de generación puede crear una tabla vacía. El resultado es que los paquetes con origen en la subred LAN (por ejemplo 192.168.60.0/24) salen sin ser masqueradeados, llegando a Internet con direcciones privadas que los routers de borde descartan.

3. Configuración de origen en reglas manuales

Al cambiar a Manual outbound NAT, OPNsense crea una regla predeterminada cuyo origen es “LAN address”. Ese valor se interpreta como la IP del propio firewall (p.ej. 192.168.60.1), no como la subred completa. Si no se ajusta, solo el tráfico originado por el firewall se NATea, mientras que los hosts LAN siguen sin salida.

Solución

Paso 1: Verificar el gateway aprendido

  1. Accede a la consola de OPNsense o a la interfaz web y revisa la tabla de rutas.
netstat -rn
  1. Busca la ruta 0.0.0.0/0. Si el Gateway apunta a una IP que no corresponde al router físico, corrígela.

  2. En la UI, navega a System → Gateways → Configuration, edita la entrada WAN_DHCP y escribe la IP correcta del router (p.ej. 10.20.0.1). Guarda y aplica.

  3. Opcionalmente, desactiva la opción “Obtain gateway via DHCP” y escribe la IP de forma estática para evitar futuros cambios inesperados.

Paso 2: Confirmar que el firewall tenga conectividad externa

ping -c3 1.1.1.1
dig +short ghcr.io

Si ambas pruebas responden, el DNS y la ruta están correctas.

Paso 3: Revisar y corregir NAT saliente

  1. En la UI, abre Firewall → NAT → Outbound.

  2. Cambia el modo a Manual outbound NAT. Esto permite inspeccionar y editar reglas explícitamente.

  3. Crea o edita la regla que cubra la subred LAN:

  • Interface: WAN
  • Source: 192.168.60.0/24 (usar “LAN net” del selector)
  • Translation / target: Interface address (masquerade)
  1. Guarda y aplica los cambios. OPNsense mostrará la regla en la tabla; verifica que el Source sea la subred completa, no solo la IP del firewall.

Paso 4: Reiniciar servicios críticos

Después de ajustar gateway y NAT, reinicia el resolvedor DNS interno (Unbound) y, si usas Talos o cualquier otro OS, recarga la configuración de red.

service unbound restart
# o, en sistemas basados en systemd
systemctl restart unbound

Paso 5: Validar el flujo de tráfico desde Kubernetes

Ejecuta un pod temporal que use una imagen ya cacheada (para evitar fallos de pull) y prueba la conectividad TCP al registro de contenedores.

kubectl run nettest -n kube-system --rm -i \
  --image=busybox:1.36 \
  --restart=Never \
  --overrides='{"spec":{"imagePullPolicy":"IfNotPresent","securityContext":{"runAsNonRoot":false}}}' \
  -- sh -c "nc -zvw5 20.207.73.86 443"

Una respuesta “open” indica que el NAT está funcionando y que los pods pueden alcanzar la Internet.

Cuándo aplicar esta solución

  • Síntomas de conectividad externa: pods en ImagePullBackOff, fallos de curl o wget desde dentro del clúster, pero DNS interno funciona.
  • Rutas estáticas sospechosas: la tabla de rutas muestra un gateway que no coincide con el router físico.
  • Reglas de NAT vacías: la sección Outbound NAT de OPNsense está en modo automático pero la tabla está en blanco.
  • Entornos con DHCP en la WAN: cuando la interfaz WAN depende de DHCP y el ISP o el switch de capa 2 provee opciones de router.

No aplicar si la infraestructura usa un router dedicado con rutas estáticas y NAT está gestionado por otro dispositivo (p.ej. un appliance de seguridad externo). En esos casos, la corrección debe hacerse en el dispositivo que realmente controla el tráfico saliente.

Código

# 1. Ver tabla de rutas en OPNsense
netstat -rn

# 2. Ping a un host externo para comprobar conectividad
ping -c3 1.1.1.1

# 3. Test DNS interno
dig +short ghcr.io

# 4. Reiniciar Unbound
service unbound restart

# 5. Test de conectividad TCP desde un pod
kubectl run nettest -n kube-system --rm -i \
  --image=busybox:1.36 \
  --restart=Never \
  --overrides='{"spec":{"imagePullPolicy":"IfNotPresent","securityContext":{"runAsNonRoot":false}}}' \
  -- sh -c "nc -zvw5 20.207.73.86 443"

Verificación

  1. Ruta y gateway: netstat -rn muestra 0.0.0.010.20.0.1 (o la IP real del router).
  2. NAT activo: en Firewall → NAT → Outbound, la tabla manual contiene una regla con Source 192.168.60.0/24 y Translation WAN address.
  3. Pod con acceso externo: el comando nc dentro del pod devuelve “open” y los pods pueden descargar imágenes nuevas sin ImagePullBackOff.
  4. Logs de OPNsense: revisa System → Log Files → Firewall para confirmar que los paquetes salientes aparecen como NAT y no como blocked.

Notas adicionales

  • Persistencia del gateway: si el ISP cambia la opción DHCP, mantén la IP del gateway estática en OPNsense. La mayoría de los firewalls permiten marcar la opción “Ignore DHCP gateway” o sobrescribirla manualmente.
  • Monitoreo proactivo: agrega una regla de alerta que dispare cuando la ruta por defecto cambie a una IP no esperada. Herramientas como Zabbix o Prometheus pueden consultar netstat -rn vía SNMP.
  • Versiones de OPNsense: versiones anteriores a 23.7 mostraron problemas con la generación automática de NAT en configuraciones de WAN con DHCP. Si usas una versión antigua, considera actualizar o forzar siempre el modo manual.
  • Documentación interna: registra la IP del router y la subred LAN en un wiki de homelab. Un cambio inesperado en DHCP es más fácil de detectar si hay una referencia clara de lo que “debería” estar configurado.