بناء وحدات ديناميكية ل Nginx

صورة


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


لنبدأ بوصف عملية تجميع الوحدة الديناميكية باستخدام المثال https://github.com/vozlt/nginx-module-vts . وبعد ذلك سوف نظهر الخطأ الذي يحدث وماذا نفعل به.


إدخال البيانات:
دبيان 9 OS
Nginx v1.10.3 من مستودع دبيان القياسي. إخراج nginx -V :


 nginx version: nginx/1.10.3 built with OpenSSL 1.1.0k 28 May 2019 (running with OpenSSL 1.1.1c 28 May 2019) TLS SNI support enabled configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-DhOtPd/nginx-1.10.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/ nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path =/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module - -with-http_stub_status_module --with-http_realip_mod ule --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module= dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-DhOtPd/nginx-1.10.3/debian/modules/nginx-auth-pam --add-dynamic-module=/build/nginx-DhOtPd/nginx-1.10.3/debian/modules/nginx-dav-ext-module --add-dynamic-module=/build/nginx-DhOtPd/nginx-1.10.3/debian/modules/nginx-echo --add-dynamic-module=/build/nginx-DhOtPd/nginx-1.10.3/debian/modules/nginx-upstream-fair --add-dynamic-module=/build/nginx-DhOtPd/nginx -1.10.3/debian/modules/ngx_http_substitutions_filter_module 

يحتوي إخراج هذا الأمر على معلومات ضرورية لإنشاء وحدات نمطية ديناميكية ، أي كل ما يتم كتابته بعد configure arguments: وقبل أول --add-dynamic-module ، وهي:


 --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-DhOtPd/nginx-1.10.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/ nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path =/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_mod ule --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module= dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module 

لذلك ، ننتقل إلى تجميع الوحدة:


  • للتجميع ، من المريح استخدام حاوية الإرساء حتى لا تشوش النظام الرئيسي ، واتخاذ ديبيان: 9 صورة كأساس ، لتوفير الراحة لنسخ الوحدة النمطية الجاهزة من الحاوية ، يمكنك تحديد حجم. سيظهر الأمر لبدء الحاوية في هذه الحالة:

 docker run --rm -it -v /tmp/nginx_module:/nginx_module debian:9 bash 

  • بعد بدء تشغيل الحاوية ، قم بتثبيت الحزم اللازمة. يرجى ملاحظة أنه يتم تحديد الحزم وفقًا لإخراج الأمر nginx -V ، لذلك قد لا تحتاج إلى بعض المكتبات. في أي حال ، سوف يحذرك البرنامج النصي للتكوين من غياب التبعيات:

 apt update apt install git make gcc autoconf wget libpcre3-dev libpcre++-dev zlib1g-dev libxml2-dev libxslt-dev libgd-dev libgeoip-dev 

حزمة libssl-dev مفقودة من هذه القائمة ، نظرًا لأن nginx المثبت على الخادم مبني على الإصدار 1.1.0k من OpenSSL ، وفي وقت كتابة هذا التقرير ، عند تثبيت حزمة libssl-dev من المستودع ، كان إصدار OpenSSL فيه هو 1.1.0l بالفعل. لذلك ، يجب تنزيل التعليمات البرمجية المصدر OpenSSL للإصدار الصحيح بشكل منفصل.


  • قم بالتنزيل من موقع الويب http://nginx.org/download nginx النسخة المطلوبة ، وفي حالتنا هذه هي 1.10.3. قم بتنزيل مصادر OpenSSL من الموقع الرسمي https://www.openssl.org/source/old ، وفي الواقع ، قم بتنزيل الشفرة المصدرية لوحدة nginx-module-vts من github.

 cd /usr/local/src/ wget http://nginx.org/download/nginx-1.10.3.tar.gz wget https://www.openssl.org/source/old/1.1.0/openssl-1.1.0k.tar.gz git clone git://github.com/vozlt/nginx-module-vts.git tar xvfz nginx-1.10.3.tar.gz tar xzvf openssl-1.1.0k.tar.gz cd nginx-1.10.3 

  • أنت الآن جاهز لتشغيل البرنامج النصي للتكوين. كمعلمات البرنامج النصي ، نشير إلى جميع المعلمات من إخراج الأمر nginx -V ، الذي كتبته في بداية المقال. نضيف أيضًا المعلمة -add-dynamic-module لإنشاء الوحدة النمطية nginx-module-vts وتحديد المسار إلى الدليل باستخدام ملفات مصدر OpenSSL من خلال --with-openssl. الأمر النهائي سيبدو كما يلي:

 ./configure --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-DhOtPd/nginx-1.10.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --with-openssl=../openssl-1.1.0k/ --add-dynamic-module=../nginx-module-vts/ 

  • بعد انتهاء البرنامج النصي configure ، نبدأ في تجميع الوحدات النمطية ؛ لسنا بحاجة إلى جمع كل nginx :

 make modules 

لاحظ أن هذا الأمر متاح فقط مع إصدار nginx 1.9.13.


  • بعد اكتمال عملية التجميع ، انسخ الملف الناتج الناتج إلى volume ، والذي تم تحميله عند بدء تشغيل الحاوية:

 cp objs/ngx_http_vhost_traffic_status_module.so /nginx_module/ 

  • بعد ذلك ، نضع الملف على الخادم الهدف ، في هذه الحالة ، يوجد الدليل الذي يحتوي على الوحدات النمطية على المسار /usr/share/nginx/modules . لتمكين الوحدة النمطية في nginx نقوم بإنشاء الملف /etc/nginx/modules-enabled/mod-http-vhost-traffic-status.conf بالمحتويات التالية:

 load_module modules/ngx_http_vhost_traffic_status_module.so; 

