Añadiste un host de retransmisión, pusiste su dirección de Nebula en una configuración y los dos pares siguen sin comunicarse. Eso ocurre porque una ruta de retransmisión necesita tres declaraciones separadas que coincidan, y solo una de ellas está en la máquina que probablemente editaste. Me he topado con esto dos veces: una en la que el host de reenvío nunca había recibido el rol de relé, y otra en la que los ajustes estaban escritos en el lado equivocado de la conexión. La secuencia siguiente comprueba el rol, el anuncio y el permiso en ese orden, y cada paso tiene un comando que te dice si debes continuar.

Distingue los tres roles antes de tocar una configuración

Nebula asigna una tarea a cada host, y esas tareas no se heredan. Un lighthouse responde a las preguntas de dónde está tal par para que los hosts puedan encontrarse. Un relé reenvía tráfico entre dos pares que no tienen una ruta directa operativa. Un host normal no hace ninguna de las dos cosas. Los tres ajustes que importan viven en tres máquinas distintas, y por eso una configuración de cliente que parece completa puede dejar a ambos pares esperando.

# on the discovery host
lighthouse:
  am_lighthouse: true
  hosts: []

# on every other host, point at the discovery host's Nebula address
lighthouse:
  hosts:
    - 10.42.0.1

Un solo síntoma separa las dos clases de fallo. Si ambos pares se listan entre sí y el registro muestra intentos de handshake que nunca se completan, el descubrimiento funciona y la ruta de datos está bloqueada por NAT o por un cortafuegos. Si un par nunca llega a conocer la dirección del otro, el problema está en el lighthouse o en su mapa estático de hosts, y los ajustes de relé no pueden arreglarlo.

Confirma qué configuración cargó realmente cada host antes de cambiar cualquier otra cosa. Una unidad que lee una ruta distinta del archivo que editaste es una causa común y bochornosa de que «el cambio no hiciera nada»:

systemctl cat nebula | grep ExecStart
nebula -version
journalctl -u nebula -n 20 --no-pager

La línea de versión importa en un parque mixto. El manejo de relés, el comportamiento del punching y las claves de configuración aceptadas no son idénticos entre versiones, así que no des por hecho que una compilación antigua entiende una sección para la que no se escribió. Alinea los hosts en la misma serie menor, ejecuta después nebula -test -config /etc/nebula/config.yml en cada host y compara la salida antes de depurar un transporte que el código no implementa.

Activa el rol de reenvío en el host de retransmisión

El rol de relé es un solo indicador en el host de reenvío, y es independiente de ser un lighthouse. Un host con el descubrimiento activado y el reenvío por relé desactivado sigue siendo solo un servicio de descubrimiento. En el relé:

relay:
  am_relay: true

Ese indicador declara una intención; no crea alcanzabilidad. Un relé tiene que ser alcanzable desde ambos pares, lo que en la práctica significa una dirección pública, UDP entrante en el puerto de Nebula abierto en el cortafuegos del host y en cualquier grupo de seguridad de la nube, y ningún NAT doble delante. Comprueba el socket en escucha y luego observa si llegan los paquetes del par:

ss -lunp | grep nebula
tcpdump -ni any udp port 4242 and host 198.51.100.7

Dos límites ahorran tiempo después. No se llega a un relé a través de otro relé, así que una cadena de nombres de relé en una configuración no sustituye a darle al host de reenvío una ruta utilizable. Y un relé reenvía paquetes; no concede permisos, las reglas de entrada del destino siguen decidiendo si se permite el flujo retransmitido. El rol y sus requisitos se describen en la documentación de configuración del relé.

Anuncia el relé desde el destino, no desde el cliente

Esta es la inversión que consume más horas. La lista de relés pertenece al host al que intentas llegar, porque indica a otros pares qué relés pueden usarse para alcanzar ese host. Ponerla en el cliente que inicia la conexión no aporta nada a la dirección que el cliente necesita:

# on the DESTINATION host: relays others may use to reach me
relay:
  relays:
    - 10.42.0.5

