Connexions API avec IPv6

Suivi de : Connexion API via IPv6 vs. IPv4 - support - Discourse Meta

J’ai récemment mis à niveau Node.js de 18 à 20 et mon application a soudainement cessé de recevoir de réponses API de Discourse. Il m’a fallu un certain temps pour comprendre que cela était lié au problème mentionné ci-dessus. J’ai vérifié cela en établissant une connexion uniquement via IPv4, comme ceci :

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

La partie importante étant la spécification de l’agent HTTP - je l’utilisais sans cela auparavant. Cela fonctionne maintenant, mais j’essayais de migrer hors d’Axios, afin de pouvoir utiliser d’autres bibliothèques basées sur fetch comme Wretch (principalement pour réduire la taille du bundle en l’utilisant également sur le frontend) : elbywan/wretch: A tiny wrapper built around fetch with an intuitive syntax. :candy: (github.com). Cependant, il n’y a pas d’option pour spécifier IPv4 ou IPv6 avec fetch. Ainsi, j’ai pensé que je devais soit :

  1. Forcer l’utilisation d’IPv4 uniquement d’une manière ou d’une autre et malgré toutes mes tentatives jusqu’à présent, cela n’a pas été possible.
  2. Vérifier avec Discourse comment je pourrais faire fonctionner cela sur IPv6.

Je me connecte à diverses autres API depuis mon application, aucune n’a ce problème, seule la connexion avec Discourse échoue.

Voici l’erreur que je reçois, au cas où cela aiderait :

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
}

Ce qui est intéressant, c’est que, contrairement au fil de discussion mentionné ci-dessus, je n’obtiens pas de réponse après un long moment. Mon appel échoue immédiatement avec cette erreur. L’appel API fonctionne bien dans le navigateur, curl et tout autre outil que je peux tester.

Ma façon de faire une requête à l’API n’a pas d’importance tant que je fais une requête depuis mon application. Cela échoue simplement et ne fonctionne qu’en utilisant l’option family mentionnée ci-dessus. Dans le fil de discussion lié, je vois ceci mentionné :

Vous devrez enquêter sur la raison pour laquelle les connexions IPv6 ne fonctionnent pas sur votre réseau.

J’ai 2 préoccupations à ce sujet :

  1. Je ne sais pas comment vérifier cela spécifiquement.
  2. Je ne suis pas sûr pourquoi ce serait un problème uniquement avec Discourse, et uniquement avec mon application.
1 « J'aime »

Un autre point à noter est que cela ne se produit qu’à l’intérieur de mon instance WSL. Si j’exécute mon application directement sur mon appareil Windows hôte, elle parvient à se connecter sans problème.

Je sais que c’est probablement quelque chose de très spécifique à ma configuration, mais je ne sais tout simplement pas où chercher les problèmes pour le moment. Toute indication serait utile !

1 « J'aime »

Il semble que la bibliothèque que vous utilisez tente des connexions sur IPv4 et IPv6 ; c’est une bonne nouvelle et cela signifie que vous n’avez pas le même problème qu’ici !

Abordons-les séparément :

Cela signifie que votre côté a envoyé un TCP SYN pour tenter la connexion à l’instance hébergée, mais n’a reçu aucune réponse. Cela signifie généralement l’une des choses suivantes :

  • la requête n’a pas atteint le serveur
  • le serveur (ou quelque chose sur le chemin) l’a délibérément ignorée silencieusement
  • la réponse n’est pas revenue à votre machine

Puisque

c’est probablement un problème avec la configuration réseau de votre machine.

Cela signifie que votre pile réseau a dit “Je ne peux pas y aller” et c’est bien puisque ce que vous utilisez se rabat visiblement sur IPv4.

En examinant tout, je suspecte :

  • IPv4 échoue depuis votre machine (il n’est pas clair si c’est vrai, veuillez vérifier - “il est capable de se connecter sans problème” pourrait signifier qu’il utilise IPv4 ou IPv6)
  • IPv4 échoue depuis votre conteneur WSL
  • IPv6 fonctionne depuis votre machine
  • IPv6 échoue depuis votre conteneur WSL

Veuillez envoyer une note à @team avec votre adresse IPv4 externe et nous vérifierons si elle est délibérément ignorée - nous avons effectivement bloqué certaines plages IP mal comportées et cela nous permettra de l’exclure.

Si, cependant, IPv4 et IPv6 fonctionnent depuis votre machine mais échouent depuis votre conteneur WSL, c’est quelque chose que vous devrez résoudre avec votre configuration WSL.

Merci beaucoup pour votre retour.

Concernant vos suspects, voici ce que j’ai pu tester jusqu’à présent :

  • J’ai essayé de désactiver l’IPv6 depuis les paramètres de Windows :

Ce qui, d’après ma compréhension, devrait permettre uniquement les connexions depuis l’IPv4. Si c’est le cas, cela a fonctionné.

  • J’ai essayé d’exécuter :
 curl -4 https://<host>/latest.json?order=created

depuis WSL et cela a bien fonctionné (j’ai obtenu la réponse).

  • Je ne suis pas sûr de la manière de tester uniquement l’IPv6 car dès que je désactive l’IPv4, de la même manière que l’IPv6 dans la capture d’écran ci-dessus (tout en laissant l’IPv6 activé), mon PC s’est essentiellement déconnecté d’Internet - toutes les connexions ont échoué, ce qui était prévisible.

  • J’ai essayé :

 curl -6 https://<host>/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

depuis WSL et cela a échoué… instantanément.

J’ai rencontré quelques problèmes avec WSL aujourd’hui, j’ai donc fini par configurer une nouvelle installation. Il s’agit d’une toute nouvelle instance avec simplement asdf et Node.js installés (et tous les paquets système mis à jour). Je ne suis pas sûr que cela soit toujours lié à une mauvaise configuration du côté de WSL - je devrais utiliser tous les paramètres par défaut actuellement.

