Skip to content

Latest commit

 

History

History
398 lines (279 loc) · 19.1 KB

7.modules.md

File metadata and controls

398 lines (279 loc) · 19.1 KB

Nginx Modül Yönetimi

Merhaba arkadaşlar,

Bu yazımızda Nginx modül yönetimini inceleyeceğiz. En çok kullanılan baz modülleri kurup örnekler yapacağız.

Nginx'de iki tip modül var,

  • Statik modüller Nginx ile birlikte derlenerek Nginx'e eklenir. Bu şekilde build alınan modülleri Nginx'in doğal üyesiymiş gibi düşünebilirsiniz. Kullanırken ekstra bir iş yapmanız gerekmez.
  • Dinamik modüller Nginx derlenip çalıştırıldıktan sonra yada doğrudan kurulumu yapıldıktan sonra ihtiyaç olduğu an load_module direktifi ile yüklenebilirler. Ancak dinamik modülleri de yine Nginx ile birlikte derlemek gerekiyor. Tek farkları Nginx'e gömmek zorunda değiliz istediğimiz zaman yükleme yapabiliriz.

Nginx'in standart modülleri statik modüllerdir, bazı modüllerini dinamik olarak da derlemek de mümkün. Plus (paralı) versiyonun modülleri dinamiktir. Dinamik modüller Linux'ün dinamik modül mantığı ile aynıdır. Linux'deki so uzantılı dosyalar gibi Nginx'de so (shared object) uzantılı dosyaları dinamik modül olarak yükler.

Herhangi bir modülün kurulu olup olmadığını test etmek için alttaki komutu kullanabilirsiniz.

nginx -V 2>&1 | grep -- 'http_auth_request_module'

Nginx'in kendi geliştirdiği modüller dışına community'nin ve firmaların geliştirdiği modüller de var. Resmi olarak desteklediği modüllerin listesi için şu sayfaya bakabilirsiniz. Resmi olarak desteklenen modülleri paket yöneticilerinden build almaya gerek olmaksızın yüklemek de mümkün. Örneğin Ubuntu için geoip modülü alttaki komutla yüklenebilir. Ancak biz build alarak yükleme yapacağız. Çünkü bu şekilde yüklenebilen modül sayısı yüzleri bulurken doğrudan yüklenebilenler yirmi kadardır.

apt-get install nginx-plus-module-geoip

Nginx resmi olarak desteklemese dahi community'in geliştirdiği çalışmaları da yakından takip ediyor. Kendi sayfasında bütün modüllerin listesine ulaşabilirsiniz. Listede yüz kadar modül bulunuyor.

Kullandığımız Linux distro paket yöneticisi (örneğin Ubuntu apt) üzerinden Nginx'i kurduğumuzda Ubuntu bazı statik Nginx modüllerini hazır olarak sunar. Daha önceki yazılarımızda kullandığımız Nginx konteynerlerinden birinde alttaki komutu çalıştırarak kurulu olan modüllerin listesini alabiliriz.

--with-.........module şeklinde yazanlar kurulu modülleri gösteriyor.

nginx -V

# sonuç
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1j  16 Feb 2021
TLS SNI support enabled

configure arguments: --with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-DUpigx/nginx-1.18.0=. 
-flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security 
-fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto 
-Wl,-z,relro -Wl,-z,now -fPIC' --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-compat --with-debug --with-pcre-jit
--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 --add-dynamic-module=/build/nginx-DUpigx/nginx-1.18.0/debian/modules/http-geoip2
--with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module
--with-http_sub_module

Aşağıdaki listede tüm statikmodüllerin listesini görebiliriz. Görüleceği üzere Ubuntu paket yöneticisinden kurmuş olduğum Nginx'de alttaki bazı modüller üstteki listede görünmüyor.

Birazdan bizde Nginx'i ve buradaki modüllerden bazılarını build alıp kuracağız. Kurulum esnasında configure komutunda modüllerin listesini görebileceğiz. Without kelimesi ile başlayan seçenekler de Nginx kurulumunda varsayılan olarak gelen modülleri kaldırmak için kullanılıyor.

