API-Verbindungen mit IPv6

Nachverfolgung von: API-Verbindung über IPv6 vs. IPv4 - Support - Discourse Meta

Ich habe kürzlich Node.js von 18 auf 20 aktualisiert und meine Anwendung erhielt plötzlich keine API-Antwort mehr von Discourse. Es dauerte eine Weile, bis ich herausfand, dass es mit dem oben genannten Problem zusammenhing. Ich habe dies verifiziert, indem ich eine Verbindung nur über IPv4 hergestellt habe, wie zum Beispiel:

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

Der wichtige Teil ist die Angabe des HTTP-Agents – ich habe ihn vorher ohne verwendet. Das funktioniert jetzt, aber ich habe versucht, von Axios wegzukommen, damit ich andere fetch-basierte Bibliotheken wie Wretch verwenden kann (hauptsächlich, um die Bundle-Größe zu reduzieren, indem ich diese auch im Frontend verwende): elbywan/wretch: A tiny wrapper built around fetch with an intuitive syntax. :candy: (github.com). Allerdings gibt es keine Option, IPv4 oder IPv6 mit fetch anzugeben. Daher habe ich festgestellt, dass ich entweder:

  1. Erzwingen muss, nur IPv4 zu verwenden, und trotz all meiner bisherigen Versuche war dies nicht möglich.
  2. Mit Discourse prüfen muss, wie ich dies mit IPv6 zum Laufen bringen kann.

Ich verbinde mich von meiner Anwendung aus mit verschiedenen anderen APIs, keine davon hat dieses Problem, nur die Verbindung mit Discourse schlägt fehl.

Dies ist die Fehlermeldung, die ich erhalte, falls sie hilfreich ist:

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
}

Interessanterweise erhalte ich, im Gegensatz zum oben genannten Thread, keine Antwort nach langer Zeit. Mein Aufruf schlägt sofort mit dieser Fehlermeldung fehl. Der API-Aufruf funktioniert im Browser, mit curl und allem anderen, was ich testen kann.

Die Art und Weise, wie ich eine Anfrage an die API stelle, spielt keine Rolle, solange ich eine Anfrage aus meiner Anwendung stelle. Sie schlägt einfach fehl und funktioniert nur durch die Verwendung der oben genannten Familienoption. Im verlinkten Thread sehe ich Folgendes erwähnt:

Sie müssen untersuchen, warum IPv6-Verbindungen in Ihrem Netzwerk nicht funktionieren.

Ich habe damit 2 Bedenken:

  1. Ich weiß nicht, wie ich das speziell überprüfen kann.
  2. Ich bin mir nicht sicher, warum dies nur mit Discourse und nur mit meiner Anwendung ein Problem sein sollte.
1 „Gefällt mir“

Ein weiterer Punkt, den man beachten sollte: Dies geschieht nur innerhalb meiner WSL-Instanz. Wenn ich meine Anwendung direkt auf meinem Host-Windows-Gerät ausführe, kann sie problemlos eine Verbindung herstellen.

Ich weiß, dass dies wahrscheinlich etwas sehr Spezifisches für mein Setup ist, aber ich weiß im Moment einfach nicht, wo ich nach Problemen suchen soll. Jeder Hinweis wäre hilfreich!

1 „Gefällt mir“

Es sieht so aus, als ob die von Ihnen verwendete Bibliothek versucht, Verbindungen über IPv4 und IPv6 herzustellen. Das sind gute Nachrichten und bedeutet, dass Sie nicht dasselbe Problem haben wie hier!

Lassen Sie uns sie getrennt betrachten:

Das bedeutet, dass Ihre Seite ein TCP-SYN gesendet hat, um die Verbindung zur gehosteten Instanz zu versuchen, aber keine Antwort erhalten hat. Das bedeutet im Allgemeinen eines der folgenden:

  • Die Anfrage hat den Server nicht erreicht
  • Der Server (oder etwas auf dem Weg) hat sie absichtlich stillschweigend verworfen
  • Die Antwort hat Ihre Maschine nicht erreicht

Da

handelt es sich wahrscheinlich um ein Problem mit der Netzwerkkonfiguration auf Ihrem Computer.