Los pares informan de esa lista junto con sus direcciones cuando se presentan ante el lighthouse, así que el anuncio se propaga mediante el descubrimiento y no mediante un intercambio directo. Si el destino no alcanza ningún lighthouse, su lista de relés nunca se difunde y un relé bien configurado permanece inactivo. Ese fallo se parece exactamente a un relé roto y no lo es.

Dale al destino una ruta de arranque en la misma pasada. El mapa estático de hosts vincula una dirección de Nebula a un extremo público para que el primer handshake tenga adónde ir, y necesita una entrada para el relé si el destino debe aceptar tráfico retransmitido de hosts a los que no puede llegar directamente:

static_host_map:
  "10.42.0.5": ["203.0.113.10:4242"]

Deja que el par que se conecta use el relé

El lado que inicia necesita su propio permiso. relay.use_relays está activo por defecto, así que el caso que merece buscarse es un false explícito, a menudo copiado de una plantilla escrita antes de que existiera la función de relé o dejado por un intento anterior de forzar rutas directas:

relay:
  use_relays: true

El permiso de este lado no es la única puerta. Las reglas de entrada del destino se siguen aplicando al paquete retransmitido, y la fuente con la que se comparan es la identidad dentro del túnel y no la dirección del propio relé. Cuando el handshake retransmitido termina y la aplicación sigue fallando, lee el registro del destino para ver qué fuente registró antes de reescribir una regla.

Los ajustes de travesía de NAT interactúan con todo esto. punchy.punch ayuda a dos pares a abrir una ruta directa, y cuando lo consigue no hay tráfico de relé que observar; eso es un éxito, no un relé ausente. Un par que funciona de forma intermitente suele significar que el punching acierta solo a veces, así que prueba ese par varias veces en lugar de sacar una conclusión de un solo intento.

Verifica con el par que falló y luego recarga

Prueba los dos hosts que realmente fallaron, con la aplicación que necesitan. Un ping correcto desde tu estación de trabajo al servicio del propio relé no demuestra nada sobre el reenvío entre otros dos pares, y es el falso positivo más común de todo este procedimiento.

journalctl -u nebula -f | grep -iE "relay|handshake"
ping -c 3 10.42.0.9

Recarga en lugar de reiniciar, y confirma que el proceso en marcha recogió el archivo que editaste. Un reinicio derriba todos los túneles y hace que la siguiente prueba sea más difícil de leer, mientras que un SIGHUP conserva el proceso y le hace releer la configuración:

sudo systemctl kill -s HUP nebula
# same signal when nebula runs in the foreground
kill -HUP $(pidof nebula)

systemctl reload solo funciona si la unidad local define ExecReload, y la unidad que se distribuye con el proyecto no lo hace, así que systemctl kill -s HUP es el paso que funciona en una instalación estándar. Tras la recarga, lee el journal para la ruta de configuración que abrió el proceso, para saber que se leyó el archivo nuevo y no el que suponías cargado.

Los ajustes de relé y el punching de NAT actúan ambos sobre la ruta; ninguno actúa sobre la identidad. Si el par sigue fallando el handshake una vez confirmados am_relay, relays y use_relays en la configuración en ejecución, comprueba que ambos hosts presentan certificados emitidos para los nombres con los que están configurados y que la CA es la misma en ambos lados. Mantén fija la configuración de certificados y cortafuegos mientras cambias un ajuste de transporte cada vez, porque una edición de certificado y una edición de relé en la misma prueba no te dicen cuál de las dos movió el handshake. Un desajuste de nombre o de CA falla en el mismo sitio que un relé que nunca se encontró, y por eso esta contracomprobación pertenece a la misma pasada.

Luego confirma que cada declaración está en el archivo al que pertenece:

  • am_relay: true en el host de reenvío, y ese host alcanzable por UDP desde ambos lados.
  • relays: con la dirección de Nebula de ese host en el destino.
  • use_relays: true en el par que inicia la conexión.
  • Reglas de entrada en el destino que siguen permitiendo la fuente real después del cambio de ruta.

Artículos relacionados