--with-select_module
--with-poll_module
--with-threads
--with-file-aio
--with-http_ssl_module
--with-http_v2_module
--with-http_realip_module
--with-http_addition_module
--with-http_xslt_module
--with-http_xslt_module=dynamic
--with-http_image_filter_module
--with-http_geoip_module
--with-http_sub_module
--with-http_dav_module
--with-http_flv_module
--with-http_mp4_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_auth_request_module
--with-http_random_index_module
--with-http_secure_link_module
--with-http_degradation_module
--with-http_slice_module
--with-http_stub_status_module

Bu arada şunu da belirtmek gerekiyor statik modülleri dinamik modüle çevirmek de mümkün. İlginizi çekerse şu sayfaya bi göz atabilirsiniz.

Static Modüllerin Deploy Edilmesi

Kurulumu doğrudan docker image oluşturarak yapacağız. Aşağıdaki komutlarla static modüllerimizle birlikte Nginx'i build alarak kendi konteynerimizi oluşturuyoruz. İsterseniz komutları doğrudan kendi makinenizde de çalıştırabilirsiniz.

Bütün komutu terminalinize kopyalayıp enter'a basmanız yeterli olacaktır. Nginxstatic adında bir docker image oluşmuş olacak.

mkdir ~/nginxstatic

cd ~/nginxstatic

cat << EOF > Dockerfile
FROM ubuntu:20.04

ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Istanbul

RUN apt update && apt install -y tzdata vim wget systemctl build-essential \
                      libpcre3 libpcre3-dev zlib1g zlib1g-dev \
                      libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev

RUN mkdir /home/nginx

WORKDIR /home/nginx
RUN wget  http://nginx.org/download/nginx-1.20.0.tar.gz && tar -zxvf nginx-1.20.0.tar.gz

WORKDIR nginx-1.20.0
RUN ./configure --prefix=/usr/sbin/nginx --sbin-path=/usr/sbin/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 \
            --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_gunzip_module \
            --with-http_gzip_static_module --with-http_sub_module \
            --with-http_mp4_module --with-mail_ssl_module\
            --with-http_secure_link_module  --with-http_v2_module \
            --with-poll_module --with-threads --with-file-aio \
            --with-select_module  --with-http_secure_link_module --with-mail

RUN make && make install

RUN ln -s /usr/lib/nginx/modules /etc/nginx/modules

WORKDIR /usr/sbin/nginx/

EXPOSE 80

CMD /bin/bash -c "./nginx && tail -f /var/log/nginx/*.log"
EOF

docker build -t nginxstatic . 

Konteynerimizi alttaki komutla çalıştırıyoruz.

docker run -d --name nginxstatic -p 8086:80 nginxstatic

Daha önce Ubuntu paket yöneticisi ile kurup çalıştırdığımız Nginx'de örneğin,

  • ngx_http_mp4_module modülü yoktu. Bu modül sayesinde .mp4, .m4v, or .m4a uzantılı video dosyalarını stream edebilirsiniz.
  • yada mail-proxy modülü ile mail gönderme veya okuma işlemleri yapabilirsiniz.

Dinamik Modüllerin Deploy Edilmesi

Standart modüllerin dışında Nginx'in destek verdiği modülleri build almaya gerek olmaksızın doğrudan paket yöneticimizle kurabiliriz.

Standart statik modüllerden bazılarının dinamik versiyonlarını statik modülleri build aldığımız gibi build alabiliriz. Bunun için dinamik versiyonları olanların sonuna alttaki örneklerdeki gibi dynamic keyword'ünü eklememiz yeterli olacaktır.

--with-http_xslt_module=dynamic
--with-http_image_filter_module=dynamic
--with-http_geoip_module=dynamic
--with-http_perl_module=dynamic
--with-mail=dynamic
--with-stream=dynamic
--with-stream_geoip_module=dynamic

Biz community'nin geliştirmiş olduğu opensource statik veya dinamik modülleri build almayı deneyeceğiz.

Listedeki bazı modüller

Standart statik ve dinamik modülleri ayrıca community'nin geliştirmiş olduğu bazı statik ve dinamik modülleri de github repo'larından indirip build alarak Docker image'ımızı oluşturacağız.

mkdir ~/nginxdynamic
cd ~/nginxdynamic

cat << EOF > Dockerfile

FROM ubuntu:20.04

