Conexiones API con IPv6

Seguimiento de: Conexión API vía ipv6 vs. ipv4 - support - Discourse Meta

Recientemente actualicé Node.js de 18 a 20 y mi aplicación de repente dejó de recibir respuestas de la API de Discourse. Me tomó un tiempo darme cuenta de que estaba relacionado con el problema anterior. Lo verifiqué haciendo una conexión solo a través de IPv4, como:

import {Agent} from 'node:https'
import axios from 'axios'
import {env} from 'node:process'
export const axiosDiscourse = axios.create({
  baseURL: 'https://<url-de-discourse>',
  headers: {
    'api-key': env['DISCOURSE_KEY'],
    'api-username': env['DISCOURSE_USERNAME']
  },
  httpsAgent: new Agent({
    family: 4
  })
})

la parte importante es especificar el Agente HTTP; lo estaba usando sin eso antes. Esto ahora funciona, pero estaba intentando migrar de Axios para poder usar otras bibliotecas basadas en fetch como Wretch (principalmente para reducir el tamaño del paquete usándolo también en el frontend): elbywan/wretch: A tiny wrapper built around fetch with an intuitive syntax. :candy: (github.com). Sin embargo, no hay opción para especificar IPv4 o IPv6 con fetch. Por lo tanto, pensé que necesitaba:

  1. Forzar el uso solo de IPv4 de alguna manera y, a pesar de todos mis intentos hasta ahora, esto no ha sido posible.
  2. Consultar con Discourse sobre cómo podría hacer que esto funcione en IPv6.

Estoy conectándome a varias otras APIs desde mi aplicación, ninguna tiene este problema, solo la conexión con Discourse está fallando.

Este es el error que estoy recibiendo en caso de que ayude:

Error: connect ETIMEDOUT 184.105.99.43:443
    at createConnectionError (node:net:1634:14)
    at Timeout.internalConnectMultipleTimeout (node:net:1685:38)
    at listOnTimeout (node:internal/timers:575:11)
    at processTimers (node:internal/timers:514:7) {
  errno: -110,
  code: 'ETIMEDOUT',
  syscall: 'connect',
  address: '184.105.99.43',
  port: 443
},
Error: connect ENETUNREACH 2602:fd3f:3:ff01::2b:443 - Local (:::0)
    at internalConnectMultiple (node:net:1176:40)
    at Timeout.internalConnectMultipleTimeout (node:net:1687:3)
    at listOnTimeout (node:internal/timers:575:11)
    at processTimers (node:internal/timers:514:7) {
  errno: -101,
  code: 'ENETUNREACH',
  syscall: 'connect',
  address: '2602:fd3f:3:ff01::2b',
  port: 443
}

Lo interesante es que, a diferencia del hilo mencionado anteriormente, no obtengo respuesta después de mucho tiempo. Mi solicitud falla inmediatamente con este error. La llamada a la API funciona bien en el navegador, curl y cualquier otra cosa que pueda probar.

Mi forma de hacer una solicitud a la API no importa siempre que esté haciendo una solicitud desde mi aplicación. Simplemente falla y solo funciona usando la opción family como se mencionó anteriormente. En el hilo enlazado, veo que se menciona esto:

Tendrás que investigar por qué las conexiones IPv6 no funcionan en tu red.

Tengo 2 preocupaciones con eso:

  1. No sé cómo verificar eso específicamente.
  2. No estoy seguro de por qué este sería un problema solo con Discourse y solo con mi aplicación.
1 me gusta

Otro punto a tener en cuenta es que esto solo sucede dentro de mi instancia de WSL. Si ejecuto mi aplicación directamente en mi dispositivo Windows anfitrión, puede conectarse sin problemas.

Sé que esto es probablemente algo muy específico de mi configuración, pero simplemente no sé dónde buscar problemas en este momento. ¡Cualquier indicación sería útil!

1 me gusta