Das bedeutet, dass Ihr Netzwerk-Stack gesagt hat: “Ich kann da nicht hin” und das ist in Ordnung, da das, was Sie verwenden, offensichtlich auf IPv4 zurückfällt.

Wenn man sich alles ansieht, vermute ich:

  • IPv4 schlägt von Ihrem Computer aus fehl (es ist nicht klar, ob dies zutrifft, bitte überprüfen Sie - “es kann sich problemlos verbinden” könnte bedeuten, dass es entweder IPv4 oder IPv6 verwendet)
  • IPv4 schlägt von Ihrem WSL-Container aus fehl
  • IPv6 funktioniert von Ihrem Computer aus
  • IPv6 schlägt von Ihrem WSL-Container aus fehl

Bitte senden Sie eine Notiz an @team mit Ihrer externen IPv4-Adresse, und wir werden prüfen, ob sie absichtlich verworfen wird - wir haben einige schlecht funktionierende IP-Bereiche blockiert, und dies wird uns helfen, dies auszuschließen.

Wenn jedoch sowohl IPv4 als auch IPv6 von Ihrem Computer aus funktionieren, aber von Ihrem WSL-Container aus fehlschlagen, ist dies etwas, das Sie im Zusammenhang mit Ihrer WSL-Einrichtung lösen müssen.

Vielen Dank für Ihre Rückmeldung.

Bezüglich Ihrer Verdächtigen konnte ich bisher Folgendes testen:

  • Ich habe versucht, IPv6 in den Windows-Einstellungen zu deaktivieren:

Was meiner Meinung nach Verbindungen nur über IPv4 ermöglichen sollte. Wenn ja, hat das funktioniert.

  • Ich habe versucht, Folgendes auszuführen:
 curl -4 https://<host>/latest.json?order=created

aus WSL und es hat gut funktioniert (ich habe die Antwort erhalten).

  • Ich bin mir nicht sicher, wie ich nur IPv6 testen kann, denn sobald ich IPv4 ähnlich wie IPv6 aus dem obigen Screenshot deaktiviere (während IPv6 aktiviert bleibt), wurde mein PC praktisch vom Internet getrennt – alle Verbindungen schlugen fehl, was zu erwarten war.

  • Ich habe Folgendes versucht:

 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

aus WSL und das ist fehlgeschlagen … sofort.

Ich hatte heute einige Probleme mit WSL und habe daher eine frische Installation konfiguriert. Dies ist eine brandneue Instanz, auf der nur asdf und Node.js installiert sind (und alle Systempakete aktualisiert wurden). Ich bin mir nicht sicher, ob dies immer noch mit einer Fehlkonfiguration auf der WSL-Seite zusammenhängt – ich sollte derzeit alle Standardeinstellungen verwenden.

Ich teile meine öffentliche IPv4-Adresse mit der genannten Gruppe.

Nun, ich sehe noch keine Möglichkeit, eine private Nachricht zu senden, wahrscheinlich weil ich ein neuer Benutzer bin.

Etwas Interessanteres… Als ich meine öffentliche IPv4-Adresse überprüfte, versuchte die Website, mir auch meine IPv6-Adresse anzuzeigen und sagte: IPv6 nicht erkannt. Also ging ich daran, zu prüfen, ob ich überhaupt eine IPv6-Verbindung habe, und fand diese Seite: How to set up IPv6 service on the TP-Link wireless router

Dort steht, dass Router einen speziellen Bereich zur Nutzung von IPv6 haben sollten. Mein Router hat keinen und ich bekomme auch nicht die dort gezeigte PPPoE v6-Option. Vielleicht unterstützt mein Router also gar kein IPv6 – was erklären könnte, warum IPv6-Verbindungen fehlschlagen (und auch, warum ich im Grunde die Internetverbindung verlor, als ich IPv4 in den Windows-Einstellungen deaktivierte).

EDIT: Ich habe diesen Router TL-WR841N | 300Mbps Wireless N Router | TP-Link India und dort steht, dass IPv6 unterstützt wird :thinking:

EDIT2: Aber wenn ich etwas wie v6.testmyipv6.com benutze, erhalte ich ERR_NAME_NOT_RESOLVED, also scheint IPv6 tatsächlich nicht für mich zu funktionieren.