وقم بإنشاء رابط رمزي لهذا الملف في الدليل /etc/nginx/modules-enabled .


بعد الانتهاء من العمل ، نسمي الأمر nginx -t و ... حصلنا على الخطأ:


 nginx: [emerg] module "/usr/share/nginx/modules/ngx_http_vhost_traffic_status_module.so" is not binary compatible in /etc/nginx/modules-enabled/50-mod-http-vhost-traffic-status.conf:1 

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


لفهم هذه المشكلة ، كان علي أن أفهم كيف يتحقق nginx إذا كانت الوحدة الديناميكية مناسبة لها. الكود الموجود في مصادر nginx في ملف src/core/ngx_module.h ( https://github.com/nginx/nginx/blob/master/src/core/ngx_module.h ) هو المسؤول عن هذا الفحص. يوجد عدد من عمليات التحقق في هذا الملف ، في هذه الحالة 34 ، يتم خلالها تعيين nginx لمتغيرات النموذج NGX_MODULE_SIGNATURE_0 (1،2،3 ، إلخ.)
القيم 1 أو 0. التالي هو المتغير NGX_MODULE_SIGNATURE
الذي يجمع نتائج جميع الشيكات في سطر واحد. وفقًا لذلك ، تكمن المشكلة في أن سلسلة توقيع الوحدة الجديدة لا تتطابق مع سلسلة توقيع nginx الموجودة. للتحقق من قيم سلاسل التوقيع ، يمكنك استخدام الأوامر التالية:


  • خط توقيع الوحدة التي تم إنشاؤها:

 strings /usr/share/nginx/modules/ngx_http_vhost_traffic_status_module.so| fgrep '8,4,8' 8,4,8,000011111101011111111111110110111 

  • سطر توقيع الملف الثنائي nginx المثبت على الخادم:

 strings /usr/sbin/nginx| fgrep '8,4,8' 8,4,8,000011111101011111111111110111111 

عند مقارنة هذه الخطوط بالعين المجردة ، من الواضح أنه في سطر توقيع الوحدة النمطية ، تحول المتغير الرابع من النهاية إلى 0 ، بينما يحتوي nginx على 1. لفهم ما هو مفقود بالضبط في الوحدة النمطية ، تحتاج إلى الرجوع إلى ملف src/core/ngx_module.h والعثور على المتغير الرابع من النهاية ، يبدو مثل هذا:


 #if (NGX_HTTP_REALIP) #define NGX_MODULE_SIGNATURE_29 "1" #else #define NGX_MODULE_SIGNATURE_29 "0" #endif #if (NGX_HTTP_HEADERS) #define NGX_MODULE_SIGNATURE_30 "1" #else #define NGX_MODULE_SIGNATURE_30 "0" #endif #if (NGX_HTTP_DAV) #define NGX_MODULE_SIGNATURE_31 "1" #else #define NGX_MODULE_SIGNATURE_31 "0" #endif #if (NGX_HTTP_CACHE) #define NGX_MODULE_SIGNATURE_32 "1" #else #define NGX_MODULE_SIGNATURE_32 "0" #endif #if (NGX_HTTP_UPSTREAM_ZONE) #define NGX_MODULE_SIGNATURE_33 "1" #else #define NGX_MODULE_SIGNATURE_33 "0" #endif #define NGX_MODULE_SIGNATURE 

نحن مهتمون بالمتغير NGX_HTTP_HEADERS ، عند إنشاء nginx كان 1 ، وعند إنشاء الوحدة النمطية 0. لكي تتمكن الوحدة النمطية من NGX_HTTP_HEADERS باستخدام NGX_HTTP_HEADERS تحتاج إلى ضبط ملف التكوين في الدليل باستخدام الكود المصدري للوحدة النمطية عن طريق إضافة السطر have=NGX_HTTP_HEADERS . auto/have have=NGX_HTTP_HEADERS . auto/have في بداية ملف config. التالي هو بداية ملف التكوين بعد إجراء التغييرات:


 ngx_addon_name=ngx_http_vhost_traffic_status_module have=NGX_STAT_STUB . auto/have have=NGX_HTTP_HEADERS . auto/have ... 

بعد ذلك ، قم make clean ، ثم أعد تشغيل configure make modules . بعد تجميع الوحدة ، نتحقق من سلسلة توقيعها ونرى الآن أنها تطابق سلسلة nginx :


 $ strings /usr/sbin/nginx| fgrep '8,4,8' 8,4,8,000011111101011111111111110111111 $ strings /usr/share/nginx/modules/ngx_http_vhost_traffic_status_module.so | fgrep '8,4,8' 8,4,8,000011111101011111111111110111111 

بعد ذلك ، تتصل الوحدة النمطية دون أي مشاكل ويمكنك جمع إحصاءات متقدمة مع nginx .


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


آمل أن توفر هذه المقالة لشخص ما بضع ساعات من الوقت ، لأنني شخصياً واجهت عدة مرات مشكلة أن الوحدة لا تتناسب مع nginx ، كنتيجة لذلك ، كقاعدة عامة ، قمت بحل هذا من خلال التجميع الكامل لـ nginx مع الوحدة النمطية الصحيحة.


اقرأ أيضًا مقالات أخرى على مدونتنا:


Source: https://habr.com/ru/post/ar473578/


All Articles