Parece que la biblioteca que estás utilizando está intentando establecer conexiones tanto a través de IPv4 como de IPv6; ¡eso es una buena noticia y significa que no tienes el mismo problema que aquí!

Abordémoslos por separado:

Esto significa que tu lado envió un SYN de TCP para intentar la conexión a la instancia alojada, pero no recibió una respuesta. Eso generalmente significa una de estas cosas:

  • la solicitud no llegó al servidor
  • el servidor (o algo en el camino) la descartó deliberadamente en silencio
  • la respuesta no llegó a tu máquina

Dado que

es probable que sea un problema con la configuración de red de tu máquina.

Esto significa que tu pila de red dijo “no puedo llegar allí” y está bien, ya que lo que estás usando evidentemente recurre a IPv4.

Mirando todo, sospecho:

  • IPv4 falla desde tu máquina (no está claro si esto es cierto, por favor verifica - “puede conectarse bien” podría significar que está usando IPv4 o IPv6)
  • IPv4 falla desde tu contenedor WSL
  • IPv6 funciona desde tu máquina
  • IPv6 falla desde tu contenedor WSL

Por favor, envía una nota a @team con tu dirección IPv4 externa y comprobaremos si se está descartando deliberadamente; tenemos algunos rangos de IP mal comportados bloqueados y esto nos permitirá descartarlo.

Si, sin embargo, tanto IPv4 como IPv6 funcionan desde tu máquina pero fallan desde tu contenedor WSL, eso es algo que deberás resolver con respecto a tu configuración de WSL.

Muchas gracias por tu respuesta.

Con respecto a tus sospechas, esto es lo que he podido probar hasta ahora:

  • Intenté deshabilitar IPv6 desde la configuración de Windows:

Lo cual, según entiendo, debería hacer que las conexiones solo se realicen desde IPv4. Si es así, eso funcionó.

  • Intenté ejecutar:
 curl -4 https://\u003chost\u003e/latest.json?order=created

desde WSL y funcionó bien (obtuve la respuesta).

  • No estoy seguro de cómo puedo probar solo IPv6 porque tan pronto como deshabilito IPv4 de manera similar a IPv6 en la captura de pantalla anterior (mientras dejo IPv6 activado), mi PC básicamente se desconectó de Internet; todas las conexiones fallaron, lo cual era de esperar.

  • Intenté:

 curl -6 https://\u003chost\u003e/latest.json?order=created -v
*   Trying 2602:fd3f:3:ff01::2b:443...
* Immediate connect fail for 2602:fd3f:3:ff01::2b: Network is unreachable
* Closing connection 0
curl: (7) Couldn't connect to server

desde WSL y falló… instantáneamente.

Tuve algunos problemas con WSL hoy, así que terminé configurando una instalación nueva. Esta es una instancia completamente nueva con solo asdf y Node.js instalados (y todos los paquetes del sistema actualizados). No estoy seguro de si esto todavía está relacionado con alguna mala configuración en el extremo de WSL; debería estar usando todas las configuraciones predeterminadas en este momento.

Estoy compartiendo mi dirección IPv4 pública con el grupo mencionado.

Bueno, no veo una forma de enviar un mensaje privado todavía, probablemente porque soy un usuario nuevo.

Algo más interesante… cuando estaba comprobando mi dirección IPv4 pública, el sitio web intentó mostrarme también mi dirección IPv6 y dijo: IPv6 no detectado. Así que, procedí a comprobar si tenía una conexión IPv6, y encontré esta página: Cómo configurar el servicio IPv6 en el router inalámbrico TP-Link

Muestra que los routers deberían tener una sección dedicada para usar IPv6. Mi router no tiene una y tampoco obtengo la opción PPPoE v6 como se muestra allí. Así que tal vez, mi router no soporta IPv6 en absoluto, lo que podría ser la razón por la que las conexiones IPv6 están fallando (y también por qué básicamente perdí la conectividad a Internet cuando deshabilité IPv4 en la configuración de Windows).

