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.
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.
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
- Ngx_small_light: Resim işleme modülü
- Ngx_http_lua_module: Nginx üzerinde Lua script çalıştırmamızı sağlar
- NginxExecute: Get ve Post metodları ile shell script çalıştırır ve sonucu client'a gönderir
- Nginx-Clojure: Clojure, Java ve Groovy kodu çalıştırır
- Nginx-auth-ldap: Ldap authentication yapmak için kullanılır
- Naxsi: SQL injection ve XSS atakları için kullanılabilcek basit ma kullanilı bir Web Application Firewall olaeak düşünülebilir
- Nginx-rtmp-module: canlı yayın veya on-demand video yayını yapmak için kullanılır.
- Nginx-selective-cache-purge-module: Cache temizlemek için kullanılır. Nginx'in Plus (paralı) versiyonundaki proxy_cache_purge direktifinin ücretsiz versiyonu.
- nginx-vod-module: VOD (Video on Demand) yayınları için kullanılır. Nginx'in Plus (paralı) versiyonundaki ngx_http_hls_module modülünün ücretsiz versiyonudur.
- nginx-upload-module: Dosya upload işlemleri için kullanılır
- nginx-video-thumbextractor-module: Arka tarafta ffmpeg kullnarak sunucudaki video'dan belirtilen boyutlarda ve istenilen saniyedeki kare üzerinden resim oluşturur.
- Nginx-image-filter-watermark: paralı olan image-filter modulü üzerinden resim üzerine watermark eklemek için kullanılır.
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.
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'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.