Назад | Перейти на главную страницу

Nginx - Перенаправление запроса по шаблону параметров GET

Один из моих серверов пару дней назад подвергся DDoS-атаке, которая длилась 4 дня. Ниже представлен фрагмент логов запроса:

36.224.180.253 - - [14/May/2013:03:11:46 +0800] "GET //?f5b2fd2f860dc=9597624054932145 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:11:50 +0800] "GET //?d69e553a2e8cc=8383534686131949 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:11:53 +0800] "GET //?cd28bceecb2f7=8014028628342069 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:11:59 +0800] "GET //?e39ba4d777ca3=8890936876339672 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:12:02 +0800] "GET //?3bc0dd265e14b=2334116190596257 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:12:06 +0800] "GET //?8b645989c8334=5444999657995141 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:12:09 +0800] "GET //?bb1f56833c451=7309469290160174 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"
36.224.180.253 - - [14/May/2013:03:12:11 +0800] "GET //?5fb9da415957e=3739296350043726 HTTP/1.1" 301 178 "-" "Opera/9.80 (Windows NT 6.1; WOW64) Presto/2.12.388 Version/12.14"

Не говоря уже об IP, это всего лишь один из массовых запросов. Существует более 3000+ разных IP-адресов, использующих один и тот же шаблон запросов GET.

Я использую Nginx (nginx-1.2.8-1.el6.ngx.x86_64) за Varnish (varnish-3.0.3-1.el6.x86_64).

У меня вопрос, как перенаправить такой запрос на конкретную страницу, скажем, 404.html?

Перезапись в Nginx работает только с путями, поэтому вам нужно использовать сравнение переменных отдельно, чтобы идентифицировать их. То, что вы просили, будет выглядеть так:

if ($args ~ "([a-f0-9]{12,})=([a-f0-9]{12,})" ){
    rewrite ^/$ /404_rewrite?;
}

location  /404_rewrite {
    return 404;
}
  • Соответствие аргументов должно быть заключено в кавычки, иначе { и } запутает Nginx.

  • В ? в конце перезаписи Nginx отбрасывает все параметры, а не добавляет их к перезаписанному URL-адресу.

Однако вы можете захотеть, чтобы Nginx пытался задерживать каждый запрос в DOS, а не обрабатывать их как можно быстрее.

limit_req_zone  $binary_remote_addr  zone=dos_attack:20m   rate=30r/m;

if ($args ~ "([a-f0-9]{12,})=([a-f0-9]{12,})" ){
    rewrite ^/$ /404_rewrite?;
}

location  /404_rewrite {
    limit_req   zone=dos_attack  burst=1;
    internal;
    return 404;
}

Что это значит:

  • Установите количество запросов на 30р / мин, что составляет 30 запросов в минуту или один запрос каждые две секунды.

  • Устанавливает пакет на 1. Для нормального ограничения скорости пакет устанавливается на> 1, чтобы позволить клиентам не ограничиваться, если они случайно превышают ограничение скорости в течение короткого периода времени.

  • Выделяет 20 мегабайт для хранения информации о зоне ограничения скорости. Согласно документация по ограничению скорости каждый $binary_remote_addr занимает 64 байта для хранения, поэтому это ограничение скорости будет работать до пары сотен тысяч отдельных машин, выполняющих DOS. Если бы машин было больше, ограничение скорости вышло бы из строя.