Linux Kernel TLS و Nginx

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

خلفية


في عام 2015 ، قدم Randall Stewart و Scott Long من Netflix عرضًا تقديميًا في مؤتمر AsiaBSDCon2015 حول تحسين توزيع المحتوى المشفر. الرسالة الرئيسية للتقرير هي نقل تشفير البيانات إلى نواة نظام التشغيل لتقليل عدد نسخ البيانات بين فضاء النواة ومساحة المستخدم واستخدام استدعاء نظام الإرسال المحسّن () غير المحظور. تحول الموضوع إلى أن يكون واعدًا بالفعل ، وفي مؤتمر Netdev 1.2 لعام 2016 ، قدم Dave Watson من Facebook عرضًا تقديميًا حول الحاجة إلى إنشاء مقابس TLS في نواة Linux ، وقدم Boris Pismenny و Ilya Lesokhin و Liran Liss من Mellanox عرضًا تقديميًاحول القدرة على استخدام تسريع أجهزة TLS في بطاقات الشبكة. تمت مناقشة الموضوع أيضًا في HighLoad ++ 2017 من قبل متحدث من Tempesta Technologies.

دعم نواة لينكس


كانت نتيجة كل هذه المحادثات ظهور Kernel TLS في Linux kernel 4.13 (2017) مع دعم TLSv1.2 وتشفير AES128-GCM. في البداية ، تم دعم تشفير حركة المرور الصادرة فقط ، ظهر دعم فك التشفير لاحقًا في Linux kernel 4.17 (2018). في الإصدار 5.1 ، أضافوا دعمًا لـ TLSv1.3 و AES256-GCM ، وفي الإصدار 5.2 أضافوا أيضًا تشفير AES128-CCM (2019).

الدعم في مساحة المستخدم


في جميع التقارير المذكورة أعلاه ، قيل أنه يمكن فقط وضع تشفير البيانات المفيدة في النواة ، ويجب معالجة جميع موافقات TLS ورسائل التحكم بالطريقة نفسها في مساحة المستخدم. ولهذا ، تم استخدام نسخة معدلة من OpenSSL. ومع ذلك ، في وقت نشر التقارير في المجال العام ، لم تكن هناك معلومات حول التعديلات التي يجب إجراؤها على هذه المكتبة المعروفة جيدًا لدعم الوظيفة. ربما كان المثال الوحيد المتاح لاستخدام Linux Kernel TLS هو مقالة المدونة Filippo Valsorda اللعب مع kernel TLS في Linux 4.13 و Goوالتي ظهرت مباشرة بعد إصدار نواة لينكس 4.13. وعلى الرغم من أنها أظهرت مثالًا صالحًا على استخدام التكنولوجيا ، إلا أنها لم تُفهم كيفية استخدام التكنولوجيا في المشاريع الحقيقية. في الواقع ، عدد قليل جدًا من الأشخاص يكتبون خادم WEB لمشروعهم بأنفسهم ، وعادة ما يستخدم الجميع أدوات معروفة ومختبرة بالوقت.

الدعم في OpenSSL


ظهرت المناقشات الأولى للتكنولوجيا في OpenSSL في صيف عام 2017 قبل إصدار نواة Linux 4.13 ( PR 3631 ) بوقت قصير ، لكن عملية المناقشة كانت بطيئة جدًا جدًا ، وظهرت التعليقات الحقيقية الأولى في أكتوبر (بعد إصدار نواة 4.13) ، وفي الواقع إصدار العملبدأ النقاش في فبراير 2018. في الوقت الذي تم فيه الاتفاق على جميع التصحيحات ، تم إغلاق نافذة إضافة وظائف جديدة في OpenSSL 1.1.1 ، وتم نقل دعم Kernel TLS إلى الإصدار التالي. منذ ذلك الوقت ، تمت إضافة دعم Kernel TLS RX ، و SSL_sendfile () هو استدعاء إلى syscall المقابل مع القليل من التعامل مع المواقف المحتملة في بروتوكول TLS. ولكن الآن في عام 2020 ، لم يتم طرح OpenSSL 3.0 بعد ، ويتم دعم TLSv1.3 من قبل الغالبية العظمى من المتصفحات ، ويتم استبدال تشفير AES128-GCM بنشاط بأكثر مقاومة AES256-GCM. لذلك أخذت الحرية وأرسلت طلب سحب لدعم الأصفار الجديدة و TLSv1.3 على أمل أنهم سيقبلونها قبل الإصدار الجديد للمكتبة.

