اتصالات API مع IPv6

متابعة لـ: API connection via ipv6 vs. ipv4 - support - Discourse Meta

لقد قمت مؤخرًا بترقية Node.js من 18 إلى 20 وتوقف تطبيقي فجأة عن تلقي استجابة API من Discourse. استغرق الأمر مني بعض الوقت لمعرفة أنه كان مرتبطًا بالمشكلة المذكورة أعلاه. لقد تحققّت من ذلك عن طريق إجراء اتصال عبر IPv4 فقط مثل:

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
  })
})

الجزء المهم هو تحديد وكيل HTTP - كنت أستخدمه بدونه من قبل. هذا يعمل الآن، لكنني كنت أحاول التخلي عن Axios، حتى أتمكن من استخدام مكتبات أخرى تعتمد على fetch مثل Wretch (بشكل أساسي لتقليل حجم الحزمة عن طريق استخدامها في الواجهة الأمامية أيضًا): elbywan/wretch: A tiny wrapper built around fetch with an intuitive syntax. :candy: (github.com). ومع ذلك، لا يوجد خيار لتحديد IPv4 أو IPv6 باستخدام fetch. وبالتالي، توصلت إلى أنني بحاجة إما إلى:

  1. فرض استخدام IPv4 فقط بطريقة ما وعلى الرغم من كل محاولاتي حتى الآن، لم يكن هذا ممكنًا
  2. التحقق مع Discourse حول كيفية الحصول على هذا العمل على IPv6.

أنا أتصل بواجهات برمجة تطبيقات أخرى مختلفة من تطبيقي، ولا تواجه أي منها هذه المشكلة، إنها فقط الاتصال بـ Discourse هو الذي يفشل.

هذا هو الخطأ الذي أحصل عليه في حال كان مفيدًا:

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
}

المثير للاهتمام هو أنه على عكس الموضوع المذكور أعلاه، لا أحصل على استجابة بعد فترة طويلة. يفشل طلبي على الفور مع هذا الخطأ. يعمل استدعاء API بشكل جيد في المتصفح و curl وأي شيء آخر يمكنني اختباره.

لا يهم طريقتي في إجراء طلب إلى API طالما أنني أجري طلبًا من تطبيقي. إنه يفشل ببساطة ويعمل فقط باستخدام خيار العائلة كما هو مذكور أعلاه. في الموضوع المرتبط، أرى هذا مذكورًا:

ستحتاج إلى التحقيق في سبب عدم عمل اتصالات IPv6 على شبكتك.

لديّ قلقان بشأن ذلك:

  1. لا أعرف كيف أتحقق من ذلك على وجه التحديد.
  2. لست متأكدًا لماذا ستكون هذه مشكلة فقط مع Discourse، وفقط مع تطبيقي.
إعجاب واحد (1)

نقطة أخرى تجدر الإشارة إليها، يحدث هذا فقط داخل مثيل WSL الخاص بي. إذا قمت بتشغيل تطبيقي مباشرة على جهاز Windows المضيف الخاص بي، فيمكنه الاتصال بشكل جيد.

أعلم أن هذا على الأرجح شيء خاص جدًا بإعداداتي، لكنني ببساطة لا أعرف أين أبحث عن المشاكل الآن. أي إرشادات ستكون مفيدة!

إعجاب واحد (1)

يبدو أن المكتبة التي تستخدمها تحاول إنشاء اتصالات عبر كل من IPv4 و IPv6؛ وهذا خبر سار ويعني أنك لا تواجه نفس المشكلة الموجودة هنا!

دعنا نعالجها بشكل منفصل:

هذا يعني أن جانبك أرسل حزمة TCP SYN لمحاولة الاتصال بالمثيل المستضاف، ولكنه لم يتلق ردًا. هذا يعني بشكل عام أحد الأمور التالية:

  • لم يصل الطلب إلى الخادم
  • الخادم (أو شيء ما في المسار) أسقطه عمدًا بصمت
  • لم يعد الرد إلى جهازك

بما أن

