Nginx یک وبسرور سبک و با سطح عملکرد بالاست که میتواند به عنوان reverse proxy یا پروکسی ایمیل IMAP/POP3 نیز مورد استفاده قرار گیرد. این وبسرور بر روی سیستمعاملهای یونیکس، لینوکس، نسخههای مختلف BSD، مک، سولاریس و مایکروسافت ویندوز اجرا میشود. مطابق دادههای نتکرافت، حدود 13.5 درصد کل دامینهای اینترنت از وبسرور Nginx استفاده میکنند.
وبسرور Nginx یکی از کاربردیترین سرورهایی است که برای رفع مشکل موسوم به C10k نوشته شده است. برخلاف سرورهای معمولی، Nginx برای مدیریت درخواستها به thread تکیه ندارد. به جای آن، از یک ساختار مقیاسپذیر مبتنی بر موقعیت استفاده میکند. به همین علت است که Nginx در برخی از وبسایتهای پرترافیک مانند وردپرس، هولو، گیتهاب و سورسفورج به کار رفته است.
امنیت وبسرور Nginx در لینوکس یا یونیکس
در این مطلب قصد داریم که نحوه ارتقای امنیت وبسرورهای Nginx را در سیستمعاملهای لینوکس یا یونیکس آموزش دهیم.
فایلهای تنظیمات پیشفرض و پورت Nginx
/usr/local/nginx/conf/ یا /etc/nginx/– دایرکتوری تنظیمات پیشفرض سرور
/usr/local/nginx/conf/nginx.conf فایل تنظیمات اصلی –
/usr/local/nginx/html/ یا /var/www/html– موقعیت پیشفرض اسناد
/usr/local/nginx/logs/ یا /var/log/nginx – موقعیت پیشفرض فایل تاریخچه عملکرد
پورت پیشفرض اچتیتیپی : TCP 80
پورت پیشفرض اچتیتیپیاس : TCP 443
در همین حال میتوانید با استفاده از فرمان زیر، تغییرات وبسرور Nginx را بررسی کنید:
# /usr/local/nginx/sbin/nginx -t
و یا با کمک این فرمان:
# nginx -t
نمونه خروجی
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok configuration file /usr/local/nginx/conf/nginx.conf test is successful
برای بازیابی تغییرات داریم:
# /usr/local/nginx/sbin/nginx -s reload
و یا اینکه:
# nginx –s reload
برای متوقفکردن سرور، فرمان زیر را تایپ کنید:
# /usr/local/nginx/sbin/nginx -s stop
و یا:
# nginx -s stop
۱) فعالسازی SELinux
SELinux یک ویژگی کرنل لینوکس است که سازوکاری برای سیاستهای امنیتی در کنترل دسترسیها ایجاد میکند. نتیجه عملکرد SELinux سطح امنیتی بسیار بالا برای سرور خواهد بود. در این حالت، جلوی بسیاری از حملات به سیستم گرفته میشود. در اینجا میتوانید ببینید که چگونه SELinux در سیستمهای مبتنی بر CentOS / RHEL فعال میشود.
قفل بولی سیستم
فرمان getsebool –a را اجرا کرده و سیستم را قفل کنید:
getsebool -a | less getsebool -a | grep off getsebool -a | grep on
برای تأمین امنیت سیستم میتوانید یک بار دیگر نگاهی به تنظیمات نیز داشته باشید. در این حالت، آنهایی را که با فرمان getsebool هنوز به صورت “on” باقی ماندهاند، به صورت “Off” دربیاورید. مقدار درست بولین SE Linux را برای حفظ کارآیی و امنیت سیستم انتخاب کنید. به خاطر داشته باشید که SELinux میتواند ۲ تا ۸ درصد به حجم نصب معمولی CentOS یا RHEL اضافه کند.
۲) کمترین اولویتبندی در توزیع فایلها در دایرکتوری
تمام فایل صفحات وب، اچتمل و پیاچپی را به صورت پارتیشنهای جداگانه در سرور ذخیره کنید. به عنوان مثال، یک پارتیشن با نام /dev/sda5 ایجاد کرده و آنها را در دایرکتوری /nginx قرار دهید. حتماً دقت کنید که /nginx با مجوزهای noexec، nodev و nosetuid همراه باشد. در اینجا یک نمونه از ورودی /etc/fstab را برای جایگذاری در /nginx ملاحظه میکنید:
LABEL=/nginx /nginx ext3 defaults,nosuid,noexec,nodev 1 2
به خاطر داشته باشید که برای ایجاد یک پارتیشن جدید باید از فرمانهای fdisk و mkfs.ext3 استفاده کنید.
۳) ورود به تنظیمات اساسی لینوکس در /etc/sysctl.conf
با استفاده از /etc/sysctl.conf میتوانید به تنظیمات شبکه و کرنل لینوکس دسترسی پیدا کنید.
# Avoid a smurf attack net.ipv4.icmp_echo_ignore_broadcasts = 1 # Turn on protection for bad icmp error messages net.ipv4.icmp_ignore_bogus_error_responses = 1 # Turn on syncookies for SYN flood attack protection net.ipv4.tcp_syncookies = 1 # Turn on and log spoofed, source routed, and redirect packets net.ipv4.conf.all.log_martians = 1 net.ipv4.conf.default.log_martians = 1 # No source routed packets here net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Turn on reverse path filtering net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Make sure no one can alter the routing tables net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv4.conf.all.secure_redirects = 0 net.ipv4.conf.default.secure_redirects = 0 # Don't act as a router net.ipv4.ip_forward = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.default.send_redirects = 0 # Turn on execshild kernel.exec-shield = 1 kernel.randomize_va_space = 1 # Tuen IPv6 net.ipv6.conf.default.router_solicitations = 0 net.ipv6.conf.default.accept_ra_rtr_pref = 0 net.ipv6.conf.default.accept_ra_pinfo = 0 net.ipv6.conf.default.accept_ra_defrtr = 0 net.ipv6.conf.default.autoconf = 0 net.ipv6.conf.default.dad_transmits = 0 net.ipv6.conf.default.max_addresses = 1 # Optimization for port usefor LBs # Increase system file descriptor limit fs.file-max = 65535 # Allow for more PIDs (to reduce rollover problems); may break some programs 32768 kernel.pid_max = 65536 # Increase system IP port limits net.ipv4.ip_local_port_range = 2000 65000 # Increase TCP max buffer size setable using setsockopt() net.ipv4.tcp_rmem = 4096 87380 8388608 net.ipv4.tcp_wmem = 4096 87380 8388608 # Increase Linux auto tuning TCP buffer limits # min, default, and max number of bytes to use # set max to at least 4MB, or higher if you use very high BDP paths # Tcp Windows etc net.core.rmem_max = 8388608 net.core.wmem_max = 8388608 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_window_scaling = 1
۴) حذف تمام ماژولهای ناخواسته Nginx
شما میبایست تعداد ماژولهایی را که مستقیماً در وبسرور Nginx کامپایل میشوند، به حداقل برسانید. این موضوع باعث میشود که با محدود کردن عملکردهای وبسرور، میزان ریسک به کمترین حدّ ممکن برسد. میتوانید nginx را تنها با ماژولهای مورد نیاز تنظیم و نصب نمایید. به عنوان مثال، برای غیرفعالکردن ماژولهای SSI و autoindex داریم:
# ./configure --without-http_autoindex_module --without-http_ssi_module # make # make install
اگر میخواهید ببنید که امکان فعال و غیرفعالکردن کدامیک از ماژولها برای وبسرور Nginx وجود دارد، از فرمان زیر استفاده کنید:
# ./configure --help | less
در نتیجه، ماژولهای nginx غیرضروری را میتوانید حذف کنید.
تغییر تیتر نسخه Nginx ( به صورت اختیاری)
برای ویرایش فایل src/http/ngx_http_header_filter_module.c، فرمان زیر را تایپ کنید:
# vi +48 src/http/ngx_http_header_filter_module.c
خطوط زیر را پیدا کنید…
static char ngx_http_server_string[] = "Server: nginx" CRLF; static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
و آنها را به صورت زیر تغییر دهید:
static char ngx_http_server_string[] = "Server: Ninja Web Server" CRLF; static char ngx_http_server_full_string[] = "Server: Ninja Web Server" CRLF;
حالا فایل را ذخیره کرده و ببندید. اکنون میتوانید سرور را کامپایل کنید. در فایل nginx.conf، خط زیر را وارد کنید تا نمایش نسخه nginx در تمام صفحات خطای خودکار متوقف شود:
server_tokens off
۵) استفاده از ابزار mod_security (در سرورهای پشتیبان آپاچی)
ابزار mod_security موجب ایجاد یک فایروال در سطح برنامه سرور آپاچی میشود. با نصب این ابزار میتوانید جلوی بسیاری از حملات نفوذ مخرب را بگیرید.
۶) نصب ابزار امنیتی SELinux برای ارتقای امنیت وبسرور Nginx
این یک واقعیت است که SELinux به صورت پیشفرض از وبسرور nginx محافظت نمیکند. با این وجود، شما میتوانید عملیات نصب و ارتقای امنیت را به صورت زیر انجام دهید. ابتدای نصب نیاز به پشتیبانی زمانی کامپایل SELinux خواهید داشت:
# yum -y install selinux-policy-targeted selinux-policy-devel
از طریق صفحه پروژه، ابزار امنیتی SELinux را به منظور ارتقای وبسرور nginx دریافت کنید:
# cd /opt # wget 'http://downloads.sourceforge.net/project/selinuxnginx/se-ngix_1_0_10.tar.gz?use_mirror=nchc'
برای این فایل، فرمان tar را اجرا کنید:
# tar -zxvf se-ngix_1_0_10.tar.gz
برای کامپایل همین فایل:
# cd se-ngix_1_0_10/nginx # make
نمونه خروجی
Compiling targeted nginx module /usr/bin/checkmodule: loading policy configuration from tmp/nginx.tmp /usr/bin/checkmodule: policy configuration loaded /usr/bin/checkmodule: writing binary representation (version 6) to tmp/nginx.mod Creating targeted nginx.pp policy package rm tmp/nginx.mod.fc tmp/nginx.mod
نصب ماژول nginx.pp SELinux
# /usr/sbin/semodule -i nginx.pp
۷) فایروال بر اساس جدول محدودکننده IP ها
اسکریپتهایی که در ادامه می آیند، همه چیز را بلوکه کرده و تنها به موارد زیر اجازه میدهند:
- ورودیهای HTTP (تیسیپی با پورت 80)
- درخواستهای ورودی پینگ ICMP
- درخواستهای خروجی ntp با پورت ۱۲۳
- درخواستهای خروجی smtp با پورت تیسیپی ۲۵
#!/bin/bash IPT="/sbin/iptables" #### IPS ###### # Get server public ip SERVER_IP=$(ifconfig eth0 | grep 'inet addr:' | awk -F'inet addr:' '{ print $2}' | awk '{ print $1}') LB1_IP="204.54.1.1" LB2_IP="204.54.1.2" # Do some smart logic so that we can use damm script on LB2 too OTHER_LB="" SERVER_IP="" [[ "$SERVER_IP" == "$LB1_IP" ]] && OTHER_LB="$LB2_IP" || OTHER_LB="$LB1_IP" [[ "$OTHER_LB" == "$LB2_IP" ]] && OPP_LB="$LB1_IP" || OPP_LB="$LB2_IP" ### IPs ### PUB_SSH_ONLY="122.xx.yy.zz/29" #### FILES ##### BLOCKED_IP_TDB=/root/.fw/blocked.ip.txt SPOOFIP="127.0.0.0/8 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8 169.254.0.0/16 0.0.0.0/8 240.0.0.0/4 255.255.255.255/32 168.254.0.0/16 224.0.0.0/4 240.0.0.0/5 248.0.0.0/5 192.0.2.0/24" BADIPS=$( [[ -f ${BLOCKED_IP_TDB} ]] && egrep -v "^#|^$" ${BLOCKED_IP_TDB}) ### Interfaces ### PUB_IF="eth0" # public interface LO_IF="lo" # loopback VPN_IF="eth1" # vpn / private net ### start firewall ### echo "Setting LB1 $(hostname) Firewall..." # DROP and close everything $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP # Unlimited lo access $IPT -A INPUT -i ${LO_IF} -j ACCEPT $IPT -A OUTPUT -o ${LO_IF} -j ACCEPT # Unlimited vpn / pnet access $IPT -A INPUT -i ${VPN_IF} -j ACCEPT $IPT -A OUTPUT -o ${VPN_IF} -j ACCEPT # Drop sync $IPT -A INPUT -i ${PUB_IF} -p tcp ! --syn -m state --state NEW -j DROP # Drop Fragments $IPT -A INPUT -i ${PUB_IF} -f -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL ALL -j DROP # Drop NULL packets $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " NULL Packets " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL NONE -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,RST SYN,RST -j DROP # Drop XMAS $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " XMAS Packets " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP # Drop FIN packet scans $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " Fin Packets Scan " $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags FIN,ACK FIN -j DROP $IPT -A INPUT -i ${PUB_IF} -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP # Log and get rid of broadcast / multicast and invalid $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j LOG --log-prefix " Broadcast " $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type broadcast -j DROP $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j LOG --log-prefix " Multicast " $IPT -A INPUT -i ${PUB_IF} -m pkttype --pkt-type multicast -j DROP $IPT -A INPUT -i ${PUB_IF} -m state --state INVALID -j LOG --log-prefix " Invalid " $IPT -A INPUT -i ${PUB_IF} -m state --state INVALID -j DROP # Log and block spoofed ips $IPT -N spooflist for ipblock in $SPOOFIP do $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j LOG --log-prefix " SPOOF List Block " $IPT -A spooflist -i ${PUB_IF} -s $ipblock -j DROP done $IPT -I INPUT -j spooflist $IPT -I OUTPUT -j spooflist $IPT -I FORWARD -j spooflist # Allow ssh only from selected public ips for ip in ${PUB_SSH_ONLY} do $IPT -A INPUT -i ${PUB_IF} -s ${ip} -p tcp -d ${SERVER_IP} --destination-port 22 -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -d ${ip} -p tcp -s ${SERVER_IP} --sport 22 -j ACCEPT done # allow incoming ICMP ping pong stuff $IPT -A INPUT -i ${PUB_IF} -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -m limit --limit 30/sec -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT # allow incoming HTTP port 80 $IPT -A INPUT -i ${PUB_IF} -p tcp -s 0/0 --sport 1024:65535 --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A OUTPUT -o ${PUB_IF} -p tcp --sport 80 -d 0/0 --dport 1024:65535 -m state --state ESTABLISHED -j ACCEPT # allow outgoing ntp $IPT -A OUTPUT -o ${PUB_IF} -p udp --dport 123 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p udp --sport 123 -m state --state ESTABLISHED -j ACCEPT # allow outgoing smtp $IPT -A OUTPUT -o ${PUB_IF} -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT $IPT -A INPUT -i ${PUB_IF} -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT ### add your other rules here #### ####################### # drop and log everything else $IPT -A INPUT -m limit --limit 5/m --limit-burst 7 -j LOG --log-prefix " DEFAULT DROP " $IPT -A INPUT -j DROP exit 0
۸) کنترل حملات جریان بافر
برای این منظور، فایل nginx.conf را ویرایش کرده و محدودیت بافر را برای همه کلاینتها تنظیم کنید.
# vi /usr/local/nginx/conf/nginx.conf
برای ویرایش و تنظیم مقادیر بافر وبسرور Nginx برای کلاینتها به صورت زیر عمل میکنیم:
## Start: Size Limits & Buffer Overflows ## client_body_buffer_size 1K; client_header_buffer_size 1k; client_max_body_size 1k; large_client_header_buffers 2 1k; ## END: Size Limits & Buffer Overflows ##
که در آن:
client_body_buffer_size 1k – مقدار مشخصکننده اندازه بافر برای بدنه متن درخواستی از کلاینت (پیشفرض ۸ یا ۱۶ کیلوبایت)
client_header_buffer_size 1k – مقدار مشخصکننده اندازه هدربافر برای هدر درخواستی از کلاینت. برای جلوگیری از مشکلات عمدهای که در درخواستها پیش میآیند، مقدار یک کیلو مناسب خواهد بود. در عین حال، اگر یک هدر سفارشی دارید و یا اینکه یک کوکی با ابعاد بزرگ از طرف کلاینت ارسال میشود، حتماً باید آن را افزایش دهید.
client_max_body_size 1k– مقدار مشخصکننده حداکثر اندازه قابلقبول برای متن درخواستی کلاینت. این مقدار توسط خط طول محوا در تیتر درخواست مشخص میشود. اگر اندازه بیشتر از مقدار داده شده باشد، کلاینت با پیغام خطای زیر روبرو خواهد شد:
Request Entity Too Large (413)
در صورتی که با روش POST فایلها را آپلود میکنید، باید این مقدار را افزایش دهید.
large_client_header_buffers 2 1k –کمقدار مشخصکننده حداکثر تعداد و ابعاد بافرها برای تیترهای قابلخواندن از طریق کلاینت. به صورت پیشفرض، اندازه یک بافر برابر اندازه یک صفحه تنظیم شده است؛ موضوعی که نسبت به پلتفرم، برابر ۴ یا ۸ کیلوبایت خواهد بود. دو مقدار یک کیلوبایت، داده آدرس اینترنتی به میزان ۲ کیلوبایت را قبول میکنند که چنین چیزی میتواند جلوی رباتهای بدافزار و حملات داس را بگیرد.
در همین حال، باید مقادیر timeout را برای بهبود عملکرد سرور و کلاینتها تنظیم کنید. ویرایش این مقادیر به صورت زیر انجام میگیرد:
## Start: Timeouts ## client_body_timeout 10; client_header_timeout 10; keepalive_timeout 5 5; send_timeout 10; ## End: Timeouts ##
client_body_timeout 10; – مقدار مشخصکننده زمان تایماوت برای متن درخواستی از کلاینت. تایماوت تنها زمانی تنظیم میشود که بدنه تنها در یک ریداستپ دریافت نشود. اگر کلاینت در این فاصله زمانی چیزی ارسال نکند، سرور انجینیکس پیغام خطای زیر را نشان خواهد داد:
Request time out (408)
مقدار پیشفرض برای این متغیر برابر ۶۰ خواهد بود.
client_header_timeout 10; – مقدار مشخصکننده زمان تایماوت برای عنوان درخواست کلاینت. این تایماوت زمانی تنظیم میشود که هدر یا عنوان در یک ریداستپ دریافت نشود. اگر کلاینت بعد از این زمان چیزی ارسال نکند، سرور انجینیکس پیغام خطای زیر را نشان خواهد داد:
Request time out (408)
keepalive_timeout 5 5; – اولین پارامتر زمان پایان حفظ ارتباط با کلاینت را مشخص میکند. بعد از این فاصله زمانی است که سرور ارتباط را قطع خواهد کرد. دومین پارامتر که به صورت اختیاری است، مقدار زمان را برای هدر مشخص میکند. این هدر برخی مرورگرهای وب را مجاب میکند که اتصال را قطع کنند.
send_timeout 10; – مقدار مشخصکننده زمان تایماوت برای واکنش کلاینت. تایماوت زمان کلی انتقال پاسخ را درنظر نمیگیرد؛ بلکه ملاک فاصله بین دو عملیات خواندن صفحه است. اگر کلاینت در این فاصله واکنشی نشان ندهد، انجینیکس کل ارتباط را خاتمه میدهد.
۹) کنترل ارتباطهای مشابه
امکان استفاده از ماژول NginxHttpLimitZone برای محدود کردن تعداد ارتباطهای مشابه در یک مقطع زمانی خاص، و از طرف یک IP وجود خواهد داشت. برای این منظور باید فایل nginx.conf را ویرایش کنید:
### Directive describes the zone, in which the session states are stored i.e. store in slimits. ### ### 1m can handle 32000 sessions with 32 bytes/session, set to 5m x 32000 session ### limit_zone slimits $binary_remote_addr 5m; ### Control maximum number of simultaneous connections for one session i.e. ### ### restricts the amount of connections from a single ip address ### limit_conn slimits 5;
تنظیمات بالا موجب میشود که کلاینتهای ریموت نتوانند بیشتر از ۵ ارتباط باز برای هر آدرس IP داشته باشند.
۱۰) مجوز دسترسی تنها به IP خودمان
اگر یک ربات تنها یک اسکن سرور برای تمام دامینها انجام میدهد، بهراحتی میتوانید جلوی آن را بگیرید. شما فقط باید به دامینهای مجازی معتبر یا درخواستهای reverse proxy مجوز بدهید. در صورتی که بخواهید درخواستهای یک IP خاص نشان داده نشوند، به صورت زیر عمل میکنید:
## Only requests to our Host are allowed i.e. ariaservice.net, images.ariaservice.net and www. ariaservice.net if ($host !~ ^( ariaservice.net|www.ariaservice.net|images.ariaservice.net)$ ) { return 444; } ##
۱۱) محدود کردن روشهای در دسترس
فرمانهای GET و POST از متداولترین روشها در اینترنت هستند. روشهای مرتبط با وبسرور به صورت کامل در راهنمای RFC 2616 آورده شدهاند. به شکل زیر میتوان تنها به روشهای GET، HEAD و POST اجازه ورود داد:
## Only allow these request methods ## if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 444; } ## Do not accept DELETE, SEARCH and other methods ##
توضیح روشهای اچتیتیپی
روش GET برای درخواست یک سند مانند http://www.ariaservice.net/index.php به کار میرود.
روش HEAD به GET شباهت دارد؛ با این تفاوت که در آن سرور نباید متن پیام را در پاسخ داشته باشد.
روش POST ممکن هر چیزی را دربر داشته باشد؛ از جمله ذخیره یا بروزرسانی داده، سفارش یک محصول یا ارسال یک ایمیل با تکمیل یک فرم. چنین چیزی معمولاً با اسکریپتهای جانبی سرور مانند PHP، PERL و Python پردازش میشود. اگر میخواهید فایل در سرور ارسال کنید و فرمها را پردازش نمایید، باید از این روش استفاده کنید.
۱۲) چگونه میتواند برخی کاربران خاص را گرفت؟
برای کاربران جعلی مانند اسکنرها، رباتها و اسپمرها که میخواهند از سرور شما سوء استفاده کنند، این کار به راحتی صورت میگیرد:
## Block download agents ## if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; } ##
بلوکه کردن رباتهای با عناوین msnbot و scrapbot:
## Block some robots ## if ($http_user_agent ~* msnbot|scrapbot) { return 403; }
جلوگیری از اسپمهای ارجاعدهنده
اسپم ارجاعدهنده واقعاً خطرناک است. این ابزار میتواند به رتبهبندی سئو به میزان قابلملاحظهای آسیب بزند؛ چرا که بازدیدکنندگان را به سایت اسپم خود ارجاع خواهد داد. با استفاده از خطوط زیر میتوانید دسترسی به اسپمهای ارجاعدهنده را محدود کنید:
## Deny certain Referers ### if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) ) { # return 404; return 403; } ##
۱۳) چگونه جلوی هاتلینکینگ تصاویر را بگیریم؟
هاتلینکینگ تصویر یا اچتمل به این معناست که شخصی به یکی از تصاویر وبسایت شما لینک میدهد، ولی آن را در وبسایت خود به نمایش درمیآورد. در نتیجه، شما پول پهنای باند را میپردازید، در حالی که بخش از آن به ظاهر یک وبسایت دیگر اختصاص مییابد. چنین چیز معمولاً در تالارهای گفتگو یا بلاگها اتفاق میافتد. توصیه میشود که در سطح سرور این دسترسی را محدود کنید:
# Stop deep linking or hot linking location /images/ { valid_referers none blocked www.example.com example.com; if ($invalid_referer) { return 403; } }
مثال: باز نویسی و نمایش تصویر
یک مثال دیگر با لینک به یک تصویر مسدود شده:
valid_referers blocked www.example.com example.com; if ($invalid_referer) { rewrite ^/images/uploads.*\.(gif|jpg|jpeg|png)$ http://www.examples.com/banned.jpg last }
۱۴) محدودیتهای دایرکتوری
میتوانید برای یک دایرکتوری خاص، محدودیت دسترسی ایجاد کنید. تمام دایرکتوریهای وب باید بر اساس موقعیتهای خاص تنظیم شوند و دسترسی به آنها تنها در زمان نیاز مقدور باشد.
محدودیت دسترسی بر اساس آدرس IP
ایجاد محدودیت دسترسی به دایرکتور /docs/ بر اساس آدرس IP
location /docs/ { ## block one workstation deny 192.168.1.1; ## allow anyone in 192.168.1.0/24 allow 192.168.1.0/24; ## drop rest of the world deny all; }
محافظت از دایرکتوری با کلمه عبور
ابتدا یک فایل پسورد ایجاد کرده و یک کاربر با عنوان vivek اضافه کنید:
# mkdir /usr/local/nginx/conf/.htpasswd/ # htpasswd -c /usr/local/nginx/conf/.htpasswd/passwd vivek
فایل nginx.conf را ویرایش کرده و به صورت زیر از دایرکتوریهای موردنیاز محافظت کنید:
### Password Protect /personal-images/ and /delta/ directories ### location ~ /(personal-images/.*|delta/.*) { auth_basic "Restricted"; auth_basic_user_file /usr/local/nginx/conf/.htpasswd/passwd; }
بعد از اینکه فایل پسورد تولید شد، کاربران دیگر را میتوانید با استفاده از فرمان زیر اضافه کنید:
# htpasswd -s /usr/local/nginx/conf/.htpasswd/passwd username
۱۵) تنظیمات اساسال وبسرور Nginx
اچتیتیپی یک پروتکل با متن ساده است و بهآسانی میتوان آن را مورد پایش غیرمستقیم قرار داد. بر این اساس، شما میبایست با استفاده از SSL به رمزنگاری محتوا برای کاربرانتان اقدام کنید.
۱۶) تنظیمات امنیتی پیاچبی برای وبسرور Nginx
پیاچپی یکی از محبوبترین زبانهای برنامهنویسی برای سرورهاست. برای تنظیمات امنیتی موردنظر، فایل /etc/php.ini را به صورت زیر ویرایش میکنیم:
# Disallow dangerous functions disable_functions = phpinfo, system, mail, exec ## Try to limit resources ## # Maximum execution time of each script, in seconds max_execution_time = 30 # Maximum amount of time each script may spend parsing request data max_input_time = 60 # Maximum amount of memory a script may consume (8MB) memory_limit = 8M # Maximum size of POST data that PHP will accept. post_max_size = 8M # Whether to allow HTTP file uploads. file_uploads = Off # Maximum allowed size for uploaded files. upload_max_filesize = 2M # Do not expose PHP error messages to external users display_errors = Off # Turn on safe mode safe_mode = On # Only allow access to executables in isolated directory safe_mode_exec_dir = php-required-executables-path # Limit external access to PHP environment safe_mode_allowed_env_vars = PHP_ # Restrict PHP information leakage expose_php = Off # Log all errors log_errors = On # Do not register globals for input data register_globals = Off # Minimize allowable PHP post size post_max_size = 1K # Ensure PHP redirects appropriately cgi.force_redirect = 0 # Disallow uploading unless necessary file_uploads = Off # Enable SQL safe mode sql.safe_mode = On # Avoid Opening remote files allow_url_fopen = Off
۱۷) در صورت امکان وبسرور Nginx را در یک فضای ایزوله یا اصطلاحاً Chroot Jail اجرا کنید.
چنین کاری خطر نفوذ بالقوه به سیستم را به میزان قابلملاحظهای کاهش میدهد. شما میتوانید تنظیمات بسیار ساده ایزولهسازی را برای وبسرور nginx به کار ببرید. FreeBSD jails، XEN، لینوکس کانتینرز در دبیان/اوبونتو، LXD در فدورا و OpenVZ، همگی میتوانند ابزاری برای این منظور باشند.
۱۸) محدودیت تعداد ارتباط برای هر IP در سطح فایروال
یک سرور همیشه باید نگران ارتباط ها باشد و ارتباط برای هر IP را محدود کند. این یکی از کارهای اساسی در سرورهاست. در مثال زیر مشاهده میکنیم که سرور در صورتی که یک IP در طول ۶۰ بیشتر از ۱۵ تلاش برای ارتباط به پورت ۸۰ داشته باشد، ارتباط را قطع خواهد کرد:
/sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set /sbin/iptables -A INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 15 -j DROP service iptables save
BSD PF: ایجاد محدودیت برای ارتباطات وبسرور Nginx در هر ثانیه
فایل /etc/pf.conf را ویرایش کرده و مطابق زیر، آن را بروزرسانی کنید. در اینجا تعداد ارتباطات برای هر منبع به ۱۰۰ عدد محدود شده است. مقدار 15/5 مشخصکننده تعداد ارتباطها در ثانیه یا یک بازه زمانی است. به عبارت دیگر محدودیت تعداد ارتباط ها ۱۶ است که در یک بازه ۵ ثانیهای اِعمال میشود. اگر هر کسی از این قوانین تخطّی کند، به جدول IPهای مخرب راه پیدا خواهد کرد و تمام ارتباطات آن بلوکه خواهد شد.
webserver_ip=”202.54.1.1” table <abusive_ips> persist block in quick from <abusive_ips> pass in on $ext_if proto tcp to $webserver_ip port www flags S/SA keep state (max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_ips> flush)
تمام مقادیر را میتوانید به نسبت نیازها و ترافیکی که در اختیار دارید، تغییر دهید. درنظر داشته باشید که مرورگرها میتوانند ارتباطهای چندگانه با سایت شما داشته باشند.
۱۹) تنظیم سیستمعامل برای محافظت از وبسرور
ابزار SELinux را مطابق دستورالعمل گفتهشده، فعال کنید. مجوزها را در آدرس سند /nginx بهدرستی تنظیم کنید. سرور nginx به صورت کاربری با عنوان nginx راهاندازی میشود. با این وجود فایلهای موجود در آدرس /nginx یا /usr/local/nginx/html نباید به مالکیت آن کاربر درآیند یا توسط آن ویرایش شوند. برای پیدا کردن فایلهایی که مجوزهای نادرست دارند، داریم:
# find /nginx -user nginx # find /usr/local/nginx/html -user nginx
مطمئن شوید که حتماً مالکیت فایل را به کاربر روت یا دیگر کاربرها انتقال دادهاید:
# ls -l /usr/local/nginx/html/
نمونه خروجی:
-rw-r--r-- 1 root root 925 Jan 3 00:50 error4xx.html -rw-r--r-- 1 root root 52 Jan 3 10:00 error5xx.html -rw-r--r-- 1 root root 134 Jan 3 00:52 index.html
در همین حال، باید فایلهای پشتیبان ناخواستهای که توسط vi یا دیگر ویرایشگرهای متنی ایجاد شدهاند را حذف کنید:
# find /nginx -name '.?*' -not -name .ht* -or -name '*~' -or -name '*.bak*' -or -name '*.old*' # find /usr/local/nginx/html/ -name '.?*' -not -name .ht* -or -name '*~' -or -name '*.bak*' -or -name '*.old*'
با استفاده از گزینه –delete در فرمان find، از دست فایلهای موردنظر راحت میشوید.
۲۰) محدود کردن ارتباطات خروجی انجینیکس
مهاجمان فایلها را به صورت محلی و با استفاده از ابزارهایی مانند wget روی سرور شما دریافت میکنند. با استفاده از iptable ها میتوانید جلوی ارتباطات خروجی کاربر nginx را بگیرید. ماژول ipt_owner سعی میکند که مشخصههای مختلف یک بسته داخلی را با سازنده آن تطبیق دهد. این ماژول تنها در زنجیره OUTPUT یافت میشود.
در این مثال، به کاربر vivek اجازه داده میشود که با استفاده از پورت ۸۰، ارتباط خروجی داشته باشد؛ موضوعی که برای دسترسی RHN یا دریافت بروزرسانیهای CentOS مفید خواهد بود.
/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner vivek -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
این دستور را به اسکریپت پایه iptable خود اضافه کنید. در همین حال، به کاربر nginx اجازه ندهید که ارتباط خارجی داشته باشد.
۲۱) نرمافزار خود را همیشه بهروز نگه دارید.
همیشه باید نرمافزار و کرنل خود را بهروز نگه دارید. اگر کاربر لینوکس دبیان یا اوبونتو هستید، میتوانید با استفاده از فرمان apt-get و دریافت پچها، آنها را بروزرسانی کنید.
$ sudo apt-get update $ sudo apt-get upgrade
اگر از لینوکسهای خانواده RHEL/CentOS/Oracle/Scientific استفاده میکنید، فرمان yum به کمک شما میآید:
$ sudo yum update
ضمن اینکه در لینوکس آلپاین، باید از فرمان apk استفاده کنید:
# apk update # apk upgrade
۲۲) جلوگیری از دزدیِ کلیک یا کلیکجکینگ
خط زیر را در تنظیمات nginx.conf یا دامین مجازیتان وارد کنید تا از کلیکجکینگ جلوگیری کنید:
add_header X-Frame-Options SAMEORIGIN;
۲۳) غیرفعالکردن استفاده از متن محتوا در برخی مرورگرها
برای این منظور، در nginx.conf یا دامین مجازیتان، خط زیر را اضافه نمایید:
add_header X-Content-Type-Options nosniff;
فعالکردن اسکریپتهای اشتراکی XSS نیز با اضافهکردن خط زیر صورت میگیرد:
add_header X-XSS-Protection "1; mode=block";
۲۴) اجبار به استفاده از HTTPS
هیچ دلیلی برای استفاده از HTTP وجود ندارد. باید همه را به صورت پیشفرض، مجبور به استفاده از HTTPS کنید.
۲۵) پایش وبسرور nginx
با استفاده از ابزار Stub Status میتوانید تعداد کلی درخواستهای کلاینت و دیگر اطلاعات را مشاهده کنید.
ترفند اضافه: بررسی تاریخچه عملکرد و حسابرسی سرور
فایلهای تاریخچه را بررسی کنید. این فایلها به شما درکی از حملات صورت گرفته به سرور ارائه میدهند. در صورت نیاز میتوانید، سطح امنیتی سرور خود را افزایش دهید.
# grep "/login.php??" /usr/local/nginx/logs/access_log # grep "...etc/passwd" /usr/local/nginx/logs/access_log # egrep -i "denied|error|warn" /usr/local/nginx/logs/error_log
ضمن اینکه سرویس auditd برای حسابرسی سیستم ارائه شده است. این سرویس را میتوانید برای اهدافی مانند اتفاقات مرتبط با SELinux، تأیید دسترسی، اصلاح فایلها و حسابهای کاربری استفاده کنید.
جمعبندی
اگر تمام موارد بالا را رعایت کرده باشید، اینک وبسرور nginx شما به شکل مناسبی حفاظت شده است. هماکنون میتوانید با خیال راحت صفحات وب خود را در اختیار همگان قرار دهید. در همین حال، باید توجه داشته باشید که همیشه باید از منابع بیشتر برای ارتقای امنیت سرور استفاده کنید. به عنوان مثال، درنظر بگیرید که وردپرس یا هر برنامه ثالث دیگر نیازمند اقدامات امنیتی خاص خود خواهد بود.