الدعم في خوادم WEB


لكن دعم Kernel TLS في مكتبة TLS لا يكفي. ذكرت تقارير عن التكنولوجيا أنه يمكن الحصول على أقصى قدر من الكفاءة باستخدام الإرسال دون نسخ البيانات إلى مساحة المستخدم - باستخدام استدعاء النظام sendfile (). وينبغي أن يكون تطبيق الخادم قادرًا على التمييز بين المواقف التي يمكنك فيها استخدام sendfile () على مقبس مع TLS ، وعندما تحتاج إلى "قراءة الطريقة القديمة" ، يجب قراءة () / SSL_write (). ظهر بعض التقدم نحو إضافة وظائف إلى Nginx في أبريل 2019 ، ولكن لم يتم قبول أي تغييرات على الرمز الرئيسي. موقف المطورين هو أن واجهة برمجة التطبيقات لهذه الوظائف لم تتم الموافقة عليها بعد في OpenSSL ، ولا يبدو أن الرمز الفعلي المقترح في التصحيح قابل للنقل بشكل كافٍ لأنظمة أساسية مختلفة. لنكون صادقين ، لا يبدو الرمز فقط لطيفًا جدًا ، ولكنه يحتوي أيضًا على أخطاء تمنع بناء Nginx دون تصحيحات إضافية.لم أتمكن من العثور على دعم Kernel TLS في خوادم الويب الأخرى على الإطلاق (ربما شاهده أحد الأشخاص - أخبرني في التعليقات).

و ما العمل؟


بينما ينتظر المجتمع إصدار OpenSSL 3.0 ، من أجل البدء في تطوير الدعم لـ Kernel TLS في Nginx باستخدام واجهة برمجة تطبيقات ثابتة ، ذهبت في الاتجاه الآخر. في ركني المريح من GitHub ، فعلت شيئين:

  1. لقد أنشأت شوكة OpenSSL وأعدت كل شيء متعلق بـ Kernel TLS إلى الإصدار الثابت من OpenSSL 1.1.1 (فرع OpenSSL_1_1_1-ktls). خاصة من أجل أن تكون قادرًا على التحقق من الوظائف في ظروف التشغيل المستقر لبقية المكتبة. عندما تتوفر إصدارات مستقرة ، أحاول إعادة تحديدها بحيث تكون الشوكة محدثة.
  2. لقد أنشأت شوكة من Nginx ، أضفت فيها (استنادًا إلى تصحيح من Mellanox) دعم SSL_sendfile () في الحالات التي يكون فيها ذلك ممكنًا بالفعل ومع عمليات التحقق من مقبس SSL الضرورية ، والقدرة على تمكين / تعطيل الوظيفة من خلال متغير التكوين. بالإضافة إلى هذه الميزة ، هناك أيضًا العديد من التصحيحات في شوكة بلدي التي تعمل على تحسين عمل Nginx قليلاً وإصلاح بعض الأخطاء (فرع الميزة الرئيسية). إلى أقصى حد ممكن ، أحاول إعادة بناء على الفرع الرئيسي لريبو Nginx الرئيسي ، من أجل إبقاء الشوكة محدثة.

أدعو الجميع للمشاركة في الاختبار. يمكن طرح التعليقات والتصحيحات على الرمز في مشكلات على GitHub. لإنشاء Nginx هذا باستخدام OpenSSL ودعم Kernel TLS المضمن ، أضف معلمات إلى البرنامج النصي للتكوين:

./configure --with-openssl=<OpenSSL-fork-dir> --with-openssl-opt="enable-ktls"

في الوقت الحالي ، لا تسنح لي الفرصة لاختبار حزمة Nginx + OpenSSL هذه تحت عبء جاد لتأكيد الأداء من التعليق إلى تصحيح Nginx ، لذلك إذا تمكن شخص ما فجأة من قياس الفرق في تحميل وحدة المعالجة المركزية بسرعات تحميل عالية للملفات ، فسيكون من الرائع الحصول على الرسوم البيانية وإضافة لهم في مقال لفهم بصري للتأثير.

All Articles