ARG DEBIAN_FRONTEND=noninteractive
ARG TZ=Europe/Istanbul

RUN apt update && apt install -y tzdata vim wget systemctl git \
                    geoip-database libgeoip-dev \ 
                    build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev \
                    libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev

RUN mkdir /home/nginx

WORKDIR /home/nginx
RUN wget  http://nginx.org/download/nginx-1.20.0.tar.gz && tar -zxvf nginx-1.20.0.tar.gz

RUN git clone https://github.com/cubicdaiya/ngx_small_light.git
RUN git clone https://github.com/openresty/lua-nginx-module.git
RUN git clone https://github.com/limithit/NginxExecute.git
RUN git clone https://github.com/nbs-system/naxsi.git
RUN git clone https://github.com/arut/nginx-rtmp-module.git
RUN git clone https://github.com/wandenberg/nginx-selective-cache-purge-module.git
RUN git clone https://github.com/fdintino/nginx-upload-module.git
RUN git clone https://github.com/wandenberg/redis_nginx_adapter.git


WORKDIR nginx-1.20.0
RUN ./configure --prefix=/usr/sbin/nginx --sbin-path=/usr/sbin/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 \
            # standart static moduller
            --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_gunzip_module \
            --with-http_gzip_static_module --with-http_sub_module \
            --with-http_mp4_module --with-mail_ssl_module\
            --with-http_secure_link_module  --with-http_v2_module \
            --with-poll_module --with-threads --with-file-aio \
            --with-select_module  --with-http_secure_link_module \
            # standart dinamik modüller
            --with-mail=dynamic --with-stream=dynamic  \
            --with-http_geoip_module=dynamic \
            # Community static modüller
            --add-module=/home/nginx/naxsi/naxsi_src \
            --add-module=/home/nginx/nginx-rtmp-module \
            # community dinamik modüller
            --add-dynamic-module=/home/nginx/NginxExecute \
            --add-dynamic-module=/home/nginx/nginx-upload-module


RUN make && make install

RUN ln -s /usr/lib/nginx/modules /etc/nginx/modules

WORKDIR /usr/sbin/nginx/

EXPOSE 80

USER root

CMD /bin/bash -c "./nginx && tail -f /var/log/nginx/*.log"

EOF

docker build -t nginxdynamic . 

Konteynerimizi alttaki komutla çalıştırıyoruz.

docker run -d --name nginxdynamic -p 8087:80 nginxdynamic

Görüleceği üzere Nginx tarafından standart olarak sunulmayan modüller için statik ile dinamik modüllerin kurulumundaki tek fark source klasörünü eklerken --add-module yerine --add-dynamic-module opsiyonunu kullanmak.

Kurulacak modüllerin bazılarının bağımlılıkları olabilir. Biz de oluşturduğumuz iki image'da da bazı paketleri yükledik.

Şimdi yüklediğimiz bu modüllerle alakalı uygulamalar yapabiliriz.

NginxExecute Modül Kullanımı

Modülü çalıştırabilmek için az önce çalıştırdığımız nginxdynamic konteynerimizde bazı ayarlar yapmamız gerekiyor.

docker exec -it nginxdynamic bash

Konteynere giriş yaptıktan sonra nginx.config dosyamızı "vim /etc/nginx/nginx.conf" komutunu çalıştırarak düzenliyoruz.

  • aşağıdaki location bloğunu dosyaya ekliyoruz.
  • global (main) alana da dinamik bir modül eklediğimiz için "load_module /usr/lib/nginx/modules/ngx_http_execute_module.so;" satırını ekleyip konteynerimizi restart ediyoruz.

location /command {
            root   html;
            index  index.html index.htm;
            command on;
        }

Daha sonra tarayıcı da adres satırında "http://localhost:8087/command?system.run[date]" adresini çağırdığımızda ekrana tarih bilgisinin geldiğini görebiliriz.

Yada "http://localhost:8087/command?system.run[pwd]" komutu çağırdığmızda Nginx bulunduğu dizinin yazıldığını görebiliriz.

Naxsi Modül Kullanımı

Naxsi'yi (Nginx Anti XSS & SQL Injection) statik modül olarak kurmuştuk bu nedenle NginxExecute modülünde olduğu gibi load_module direktifini çağırmamıza gerek yok. Modül hazır bir kural listesiyle geliyor. Ayrıca community'nin oluşturduğu kural listeleri de mevcut. Kural listesini düzenlemek de mümkün.

