الخلاصة

  • يحمل ALPN عرضاً مرتباً من معرفات معتمة يرسلها العميل، ثم يختار الخادم قيمة مشتركة واحدة. يحكم الاختيار بيانات التطبيق في اتصال TLS نفسه، لا وصلة أخرى ولا خاصية دائمة للخدمة.
  • يعمل الوكيل الذي ينهي TLS خادماً في اتجاه العميل، ثم يصبح عميلاً جديداً في اتجاه الأصل. يمكن أن يكون HTTP/2 صحيحاً في الوصلة الأولى وHTTP/1.1 صحيحاً في الثانية؛ لكل منهما دليل مستقل.
  • يثبت سجل IANA والإعداد ووجود callback إمكانية ما. أما دليل التشغيل فيربط العرض والاختيار أو الإنذار واستدعاء callback واكتمال المصافحة وبدء البروتوكول بمعرف اتصال محدد.

لم يكن التحويل هو العطل

في الوصلة الخارجية كان التسلسل متماسكاً. حمل ClientHello قيمتين، وأعاد EncryptedExtensions القيمة h2، ثم وثق Finished سجل المصافحة، وتبادل الطرفان مقدمة اتصال HTTP/2 وSETTINGS.

غير أن الأصل لم يكن الطرف الآخر في ذلك الاتصال. فكّت الحافة التعمية، ثم أنشأت TCP وTLS جديدين بسياسة ومفاتيح وشهادة أخرى. هناك قد تختار http/1.1، أو قد يغيب ALPN فتطبق الحافة رجوعاً معلناً إلى HTTP/1.1.

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

التفاوض على بايتات لا على أسماء تقريبية

خصصت IANA القيمة 16 للامتداد application_layer_protocol_negotiation. وتعرف RFC 7301 كل ProtocolName كسلسلة بايتات معتمة غير فارغة، طولها من بايت إلى 255 بايتاً، يسبقها بايت طول. العنصر الفارغ أو المبتور غير صالح.

لذلك لا يجوز تغيير حالة الأحرف أو القص أو المطابقة التقريبية. يستخدم HTTP/2 فوق TLS القيمة الدقيقة h2. وتحظر RFC 9113 عرض h2c أو اختياره داخل ALPN فوق TLS.

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

عند غياب التقاطع تفرض RFC 7301 إنذار no_application_protocol القاتل. وتؤكد RFC 9325 المعالجة الصارمة للحد من الالتباس بين البروتوكولات. لا يملك الخادم أن يختار قيمة لم يعرضها العميل.

نتيجة حاسمة ضمن نطاق صغير

بعد الاختيار تصبح القيمة حاسمة لبيانات التطبيق في الاتصال نفسه. من يختار h2 لا يجوز له تحليل البايتات نفسها كأنها HTTP/1.1. وتضيف مقدمة اتصال HTTP/2 وSETTINGS تأكيداً بعد TLS.

ينشأ بذلك سلم أدلة: عرض في ClientHello، اختيار في EncryptedExtensions، مصافحة موثقة بـFinished، مقدمة صحيحة، ثم تبادل مفيد. لا يثبت ClientHello منفرد اكتمال التفاوض، ولا يثبت نجاح ALPN وحده بدء HTTP/2.

ولا تنتقل النتيجة إلى المستقبل. تنبه RFC 9113 إلى أن الدعم السابق ليس إشارة قوية لاتصال تالٍ، لأن النسخ والإعداد والشبكة تتغير. لذا الاتصال هو وحدة الإسناد الصحيحة.

للوكيل دفتران لا خانة واحدة

أمام المتصفح يكون الوكيل خادم TLS، وأمام أصل يستخدم TLS يصبح عميلاً. لكل وصلة عرض واختيار وإنذار وجيل سياسة مستقل.

توضح خيارات Envoy الرسمية ذلك: يمكن استخدام بروتوكول الوصلة الهابطة صراحة، أو التفاوض مستقلاً على HTTP/1.1 أو HTTP/2 في الوصلة الصاعدة، أو الرجوع إلى HTTP/1.1 عند غياب ALPN هناك. الاستمرارية سلوك جرى إعداده وتشغيله، وليست وراثة تلقائية.

أما النفق الحقيقي فقد يمرر الوسيط البايتات من دون أن يكون طرف TLS. يستطيع رأس HTTP في RFC 7639 وصف البروتوكولات المقصودة داخل CONNECT، لكن القصد لا يثبت مصافحة داخلية مكتملة.

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