فمن المحتمل أن تكون المشكلة في إعدادات الشبكة على جهازك.

هذا يعني أن مكدس الشبكة لديك قال “لا يمكنني الوصول إلى هناك” وهذا جيد بما أن ما تستخدمه يعود إلى IPv4 بشكل واضح.

بالنظر إلى كل شيء، أشك في:

  • فشل IPv4 من جهازك (ليس من الواضح ما إذا كان هذا صحيحًا، يرجى التحقق - قد يعني “يمكنه الاتصال بشكل جيد” أنه يستخدم IPv4 أو IPv6)
  • فشل IPv4 من حاوية WSL الخاصة بك
  • نجاح IPv6 من جهازك
  • فشل IPv6 من حاوية WSL الخاصة بك

يرجى إرسال ملاحظة إلى @team بعنوان IP الخارجي الخاص بك وسنتحقق مما إذا كان يتم إسقاطه عمدًا - لدينا بعض نطاقات IP سيئة السلوك محظورة وهذا سيتيح لنا استبعاد ذلك.

إذا، مع ذلك، نجح كل من IPv4 و IPv6 من جهازك ولكنهما فشلا من حاوية WSL الخاصة بك، فهذا شيء ستحتاج إلى حله فيما يتعلق بإعداد WSL الخاص بك.

شكراً جزيلاً على ردك.

بخصوص المشتبه بهم لديك، إليك ما تمكنت من اختباره حتى الآن:

  • حاولت تعطيل IPv6 من إعدادات Windows:

والذي، حسب فهمي، يجب أن يجعل الاتصالات من IPv4 فقط. إذا كان الأمر كذلك، فقد نجح ذلك.

  • حاولت تشغيل:
curl -4 https://<host>/latest.json?order=created

من WSL وعمل بشكل جيد (حصلت على الاستجابة).

  • لست متأكداً من كيفية اختبار IPv6 فقط لأنه بمجرد تعطيل IPv4، على غرار IPv6 من لقطة الشاشة أعلاه (مع ترك IPv6 قيد التشغيل)، تم فصل جهازي عن الإنترنت بشكل أساسي - فشلت جميع الاتصالات، وهو ما يمكن توقعه.

  • حاولت:

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

من WSL وفشل… على الفور.

واجهت بعض المشاكل مع WSL اليوم، لذلك انتهى بي الأمر بتكوين تثبيت جديد. هذه نسخة جديدة تمامًا مع تثبيت asdf و Node.js فقط (وجميع حزم النظام محدثة). لست متأكداً مما إذا كان هذا لا يزال متعلقاً ببعض التكوين الخاطئ في نهاية WSL - يجب أن أكون أستخدم جميع الإعدادات الافتراضية الآن.

أشارك عنوان IP العام الخاص بي IPv4 مع المجموعة المذكورة.

حسنًا، لا أرى طريقة لإرسال رسالة خاصة بعد، ربما لأنني مستخدم جديد.

شيء أكثر إثارة للاهتمام… عندما كنت أتحقق من عنوان IPv4 العام الخاص بي، حاول الموقع عرض عنوان IPv6 الخاص بي أيضًا وقال، لم يتم اكتشاف IPv6. لذلك، ذهبت للتحقق مما إذا كان لدي اتصال IPv6 على الإطلاق، ووجدت هذه الصفحة: How to set up IPv6 service on the TP-Link wireless router

توضح أن أجهزة التوجيه يجب أن تحتوي على قسم مخصص لاستخدام IPv6. جهاز التوجيه الخاص بي لا يحتوي على واحد، ولا أحصل على خيار PPPoE v6 كما هو موضح هناك. لذلك ربما، جهاز التوجيه الخاص بي لا يدعم IPv6 على الإطلاق - وهذا قد يكون سبب فشل اتصالات IPv6 (وأيضًا سبب فقداني لاتصال الإنترنت بشكل أساسي عندما قمت بتعطيل IPv4 في إعدادات Windows).

تحرير: لدي جهاز التوجيه هذا TL-WR841N | 300Mbps Wireless N Router | TP-Link India ويقول إنه يدعم IPv6 :thinking:

