يظهر عَرَضان في الحلقة نفسها من VpnService ويُنسبان إلى الشيء نفسه: قارئ لا يعود أبدا، وكتابة تفشل بـ ENOBUFS. وهما ليسا صورتين لخلل واحد. القراءة المتوقفة خلاف حول التحكم في التدفق مع النظير؛ والكتابة الفاشلة حزمة لا تقبلها الواجهة. إذا تعاملت معهما كمشكلة واحدة فستنفق يوما في ضبط مخازن مؤقتة لم تكن طرفا أصلا. التقسيم أدناه هو كيف أقرر أي نصف من الحلقة أراقب أولا.

حلقة واحدة، نقطتا فشل مستقلتان

تقرأ خدمتك حزمة IP من واصف ملف TUN، وتفحصها، وتكتب ردا إلى الواصف نفسه. كل ما ينكسر في هذا المسار يظهر عند أحد هذين النداءين، ولهذا يُبلَّغ عن الاثنين بأن النفق معطل. للنداءين عقدان مختلفان. القراءة تنتظر أن يسلّمك النواة حزمة، والكتابة تسلّم النواة حزمة يُسمح لها برفضها.

القراءات هي النصف الأسهل في التفكير. القراءة التي لا تعيد شيئا إما تنتظر حركة مرور لا تصل أبدا أو تنتظر لأن النظير توقف عن الإرسال.

القراءة المتوقفة خلاف في التحكم في التدفق

قراءة جهاز TUN تحجب حتى تتوفر حزمة. هذا سلوك مصمم، ولهذا يبدو خيط متوقف داخل read طبيعيا على رابط خامل. يصبح تعليقا عندما يواصل مكدس TCP الخاص بك قبول البيانات من التطبيق المحلي لكنه لا يعلن نافذة كافية للنظير البعيد ليرسل المزيد. يملأ النظير النافذة التي أعلنتها، وينتظر ACK وتحديث نافذة، ثم يتوقف. حينها لا يجد قارئك شيئا يعيده، ويرى التطبيق اتصالا مفتوحا صامتا.

الأسباب الشائعة هي مكدس يكتب في المقبس دون تتبع النافذة المعلنة، وآخر ينسى إرسال تحديث نافذة بعد تفريغ مخزنه. من الخارج يبدوان متطابقين: تخرج البايتات، لا يعود شيء، ولا يُرفع أي خطأ. حجب خيط القراءة عند التحليل أو تحليل DNS أو إدخال وإخراج القرص ينتج الشكل نفسه من الأعراض لسبب غير ذي صلة، لذا تأكد أن الخيط داخل read فعلا قبل لوم التحكم في التدفق.

افحص قائمة انتظار الإرسال عند النظير والنافذة التي رآها آخر مرة. إذا كان النظير يحتفظ ببيانات لأن نافذتك صفر، فالإصلاح في مسار ACK لديك، لا في قراءة TUN.

ENOBUFS مشكلة حجم، لا نقص في المخزن المؤقت

الكتابة التي تعيد ENOBUFS على واجهة TUN ترفض عادة طول الحزمة. للواجهة MTU، والحزمة الأكبر منه لا يمكن وضعها في الطابور، وإعادة محاولة الحزمة نفسها تفشل بالطريقة نفسها في كل مرة. هذه الحتمية هي الدليل. نقص المخزن الحقيقي يزول مع انخفاض الضغط، أما رفض الحجم فلا يهمه كم تنتظر.

يملك TCP آلية لهذا بالضبط، وهي الخطوة التي يتجاوزها الناس: تقييد MSS. عندما تصنع المقاطع في فضاء المستخدم فأنت تختار حجم الحمولة، واختياره من MTU الواجهة المحلية بدلا من MTU النفق يخرج مقاطع لا يستطيع النفق حملها. قيّد إلى الأصغر منهما. التقييد يغطي TCP فقط، لذا يجب تقطيع حزمة UDP الكبيرة أو إسقاطها بواسطة شفرتك.

سجّل طول كل حزمة تكتبها أثناء التصحيح. الطول الذي يفشل هو الجواب، ولن يتغير بين المحاولات.

ثلاثة قياسات تفصل الحالات

لا تحتاج إلى مصحح لأي من الفشلين. ثلاث ملاحظات تكفي لتوجيه نفسك إلى القسم الصحيح، وهي تستغرق وقتا أقل من إعادة بناء.

What you seeWhere to look
Reader parked, peer send queue empty, last advertised window zeroWindow updates in your ACK path
Write fails on one length and succeeds on a smaller oneMSS clamp and tunnel MTU
Both directions look fine, app still sees no dataProtected socket and routing loop

إذا طابق الصف الثالث، فالحلقة نفسها سليمة والمشكلة حيث لا يراها النفق: مقبس نقل غير محمي يحمل حركة VPN الخاصة بك عائدة إلى النفق، وهو يظهر عادة كاتصال ينجح ثم لا يسلّم شيئا.

أصلح السباكة التي يعتمد عليها المساران

لا يستحق أي من العَرَضين المطاردة قبل بناء الواجهة بشكل صحيح. نداءات الباني المهمة هي العنوان والمسار وMTU والموافقة، بهذا الترتيب:

Builder()
  .addAddress(10.8.0.2, 32)
  .addRoute(0.0.0.0, 0)
  .setMtu(1400)
  .establish()

اضبط MTU على القيمة الحقيقية للنفق بدلا من تركها على ما استخدمه المثال. كل ما تكتبه لاحقا محدود بذلك الرقم، وعدم التوافق بين MTU الذي تضبطه وMSS الذي تقيّد به هو أكثر طريقة شائعة لإعادة خطأ الكتابة بعد إصلاح. ثم احمِ المقبس الذي يحمل حركة المرور إلى خادم VPN نفسه. بدون protect تُوجَّه تلك الحزم إلى نفقك الخاص ولا يكتمل الاتصال أبدا، وهو ما يبدو كقراءة متوقفة لكنه حلقة توجيه.

لا يمكن تجاوز الموافقة. الخدمة التي تبدأ دون أن يعيد prepare قيمة null لا تحصل على واجهة، وestablish يعيد null بدلا من أن يرمي، لذا افحص الواصف قبل بدء الحلقة. مرجع VpnService هو المكان لتأكيد عقد الباني بدلا من نسخ مثال.

تحقق من اتجاه واحد في كل مرة

أرسل صدى UDP عبر النفق وراقب أطوال الحزم قبل أن تلمس TCP. ثم افتح مصافحة وتأكد أن المقاطع تبقى تحت MSS الذي حسبته. عُدّ الحزم لا الاتصالات، ليظهر التوقف كثغرة في العداد بدلا من مقبس معلق. إذا توقفت القراءات بعد دفعة من الكتابات، فالنافذة هي المشتبه بها؛ وإذا فشلت الكتابات فورا، فالطول هو.

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

مقالات ذات صلة