Je partage mon adresse IPv4 publique avec le groupe mentionné.

Tant pis, je ne vois pas encore de moyen d’envoyer un message privé, probablement parce que je suis un nouvel utilisateur.

Quelque chose de plus intéressant… lorsque je vérifiais mon adresse IPv4 publique, le site web a tenté de m’afficher également mon adresse IPv6 et a indiqué “IPv6 non détecté”. J’ai donc vérifié si j’avais une connexion IPv6, et j’ai trouvé cette page : Comment configurer le service IPv6 sur le routeur sans fil TP-Link

Elle indique que les routeurs devraient avoir une section dédiée pour utiliser l’IPv6. Mon routeur n’en a pas et je n’ai pas non plus l’option PPPoE v6 comme indiqué. Il est donc possible que mon routeur ne prenne pas en charge l’IPv6 du tout, ce qui pourrait expliquer pourquoi les connexions IPv6 échouent (et aussi pourquoi j’ai essentiellement perdu la connectivité Internet lorsque j’ai désactivé l’IPv4 dans les paramètres de Windows).

EDIT : J’ai ce routeur TL-WR841N | Routeur Wi-Fi N 300 Mbps | TP-Link Inde et il est indiqué qu’il prend en charge l’IPv6 :thinking:

EDIT2 : Mais en utilisant quelque chose comme : v6.testmyipv6.com, j’obtiens ERR_NAME_NOT_RESOLVED, donc il semble que l’IPv6 ne fonctionne effectivement pas pour moi.

Si c’est le problème, je ne comprends toujours pas pourquoi cela a commencé à se produire soudainement. Cela fonctionnait bien pendant un certain temps.

Je vous ai donné un petit coup de pouce. :slight_smile: Vous devriez voir le bouton de message si vous cliquez maintenant sur @team. :+1:

1 « J'aime »

Merci, envoyé !

1 « J'aime »

Point de données supplémentaire, j’ai basculé vers le partage de connexion de mon réseau mobile qui utilise IPv6. Je peux maintenant vérifier en utilisant :

curl -6 https://<host>/latest.json?order=created -v
*   Tentative de connexion à 2602:fd3f:3:ff01::2b:443...
* Échec de connexion immédiat pour 2602:fd3f:3:ff01::2b: Réseau inaccessible
* Fermeture de la connexion 0
curl: (7) Impossible de se connecter au serveur

échoue toujours de manière similaire. Cependant, avec IPv4 désactivé dans les paramètres de Windows, je peux accéder à Internet contrairement à avant. Donc, nouvelles données :

  • IPv4 sur Windows : Fonctionne
  • IPv6 sur Windows : Fonctionne
  • IPv4 sur WSL : Fonctionne
  • IPv6 sur WSL : Échoue

Si je ne spécifie pas -4 ou -6 à curl, il revient à IPv4 (IPv6 échoue immédiatement) :

curl https://<host>/latest.json?order=created -v
*   Tentative de connexion à 184.105.99.43:443...
*   Tentative de connexion à 2602:fd3f:3:ff01::2b:443...
* Échec de connexion immédiat pour 2602:fd3f:3:ff01::2b: Réseau inaccessible
* Connecté à <host> (184.105.99.43) port 443 (#0)

J’ai également exécuté :

ping -6 google.com

Depuis Windows ainsi que depuis WSL. Cela fonctionne sous Windows, échoue sous WSL. Je pense avoir maintenant suffisamment d’informations et de validation pour dire que quelque chose ne va pas avec la connectivité IPv6 de mon instance WSL. Semble être un problème : cannot reach ipv6 only address · Issue #4518 · microsoft/WSL (github.com)

Enfin !

Sur la base de la discussion liée ci-dessus, j’ai pu ajouter

[experimental]
networkingMode=mirrored

à .wslconfig et cela m’a donné une connectivité IPv6 à l’intérieur de mon instance WSL. Je peux maintenant exécuter avec succès :

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

Cela ne fonctionne toujours pas sur mon WiFi, et c’est très probablement parce que ce vieux routeur ne prend pas en charge l’IPv6. Cela fonctionne bien lorsque j’utilise le partage de connexion de mon téléphone.

Merci beaucoup @JammyDodger pour les indices, vous m’avez mis sur la bonne voie !

OK, donc quelque chose a manifestement changé entre le post original et celui-ci, puisque vous obteniez :

Heureux de voir que cela fonctionne maintenant.

Ouais, ça me laisse toujours perplexe. Comme je l’ai mentionné précédemment, j’étais capable d’envoyer une requête curl via WSL auparavant et cela fonctionnait. D’une manière ou d’une autre, cela échouait en utilisant Axios dans mon application (peut-être est-ce un problème avec Axios ou Node.js ?).

D’une manière ou d’une autre, curl -4 fonctionne toujours, et Axios fonctionne également lorsque je spécifie httpFamily comme indiqué dans mon message d’origine. Mais ce n’est pas une erreur pour laquelle je vais perdre le sommeil.

Juste pour vérifier, j’ai rebasculé sur Node.js 18 et j’ai pu me connecter sans spécifier httpFamily, donc c’est définitivement quelque chose qui a changé dans Node.js 19 ou 20. Mais grâce à cela, j’ai au moins découvert cette histoire d’IPv6, sinon je n’aurais toujours pas cherché ou appris cela.

Je suis également capable d’exécuter le code avec bun au lieu de Node.js sans avoir à spécifier le truc IPv4. J’ai contacté Node.js : https://github.com/orgs/nodejs/discussions/50826