Örneğimizde hazır gelen bu core kural listesini kullanacağız. Öncelikle bu kural listesini etc altındaki nginx klasörüne taşıyıp nginx.conf dosyamıza include direktifi ile ekliyoruz.

Konteynerimize giriş yapıyoruz.

docker exec -it nginxdynamic bash

İlgili dosyayı taşıyoruz.

cp /home/nginx/naxsi/naxsi_config/naxsi_core.rules /etc/nginx/

Daha sonra nginx.conf dosyamızda html bloğunda global alana ekliyoruz.

vim /etc/nginx/nginx.conf

alttaki satırı ekliyoruz.

include /etc/nginx/naxsi_core.rules;

Daha sonra bu kural listesinden bazılarını kullanmak için location bloğuna alttaki satırları ekliyoruz.

location / {
            root   html;
            index  index.html index.htm;

        SecRulesEnabled;

        #ilk açılışta learning mode açık
        LearningMode;

        #Bloklanacak url'lerin gideceği sayfa
        DeniedUrl "/50x.html";


        #Seçilen kurallar. Core kurallardan bazılarını burada kullanacağımızıbelirtmiş olduk
        #Kural çalışınca ilgili sayfanın BLOCK'lanacağını belirttik

        CheckRule "$SQL >= 8" BLOCK;
        CheckRule "$RFI >= 8" BLOCK;
        CheckRule "$TRAVERSAL >= 4" BLOCK;
        CheckRule "$EVADE >= 4" BLOCK;
        CheckRule "$XSS >= 8" BLOCK;

       }

Konteynerimizi restart yaptıktan sonra LearningMode açık iken tarayıcımızda core modülde geçen alttaki kuralı Naxsi'ye öğretmek http://localhost:8087/?s=< adresini çağırıyoruz.

Amacımız aşağıdaki kuralı tetiklenecek URL'i çağırarak sistemi LearningMode'dan çıkarttığımızda BLOCK yapmasını sağlamak.

MainRule "str:<" "msg:html open tag" "mz:ARGS|URL|BODY|$HEADERS_VAR:Cookie" "s:$XSS:8" id:1302;

Bu adresi çalıştırdıktan sonra error.log dosyasına bakacak olursak aşağıdaki gibi bir satır görmeliyiz.

2021/07/07 18:24:41 [error] 11#11: *1 NAXSI_FMT: ip=172.17.0.1&server=localhost&uri=/&vers=1.3&total_processed=6&total_blocked=6&config=learning&cscore0=$XSS&score0=8&zone0=ARGS&id0=1302&var_name0=s, client: 172.17.0.1, server: localhost, request: "GET /?s=%3C HTTP/1.1", host: "localhost:8087"

Learning mode açıkken ilgili kural çalışsa dahi sayfa BLOCK'lanmayacaktır. Log'larda da öğrenme modu için log alındığını gösteren config=learning ayarı görebilirsiniz.

Sistemi LearningMode'dan çıkartmak için nginx.conf dosyasında LearningMode; satırını açıklama satırına çevirip konteynerimizi restart ediyoruz. Tarayıcızımızda http://localhost:8087/?s=< adresini çağırdığımızda sayafanın BLOCk'landığını göreviliriz. Ayrıca tekrar error.log dosyasını kontrol edecek olursak aşağıdaki satırı görüyor olacağız.

2021/07/07 18:26:46 [error] 10#10: *1 NAXSI_FMT: ip=172.17.0.1&server=localhost&uri=/&vers=1.3&total_processed=5&total_blocked=5&config=block&cscore0=$XSS&score0=8&zone0=ARGS&id0=1302&var_name0=s, client: 172.17.0.1, server: localhost, request: "GET /?s=%3C HTTP/1.1", host: "localhost:8087"

Bu örneğimizi de tamamlamış olduk. Böylece hem Nginx'in stadart modüllerini, statik ve dinamik modülleri build alıp kullanamyı görmüş olduk.

Bir sonraki yazımıda Nginx'in Plus (paralı) versiyonunun kurulumu ve kullanımını öğreneceğiz.