EDIT: Tengo este router TL-WR841N | Router Inalámbrico N de 300 Mbps | TP-Link India y dice que soporta IPv6 :thinking:

EDIT2: Pero al usar algo como: v6.testmyipv6.com me da ERR_NAME_NOT_RESOLVED, así que parece que IPv6 de hecho no está funcionando para mí.

Si ese es el problema, todavía no sé por qué esto empezó a suceder de repente. Estuvo funcionando bien durante bastante tiempo.

Te he dado un pequeño empujón. :slight_smile: Deberías ver el botón de mensaje si haces clic en @team ahora. :+1:

1 me gusta

¡Gracias, enviado!

1 me gusta

Punto de datos adicional, cambié a hotspot desde mi red móvil que usa IPv6. Ahora puedo verificar usando:

curl -6 https://<host>/latest.json?order=created -v
*   Intentando 2602:fd3f:3:ff01::2b:443...
* Fallo de conexión inmediata para 2602:fd3f:3:ff01::2b: Red inalcanzable
* Cerrando conexión 0
curl: (7) No se pudo conectar al servidor

todavía falla de manera similar. Sin embargo, con IPv4 deshabilitado en la configuración de Windows, puedo acceder a Internet a diferencia de antes. Nuevos datos:

  • IPv4 en Windows: Funciona
  • IPv6 en Windows: Funciona
  • IPv4 en WSL: Funciona
  • IPv6 en WSL: Falla

Si no especifico -4 o -6 a curl, recurre a IPv4 (IPv6 falla inmediatamente):

curl https://<host>/latest.json?order=created -v
*   Intentando 184.105.99.43:443...
*   Intentando 2602:fd3f:3:ff01::2b:443...
* Fallo de conexión inmediata para 2602:fd3f:3:ff01::2b: Red inalcanzable
* Conectado a <host> (184.105.99.43) puerto 443 (#0)

También ejecuté:

ping -6 google.com

Tanto desde Windows como desde WSL. Funciona en Windows, falla en WSL. Creo que ahora tengo suficiente información y validación de que algo está saliendo mal con la conectividad IPv6 de mi instancia de WSL. Parece un problema: cannot reach ipv6 only address · Issue #4518 · microsoft/WSL (github.com)

¡Por fin!

Basándome en la discusión enlazada anteriormente, pude añadir

[experimental]
networkingMode=mirrored

a .wslconfig y eso me dio conectividad IPv6 dentro de mi instancia de WSL. Ahora puedo ejecutar con éxito:

curl -6 https://<host>/latest.json?order=created

Sin embargo, todavía no funciona en mi WiFi y es muy probable que sea porque este router antiguo no soporta IPv6. Funciona bien cuando uso el punto de acceso de mi teléfono.

¡Muchas gracias @JammyDodger por las indicaciones, me guiaste en la dirección correcta!

OK, así que algo cambió evidentemente entre la publicación original y esta, ya que estabas recibiendo:

Me alegra ver que ahora funciona.

Sí, eso todavía me desconcierta. Como mencioné antes, podía enviar una solicitud curl a través de WSL incluso antes y eso funcionaba. De alguna manera, estaba fallando usando Axios en mi aplicación (¿quizás eso es algo de Axios o de Node.js?).

De alguna manera, curl -4 todavía funciona, y Axios también funciona cuando especifico httpFamily como se muestra en mi publicación original. Pero ese no es un error por el que vaya a perder más sueño.

Solo para verificar, volví a Node.js 18 y pude conectarme sin especificar httpFamily, por lo que esto es definitivamente algo que ha cambiado en Node.js 19 o 20. Pero debido a eso, al menos me enteré de esta cosa de IPv6, o de lo contrario todavía no habría buscado ni aprendido sobre esto.

También puedo ejecutar el código con bun en lugar de Node.js sin tener que especificar lo de IPv4. Me he puesto en contacto con Node.js: https://github.com/orgs/nodejs/discussions/50826