Membangun Modul Dinamis untuk Nginx

gambar


Baru-baru ini, kami membangun modul dinamis untuk Nginx, dan ketika semuanya sudah siap, ternyata modul kami tidak kompatibel dengan Nginx, yang sudah diinstal pada server. Kami tidak dapat menemukan solusi yang siap pakai untuk masalah ini dan kami mulai melawannya sendiri. Kami menghabiskan banyak waktu, tetapi mendapat pengalaman baru dan, yang paling penting, solusi kerja. Yang ingin saya bagikan.


Mari kita mulai dengan deskripsi proses perakitan modul dinamis menggunakan contoh https://github.com/vozlt/nginx-module-vts . Dan kemudian kita akan menunjukkan kesalahan apa yang terjadi dan apa yang harus dilakukan dengannya.


Input data:
Debian 9 OS
Nginx v1.10.3 dari repositori standar Debian. nginx -V output:


 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 

Output dari perintah ini berisi informasi yang diperlukan untuk perakitan modul dinamis, yaitu, semua yang ditulis setelah configure arguments: dan sebelum yang pertama - --add-dynamic-module , yaitu:


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

Jadi, kita lanjutkan ke perakitan modul:


  • Untuk perakitan, lebih mudah untuk menggunakan wadah buruh pelabuhan agar tidak mengacaukan sistem utama, mengambil gambar debian: 9 sebagai dasar, untuk kenyamanan menyalin modul jadi dari wadah, Anda dapat menentukan volume. Perintah untuk memulai wadah dalam kasus ini akan terlihat seperti ini:

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

  • Setelah memulai wadah, instal paket yang diperlukan. Harap dicatat bahwa paket dipilih sesuai dengan output dari perintah nginx -V, jadi Anda mungkin tidak memerlukan beberapa pustaka. Bagaimanapun, skrip konfigurasi akan memperingatkan Anda tentang tidak adanya dependensi:

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

Paket libssl-dev tidak ada dalam daftar ini, karena nginx yang diinstal pada server dibangun dengan versi 1.1.0k dari OpenSSL, dan pada saat penulisan, ketika menginstal paket libssl-dev dari repositori, versi OpenSSL di dalamnya sudah 1.1.0l. Oleh karena itu, kode sumber OpenSSL untuk versi yang benar harus diunduh secara terpisah.



 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 

  • Sekarang Anda siap menjalankan skrip configure. Kami menentukan semua parameter dari output perintah nginx -V sebagai parameter skrip, yang saya tulis di awal artikel. Kami juga menambahkan parameter --add-dynamic-module untuk membangun modul nginx-module-vts dan menentukan path ke direktori dengan file sumber OpenSSL melalui parameter --with-openssl. Perintah terakhir akan terlihat seperti ini:

 ./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/ 

  • Setelah skrip configure selesai berfungsi, kami memulai perakitan modul, kami tidak perlu mengumpulkan semua nginx :

 make modules 

Perhatikan bahwa perintah ini hanya tersedia dengan nginx versi 1.9.13.


  • Setelah proses perakitan selesai, salin file yang dihasilkan ke volume , yang dipasang ketika wadah dimulai:

 cp objs/ngx_http_vhost_traffic_status_module.so /nginx_module/ 

  • Selanjutnya, kami menempatkan file pada server target, dalam hal ini, direktori dengan modul-modul terletak di jalur /usr/share/nginx/modules . Untuk mengaktifkan modul di nginx kita membuat file /etc/nginx/modules-enabled/mod-http-vhost-traffic-status.conf dengan konten berikut:

 load_module modules/ngx_http_vhost_traffic_status_module.so; 

Dan buat tautan simbolis ke file ini di direktori /etc/nginx/modules-enabled .


Setelah pekerjaan selesai, kita memanggil perintah nginx -t dan ... kita mendapatkan kesalahan:


 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 

Dan di sini, biasanya, ada beberapa kebingungan, karena versi sumber dan versi nginx diinstal pada server adalah sama, versi OpenSSL juga, parameter untuk skrip configure juga disalin seluruhnya. Jadi apa masalahnya?


Untuk memahami masalah ini, saya harus memahami bagaimana nginx memeriksa apakah modul dinamis cocok untuk itu. Kode yang terletak di sumber nginx dalam file src/core/ngx_module.h ( https://github.com/nginx/nginx/blob/master/src/core/ngx_module.h ) bertanggung jawab untuk pemeriksaan ini. Ada sejumlah cek dalam file ini, dalam kasus ini 34, di mana nginx menetapkan variabel dari bentuk NGX_MODULE_SIGNATURE_0 (1,2,3, dll.)
nilai 1 atau 0. Berikutnya adalah variabel NGX_MODULE_SIGNATURE
yang mengumpulkan hasil semua cek dalam satu baris. Dengan demikian, masalahnya adalah bahwa string tanda tangan dari modul baru tidak cocok dengan string tanda tangan dari nginx yang ada. Untuk memeriksa nilai string tanda tangan, Anda dapat menggunakan perintah berikut:


  • Garis tanda tangan modul yang dibangun:

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

  • Baris tanda tangan dari file biner nginx diinstal di server:

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

Ketika membandingkan garis-garis ini dengan mata telanjang, jelas bahwa dalam baris tanda tangan modul, variabel keempat dari ujung ternyata 0, sedangkan nginx memiliki 1. Untuk memahami apa yang sebenarnya hilang dalam modul, Anda perlu merujuk ke file src/core/ngx_module.h dan temukan variabel keempat dari akhir, tampilannya seperti ini:


 #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 

Kami tertarik pada variabel NGX_HTTP_HEADERS , ketika membangun nginx itu adalah 1, dan ketika membangun modul 0. Agar modul dapat NGX_HTTP_HEADERS dengan NGX_HTTP_HEADERS Anda perlu menyesuaikan file konfigurasi di direktori dengan kode sumber modul dengan menambahkan baris have=NGX_HTTP_HEADERS . auto/have have=NGX_HTTP_HEADERS . auto/have di awal file config. Berikut ini adalah awal file konfigurasi setelah melakukan perubahan:


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

Selanjutnya, lakukan make clean , lalu mulai kembali configure dan make modules . Setelah merakit modul, kami memeriksa string tanda tangannya dan melihat bahwa sekarang cocok dengan string 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 

Setelah itu, modul terhubung tanpa masalah dan Anda dapat mengumpulkan statistik lanjutan dengan nginx .


Dalam kasus Anda, mungkin garis tanda tangan akan terlihat berbeda, serta variabel yang bertanggung jawab untuk setiap posisi di baris ini. Namun, sekarang Anda dapat memahami apa yang sebenarnya salah dengan perakitan modul dan memperbaiki masalahnya.


Saya harap artikel ini menyelamatkan seseorang beberapa jam, karena saya secara pribadi beberapa kali menghadapi masalah bahwa modul tidak cocok dengan nginx , sebagai hasilnya, saya menyelesaikannya melalui perakitan penuh nginx bersama dengan modul yang tepat.


Baca juga artikel lain di blog kami:


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


All Articles