Wenn das das Problem ist, weiß ich immer noch nicht, warum das plötzlich angefangen hat. Es hat einige Zeit lang gut funktioniert.

Ich habe dir einen kleinen Anstoß gegeben. :slight_smile: Du solltest jetzt den Nachrichtenbutton sehen, wenn du auf @team klickst. :+1:

1 „Gefällt mir“

Danke, gesendet!

1 „Gefällt mir“

Zusätzlicher Datenpunkt: Ich bin über den Hotspot meines Mobilfunknetzes, das IPv6 verwendet, verbunden. Ich kann dies nun verifizieren mit:

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

Es schlägt immer noch auf ähnliche Weise fehl. Wenn ich jedoch IPv4 in den Windows-Einstellungen deaktiviere, kann ich das Internet nutzen, im Gegensatz zu vorher. Neue Daten also:

  • IPv4 unter Windows: Funktioniert
  • IPv6 unter Windows: Funktioniert
  • IPv4 unter WSL: Funktioniert
  • IPv6 unter WSL: Schlägt fehl

Wenn ich bei curl nicht -4 oder -6 angebe, greift es auf IPv4 zurück (IPv6 schlägt sofort fehl):

curl https://<host>/latest.json?order=created -v
*   Trying 184.105.99.43:443...
*   Trying 2602:fd3f:3:ff01::2b:443...
* Immediate connect fail for 2602:fd3f:3:ff01::2b: Network is unreachable
* Connected to <host> (184.105.99.43) port 443 (#0)

Ich habe auch Folgendes ausgeführt:

ping -6 google.com

Sowohl unter Windows als auch unter WSL. Unter Windows funktioniert es, unter WSL schlägt es fehl. Ich denke, ich habe jetzt genügend Informationen und Bestätigungen, dass mit der IPv6-Konnektivität meiner WSL-Instanz etwas schiefgeht. Sieht nach einem Problem aus: cannot reach ipv6 only address · Issue #4518 · microsoft/WSL (github.com)

Endlich!

Basierend auf der oben verlinkten Diskussion konnte ich Folgendes zu .wslconfig hinzufügen:

[experimental]
networkingMode=mirrored

Dadurch erhielt ich IPv6-Konnektivität in meiner WSL-Instanz. Ich kann jetzt erfolgreich Folgendes ausführen:

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

In meinem WLAN funktioniert es jedoch immer noch nicht, was sehr wahrscheinlich daran liegt, dass dieser alte Router kein IPv6 unterstützt. Es funktioniert einwandfrei, wenn ich den Hotspot meines Telefons verwende.

Vielen Dank @JammyDodger für die Hinweise, Sie haben mich in die richtige Richtung gewiesen!

OK, also hat sich offensichtlich etwas zwischen dem ursprünglichen Beitrag und diesem hier geändert, da Sie Folgendes erhalten haben:

Ich freue mich zu sehen, dass es jetzt funktioniert.

Das ist mir immer noch ein Rätsel. Wie ich bereits erwähnt hatte, konnte ich zuvor eine Curl-Anfrage über WSL senden, und das funktionierte. Irgendwie schlug es mit Axios in meiner Anwendung fehl (vielleicht ist das eine Sache von Axios oder Node.js?).

Irgendwie funktioniert curl -4 immer noch, und Axios funktioniert auch, wenn ich httpFamily wie in meinem ursprünglichen Beitrag gezeigt angebe. Aber das ist kein Fehler, über den ich mir noch weiter den Schlaf rauben werde.

Nur zur Überprüfung, ich bin zu Node.js 18 zurückgekehrt und konnte eine Verbindung herstellen, ohne httpFamily angeben zu müssen. Das ist definitiv etwas, das sich in Node.js 19 oder 20 geändert hat. Aber dadurch habe ich zumindest von dieser IPv6-Sache erfahren, sonst hätte ich nie danach gesucht oder davon erfahren.

Ich kann den Code auch mit bun anstelle von Node.js ausführen, ohne die IPv4-Sache angeben zu müssen. Ich habe Node.js kontaktiert: https://github.com/orgs/nodejs/discussions/50826