Модуль nginx для борьбы с DDoS

Наткнулся тут на хабре на интереснейшую статью по борьбе с DDOS средствами самого nginx  и спешу поделиться находкой со всеми:

Многие сталкивались с таким явлением как DDoS атака методом HTTP флуда. Нет, это не очередной туториал по настройке nginx, хочу представить свой модуль, работающий как быстрый фильтр между ботами и бэкэндом во время L7 DDoS атаки и позволяющий отсеивать мусорные запросы.

Модуль умеет

 

  • Ставить cookies стандартным способом через HTTP заголовок Set-Cookie. После установки cookies перенаправлять пользователя (заставить отправить нам полученные cookies) используя код ответа 301 и заголовок Location
  • После установки cookies перенаправлять пользователя (заставить отправить нам полученные cookies) используя код ответа 200 и HTML тег Meta «refresh»
  • Считать количество попыток поставить cookies и отправлять пользователя по заданному URL после превышения максимального количества неудачных попыток
  • Использовать custom шаблоны для ответа фильтра, в которых можно делать что угодно (например, выставить cookies через JavaScript)
  • Для предотвращения автоматического парсинга ответов нацеленных на исполнение JavaScript, шифровать значение переменных в шаблоне симметричным криптоалгоритмом с дальнейшей расшифровкой через JavaScript на стороне клиента (используя SlowAES)
  • Whitelist’ить заданные сети (например, сети в которых живут поисковые роботы)
  • Кое-какие мелкие фишки полезные во время DoS атаки.

Не умеет

 

  • Модуль лишь возвращает клиенту заданные ответы, принимать решение о блокировке клиента (например, используя fail2ban) вы должны самостоятельно
  • Кто-то скажет — «Я сэмулирую JavaScript», но давайте будем реалистами — часто вас DoS’ят ботами с полноценной эмуляцией? отправьте их ко мне, будем майнить bitcoin’ы
  • В документации ничего нет про captcha и flash — если нужно, вы можете прикрутить их самостоятельно, нужно лишь проявить фантазию при конфигурации
  • Данный модуль не панацея — это лишь маленький компонент в комплексе защитных мер, инструмент, который может помочь, если его правильно использовать.

Как это работает

Чаще всего, боты, реализующие HTTP флуд довольно тупые, и не имеют механизмов HTTP Cookie и редиректа. Иногда попадаются более продвинутые — такие могут использовать cookies и обрабатывать редиректы, но почти никогда DoS бот не несет в себе полноценного JavaScript движка.
Для понимания принципа работы фильтра ниже приведен flow общения клиент-сервер в зависимости от сценария атаки.

  1. Боты не понимают редиректы и cookies
  2. Боты понимают редиректы и cookie, но не умеют JavaScript

Примеры конфигурации для основных сценариев атак

 

    • боты не понимают редиректы и cookies (типичный случай)

server {

listen 80;
server_name domain.com;
testcookie off;
testcookie_name BPC;
testcookie_secret keepmescret;
testcookie_session $remote_addr;
testcookie_arg attempt;
testcookie_max_attempts 3;
testcookie_fallback /cookies.html?backurl=http://$host$request_uri;
testcookie_get_only on;
location = /cookies.html {
root /var/www/public_html;
}

location / {
testcookie on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}

    • боты понимают редиректы и cookies

server {
listen 80;
server_name domain.com;

testcookie off;
testcookie_name BPC;
testcookie_secret keepmescret;
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_template ‘<html><body><script>document.cookie=»BPC=$testcookie_set»;document.location.href=»$testcookie_nexturl»;</script></body></html>’;

location = /cookies.html {
root /var/www/public_html;
}
location / {
testcookie on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}

    • защищаемый URL вставили в iframe на популярном сайте

server {
listen 80;
server_name domain.com;
testcookie off;
testcookie_name BPC;
testcookie_secret keepmescret;
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_template ‘<html><body><script>function bla() { document.cookie=»BPC=$testcookie_set»;document.location.href=»$testcookie_nexturl»;}</script><input type=»submit» value=»click me» onclick=»bla();»></body></html>’;

location = /cookies.html {
root /var/www/public_html;
}

location / {
testcookie on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}

    • боты научились вытаскивать значение cookies через regexp

server {
listen 80;
server_name domain.com;

testcookie off;
testcookie_name BPC;
testcookie_secret keepmescret;
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=»BPC=»+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>’;

location = /aes.min.js {
gzip on;
gzip_min_length 1000;
gzip_types text/plain;
root /var/www/public_html;
}

location = /cookies.html {
root /var/www/public_html;
}

location / {
testcookie on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}

    • боты научились вытаскивать параметры через regexp и расшифровывать значение cookies (сомневаюсь, что кто-то будет возиться)

server {
listen 80;
server_name domain.com;

testcookie off;
testcookie_name BPC;
testcookie_secret keepmescret;
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 deadbeefdeadbeefdeadbeefdeadbeef; #меняем по крону
testcookie_refresh_encrypt_cookie_iv deadbeefdeadbeefdeadbeefdeadbeef; #меняем по крону

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({используем любимый JS обфускатор чтобы спрятать значение iv, меняем по крону}),b=toNumbers({используем любимый JS обфускатор чтобы спрятать значение ключа, меняем по крону}),c=toNumbers(«$testcookie_enc_set»);document.cookie=»BPC=»+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>’;

location = /aes.min.js {
gzip on;
gzip_min_length 1000;
gzip_types text/plain;
root /var/www/public_html;
}

location = /cookies.html {
root /var/www/public_html;
}

location / {
testcookie on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:8080;
}
}

 

Исходные тексты

Модуль с инструкциями по установке и документацией доступен на github под BSD лицензией.

(c)Habr

Вы можете следить за ответами к этой записи через RSS.
Вы можете оставить отзыв или трекбек со своего сайта.

Ваш отзыв

К сожалению, по вашему запросу ничего не найдено.