Nginx защита от DDoS (testcookie-nginx-module)

Наиболее часто для нарушения работы сайта злоумышленники используют HTTP-флуд. Для защиты от HTTP-флуда я буду использовать связку из Nginx и модуля nginx-module-testcookie

Для начала необходимо добавить репозиторий rpms.southbridge.ru в систему. Для этого выполните команду:

rpm -Uhv http://rpms.southbridge.ru/southbridge-rhel7-stable.rpm

Далее стандартной командой устанавливаем пакеты:

yum install nginx nginx-module-testcookie

С учетом того, что Nginx я обновляю достаточно редко, по ряду причин на постоянной основе я не хочу использовать выше указанный репозиторий, то я выполню установку непосредственно из скачанных rpm-пакетов:

wget http://rpms.southbridge.ru/rhel7/stable/x86_64/nginx-1.9.5-1.el7.centos.ngx.x86_64.rpm
wget http://rpms.southbridge.ru/rhel7/stable/x86_64/nginx-module-testcookie-1.15.6.1.24-1.el7.ngx.x86_64.rpm

Если в системе ранее уже был установлен Nginx, нужно его удалить. Устанавливаем Nginx и nginx-module-testcookie:

rpm -Uhv nginx-1.15.6-1.el7.ngx.x86_64.rpm
rpm -Uhv nginx-module-testcookie-1.15.6.1.24-1.el7.ngx.x86_64.rpm

Чтобы включить модуль добавьте строку ниже в файл /etc/nginx/nginx.conf:

Для включение и отключения testcookie нам необходимо периодически просматривать статистику подключений. Для этого добавьте в конфиг:

server {

    listen 80;

    server_name localhost;



    location /nginx_status {

        stub_status on;

        access_log off;

        allow 127.0.0.1;

        deny all;

    }

}

 

Применяем настройки, проверяем:

# service nginx restart
# curl http://localhost/nginx_status
Active connections: 4
server accepts handled requests
137 137 190
Reading: 0 Writing: 1 Waiting: 3
Берем файл https://github.com/duy13/vDDoS-Protection/blob/master/aes.min.js.txt и копируем его в отдельный каталог на сервере /www/public_html/aes.min.js

Добавляем в конфиг вашего сайта следующие строки:

location = /aes.min.js {

    gzip on;

    gzip_min_length 1000;

    gzip_types text/plain;

    gzip_static on;

    root /www/public_html;

}

Сохраняем настройки:

nginx reload
Проверяем, что файл доступен по адресу http://site.ru/aes.min.js

Добавляем в конфиг вашего сайта параметры по примеру ниже:

http {

    testcookie off;

    testcookie_name RCPC;

    testcookie_secret nlos7m5hYc6gNmm7NvhCZJ8W7lJHuAaV2dp73px9diYMYzKmhvrpjZLNaoK989wW;

    testcookie_session $remote_addr;

    testcookie_arg attempt;

    testcookie_max_attempts 3;

    testcookie_get_only on;

    testcookie_redirect_via_refresh on;

    testcookie_refresh_encrypt_cookie on;

    testcookie_refresh_encrypt_cookie_key ea5891045bdfddd19682146f1e88e6e8;

    testcookie_refresh_encrypt_cookie_iv ea5891045bdfddd19682146f1e88e6e8;

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







 server {

        listen 80;

        server_name test.com;



        location = /aes.min.js {

            gzip on;

            gzip_min_length 1000;

            gzip_types text/plain;

            root /var/www/public_html;

        }

        

        #Если используется проксирование, в противном случае не использовать

        location / {

            testcookie 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_pass http://127.0.0.1:80;

        }

    }

Параметр testcookie_secret заполняем случайным набором из 64 символов. Для testcookie_refresh_encrypt_cookie_key и testcookie_refresh_encrypt_cookie_iv генерируем hex число длиной 32 символа этим генератором.

Теперь осталось настроить скрипт, который будет автоматически проверять количество подключений к Nginx и в случае превышения лимита, автоматически включать testcookie и атпровлять уведомление администратору на почту.

 

#!/bin/sh



NGINX_CONF=/etc/nginx/conf.d/default.conf

MAIL="admin@site.ru"

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 testcookien" "$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 testcookien" "$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

Добавляем задание в cron:

 

* * * * * /etc/nginx/check.sh >/dev/null 2>&1