تحرير2: ولكن باستخدام شيء مثل: v6.testmyipv6.com يعطيني ERR_NAME_NOT_RESOLVED، لذلك يبدو أن IPv6 لا يعمل بالفعل بالنسبة لي.

إذا كانت هذه هي المشكلة، فلا أزال لا أعرف لماذا بدأ هذا في الحدوث فجأة. لقد كان يعمل بشكل جيد لبعض الوقت.

لقد أعطيتك دفعة صغيرة. :slight_smile: يجب أن ترى زر الرسالة إذا نقرت على @team الآن. :+1:

إعجاب واحد (1)

شكرا، تم الإرسال!

إعجاب واحد (1)

نقطة بيانات إضافية، لقد تحولت إلى نقطة اتصال من شبكتي المحمولة التي تستخدم IPv6. يمكنني الآن التحقق باستخدام:

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

لا يزال يفشل بطريقة مماثلة. ومع ذلك، مع تعطيل IPv4 في إعدادات Windows، يمكنني الوصول إلى الإنترنت على عكس ما كان عليه من قبل. لذا بيانات جديدة:

  • IPv4 على Windows: يعمل
  • IPv6 على Windows: يعمل
  • IPv4 على WSL: يعمل
  • IPv6 على WSL: يفشل

إذا لم أحدد -4 أو -6 لـ curl، فإنه يعود إلى IPv4 (يفشل IPv6 على الفور):

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)

لقد قمت أيضًا بتشغيل:

ping -6 google.com

من Windows وكذلك WSL. يعمل على Windows، ويفشل في WSL. أعتقد أن لدي الآن معلومات كافية وتأكيدًا على أن هناك خطأ ما يحدث مع اتصال IPv6 الخاص بمثيل WSL الخاص بي. يبدو أنها مشكلة: cannot reach ipv6 only address · Issue #4518 · microsoft/WSL (github.com)

أخيراً!

بناءً على المناقشة المرتبطة أعلاه، تمكنت من إضافة

[experimental]
networkingMode=mirrored

إلى .wslconfig وهذا منحني اتصال IPv6 داخل مثيل WSL الخاص بي. يمكنني الآن تشغيل:

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

بنجاح.

لا يزال الأمر لا يعمل على شبكة WiFi الخاصة بي، ومن المحتمل جدًا أن يكون ذلك بسبب أن هذا الموجه القديم لا يدعم IPv6. إنه يعمل بشكل جيد عند استخدام نقطة اتصال هاتفي.

شكراً جزيلاً لك @JammyDodger على التوجيهات، لقد وجهتني في الاتجاه الصحيح!

حسنًا، يبدو أن شيئًا ما قد تغير بين المنشور الأصلي وهذا، حيث كنت تحصل على:

يسعدني أن أرى أنه يعمل الآن.

نعم، هذا لا يزال يحيرني. كما ذكرت من قبل، كنت قادرًا على إرسال طلب curl عبر WSL حتى قبل ذلك وكان ذلك يعمل. بطريقة ما، كان يفشل باستخدام Axios في تطبيقي (ربما هذا شيء خاص بـ Axios أو Node.js؟).

بطريقة ما، لا يزال curl -4 يعمل، ويعمل Axios أيضًا عندما أحدد httpFamily كما هو موضح في منشوري الأصلي. لكن هذا ليس خطأ سأخسر المزيد من نومي بسببه.

فقط للتحقق من سلامة العقل، عدت إلى Node.js 18 وتمكنت من الاتصال دون تحديد httpFamily، لذا من المؤكد أن هذا شيء قد تغير في Node.js 19 أو 20. ولكن بسبب ذلك، اكتشفت على الأقل أمر IPv6 هذا، وإلا لما كنت قد بحثت أو تعلمت عن هذا.

أنا قادر أيضًا على تشغيل الكود باستخدام bun بدلاً من Node.js دون الحاجة إلى تحديد أمر IPv4. لقد تواصلت مع Node.js: https://github.com/orgs/nodejs/discussions/50826