Nginx: автоматическая защита от парсинга и DDoS-атак

В своей прошлой статье я писал о возможности применения данного способа защиты от атак с помощью модуля Nginx testcookie. Сегодня мы более подробно остановимся на реализации скрипта, который автоматически будет включать защиту, обновляя конфиг и отправляя уведомление на email при срабатывании.

Устанавливаем и включаем модуль:

yum install nginx-module-testcookie

# /etc/nginx/module.inc.conf
load_module modules/ngx_http_testcookie_access_module.so;

Скрипт /srv/scripts/check_ddos.sh выглядит следующим образом и работает довольно просто. Он мониторит LA и количество коннектов к nginx. При превышении установленных порогов LA_ACTIVATE или NGINX_CONNECT включает тесткуку и отправляет письмо на email. При снижении LA ниже порога LA_DEACTIVATE, скрипт выключает тесткуку:

#!/bin/sh

NGINX_CONF=/srv/www/nagg.ru/conf/nginx.conf
MAIL="" # true is enable send mail
MAILTO=root
LA_ACTIVATE=17
LA_DEACTIVATE=5
NGINX_CONNECT=1000

########################################################
TMPLOG=/tmp/testcookie_module.tmp
NGINXCONN=`curl -s http://localhost/nginx-status | grep "Active" | awk '{print($3)}'`
LA=`cat /proc/loadavg | awk -F '.' '{print($1)}'`

function e {
    echo -en $(date "+%F %T"): "$1"
}

if [ ! -f $TMPLOG ];then echo 0 > $TMPLOG; fi
LASTRESULT=`cat $TMPLOG`

if [ -n "$NGINXCONN" ]; then
  if [ $NGINXCONN -gt $NGINX_CONNECT ]; then
    ALERT1="1"
  fi
fi

if [ -n "$LA" ]; then
  if [ $LA -gt $LA_ACTIVATE ]; then
    ALERT2="1"
  fi
fi

ALERT=$ALERT1$ALERT2

if [ -n "$ALERT" -a $LASTRESULT -eq 0 ]; then
    e; printf "Nginx connect: %-4s LA: %-3s | Activate testcookie\n" "$NGINXCONN" "$LA"
    sed -i 's/.*##-AUTO-DDOS-LABEL-##/\ttestcookie on; ##-AUTO-DDOS-LABEL-##/g' $NGINX_CONF
    /sbin/service nginx reload >/dev/null 2>&1
    echo 1 > $TMPLOG
    if [ "$MAIL" = "true" ];then
        echo "Nginx connect $NGINXCONN, LA $LA. Nginx test-cookie enable" | mail -s "`hostname` DDOS detected. Nginx test-cookie enable" $MAILTO
    fi
fi

if [ $LA -le $LA_DEACTIVATE -a $LASTRESULT -eq 1 ]; then
    e; printf "Nginx connect: %-4s LA: %-3s | Dectivate testcookie\n" "$NGINXCONN" "$LA"
    sed -i 's/.*##-AUTO-DDOS-LABEL-##/\ttestcookie off; ##-AUTO-DDOS-LABEL-##/g' $NGINX_CONF
    /sbin/service nginx reload >/dev/null 2>&1
    echo 0 > $TMPLOG
fi

После установки rpm с собранным модулем testcookie, конфги должен выглядеть следующим образом:

nagg.ru.conf 

server {
    listen 80;
    server_name nagg.ru;

    testcookie off;
    testcookie_name RCPC;
    testcookie_secret XXXXXXXXXXXXXXXXXXXX;
    testcookie_session $remote_addr;
    testcookie_arg attempt;
    testcookie_max_attempts 3;
    testcookie_fallback /cookies.html?backurl=http://$host$request_uri;
    testcookie_get_only on;
    testcookie_redirect_via_refresh on;

    testcookie_refresh_encrypt_cookie on;
    testcookie_refresh_encrypt_cookie_key random;
    testcookie_refresh_encrypt_cookie_iv random;
    testcookie_refresh_template '<html><body>setting cookie...<script type=\"text/javascript\" src=\"/aes.min.js\" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("$testcookie_enc_key"),b=toNumbers("$testcookie_enc_iv"),c=toNumbers("$testcookie_enc_set");document.cookie="RCPC="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";document.location.href="$testcookie_nexturl";</script></body></html>';

    # добавляем в исключение IP
    testcookie_whitelist {
       X.X.X.X/32;
       Y.Y.Y.Y/32;
    }

    location = /aes.min.js {
        gzip on;
        gzip_min_length 1000;
        gzip_types text/plain;
        gzip_static on;
        root /srv/www/nagg.ru/data;
    }

    location = /cookies.html {
        root /srv/www/nagg.ru/htdocs;
    }

    location / {
testcookie off; ##-AUTO-DDOS-LABEL-##
	proxy_pass http://127.0.0.1:8080;
	proxy_set_header Proxy "";
	proxy_redirect off;
	proxy_set_header Host $host;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

	proxy_read_timeout 600;
	client_max_body_size 256m;

	proxy_buffer_size 16k;
	proxy_buffers 32 16k;
    }

    include vhost.inc.conf;
}

В локейшене обязательно должны быть файлы aes.min.js и aes.min.js.gz, скачать их можно по ссылкам. Меняем testcookie_secret и кладем в каталог с сайтом скрипт aes.min.js.

Осталось дело за малым – добавить в крон скрипт на запуск раз в минуту и применить изменения в nginx.

/etc/cron.d/check_ddos_testcookie_module
* * * * * root /srv/scripts/check_ddos.sh > >>/srv/www/nagg.ru/logs/testcookie_module-acc 2>&1

При активации скрипта необходимо выключить защиту вручную, изменив в конфиге nginx переменную «testcookie on» на «testcookie off».

Обратите внимание, при включении защиты testcookie, доступ будет осложнен не только для атакующих ботов, но и для поисковых, это серьезная проблема и одновременно причина не держать постоянно включенной защиту без необходимости, помните, вы включаете защиту только во время атаки и выключаете как атака завершится.

Related posts:

  1. Nginx защита от DDoS атак При несложных атаках, можно защититься средствами сервера, в некоторых случаях...
  2. Nginx защита от DDoS атак – продолжение Обычно атака ботов происходит на любой участок сайта, обычно это...
  3. Проксирование запросов с помощью Nginx Например стоит задача спроксировать через свой домен (mydomain.ru) ссылки вида:...
  4. Передача HTTPS приложению в связке Nginx Apache Иногда при работе по защищенному HTTPS-соединению, приложение не может определить...
  5. Nginx: принудительное кэширование сайта Резкие всплески посещаемости всегда дают о себе знать высокой нагрузкой,...
You can leave a response, or trackback from your own site.

Оставить комментарий

*