بين وجود callback وتنفيذه

في OpenSSL يؤدي ضبط طول قائمة العميل إلى صفر إلى حذف امتداد ALPN. وإذا لم يعرض ClientHello شيئاً، فلن يُستدعى callback الخاص بالخادم. التثبيت قدرة، والاستدعاء تنفيذ.

يعمل callback الخاص باسم الخادم أولاً وقد يستبدل SSL_CTX؛ بعد ذلك يعمل ALPN في السياق الناتج. لذلك قد تختلف سياسة المضيف الافتراضي عن الجرد العام.

تعيد SSL_get0_alpn_selected ذاكرة مستعارة غير منتهية بـNUL مع طول صريح. معاملتها كنص عادي قد تبتر المعرف أو تشوهه.

يوجد اختبار سلبي مهم في SSL_select_next_proto: عند عدم وجود تطابق، تضع الدالة أول عنصر للعميل في الخرج مع OPENSSL_NPN_NO_OVERLAP. يجب تجاهل الخرج في مسار ALPN. تسجيله قبل فحص النتيجة يصنع تفاوضاً لم يقع.

ويجب فصل غياب العرض، والترميز غير الصالح، وعدم التطابق، وNOACK، وفشل callback، والاختيار الناجح. لا يحفظ متغير منطقي واحد مسار القرار.

الاستئناف اتصال جديد لا استمرار للسلطة

تجعل RFC 7301 ALPN خاصية للاتصال لا للجلسة. عند الاستئناف لا تحكم القيم القديمة؛ رسائل المصافحة الجديدة هي المرجع.

لا تجبر تذكرة صدرت حين كان h2 مفعلاً نسخة جديدة على اختياره. نسخ النتيجة القديمة إلى القياس الجديد يخفي تغير النشر.

في TLS 1.3 تشمل معلمات 0-RTT المرتبطة بـPSK قيمة ALPN. لا يقبل الخادم البيانات المبكرة إلا إذا طابقها الاختيار الجديد. وإذا رفضها ثم اختار بروتوكولاً آخر، فقد يحتاج التطبيق إلى بناء رسالة مختلفة.

لهذا تحظر RFC 9846 على TLS إعادة الإرسال تلقائياً ما لم يُختر ALPN نفسه. التطبيق وحده يعرف التأطير والمعنى.

البروتوكول والهوية والإذن ثلاث إجابات

يجيب ALPN عن كيفية الحديث. ويجيب التحقق من الشهادة وهوية الخدمة عن هوية الطرف. ثم تقرر سياسة التطبيق الفعل المسموح.

يوضح HTTP/3 الفصل: تختار المصافحة عادة h3 فوق QUIC، لكن RFC 9114 تفرض أيضاً شهادة مقبولة لأصل URI. اختيار h3 الحقيقي لا يجعل خادماً بهوية خاطئة صاحب سلطة على الأصل.

كما أن تسجيل IANA يحدد معنى البايتات ولا يثبت نشرها. يفسر الكود والإعداد ما يمكن أن يحدث، لكنهما لا يستبدلان العرض والاختيار وبدء التطبيق المرصود.

اختبارات سلبية تحفظ الحد

يعرض العميل h2,http/1.1 ويفضل الخادم http/1.1؛ يجب أن يسجل القياس الاختيار لا أول عنصر. ويجب أن يؤدي رد بقيمة غير معروضة إلى إنهاء المصافحة.

يرسل ClientHello بلا ALPN لإثبات عدم استدعاء callback. ويفصل no_application_protocol عن NOACK المقصود. ويُختبر OPENSSL_NPN_NO_OVERLAP من دون تحويل خرجه إلى اختيار. كما يُستبدل SSL_CTX عبر SNI وتُنسب النتيجة إلى الجيل الصحيح.

في الحافة يُنشأ h2 هابط وHTTP/1.1 صاعد مع حفظ الاتصالين والتحويل. ثم يستأنف اتصال بعد تغير السياسة من دون وراثة القيمة القديمة. وعند تغير ALPN النهائي تُرفض 0-RTT ولا يعاد إرسالها تلقائياً.

أخيراً ينجح ALPN وتفشل الهوية، ثم ينجحان ويرفض التطبيق الفعل. ظهور النتائج منفصلة يثبت أن كل طبقة بقيت داخل سلطتها.

المصادر