Учимся отражать микроDDoS на NGiNX
Коротко о нас.
Совместно с Центром телекоммуникаций и информационных технологий МГУ им. М.В. Ломоносова, мы занимаемся исследованиями DDoS.
Основная цель: разработать и донести до сообщества эффективные, доступные техники противодействия распределенным атакам на отказ в обслуживании.
В рамках исследовательской программы мы бесплатно предоставляем защиту. Все что нужно — передать трафик на наше оборудование любым удобным способом (изменить А запись DNS, GRE/IPIP tunnel).
В блоге проекта hll.msu.ru мы будем регулярно публиковать материалы, полученные в ходе исследований. Самые интересные случаи, методики, распространенные ошибки, — публиковать на Хабре.
В прошлую пятницу наблюдали ситуацию, в которой вполне вменяемый админ, к которому зашли в гости около 7 тыс ботов и, видимо, не очень радостный директор,
поддался панике и соорудил конструкцию вида:
NGINX -> apache -> mod_php -> memcached -> [кэшированая версия /]
Это бесспорно лучше чем генерация титульной страницы на каждый запрос с несколькими выборками для базы, но все еще недостаточно хорошо...
Настолько нехорошо, что даже те 3-8 запросов которые успевал сделать бот, до того как был распознан и забанен, создавали серьезные проблемы и время обработки запросов сервером составляло 1-2 секунды.
Вспомнив пару интересных новых “тематических” фич которые проходили за последних месяцев в NGINX, решили поупражняться в config-fu и в итоге получился вот такой вот забавный этюд…
Далее 5 минутный TTL на коленке…
Что было необходимо и достаточно чтобы остановить 5000 ботов.
В качестве дополнительной меры можно выбирать наиболее назойливых по limiting requests из error_log и отправлять их в Null либо на ближайшем раутере либо в вашем netfilter.
Подумать:
Переработав этот конфигурацианный файл можно организовать и полное кэширование вашего сайта. Попробуем?
Хорошим тоном считается что все сервисы, и LAMP в том числе, на сервере стартуют сразу после его перезагрузки автоматически… И автоматически укладываются DDoS ом вместе с сервером.
Возможно стоит выбрать другую стратегию для initrc?
В случае например с NAT beeline огромное количество людей может находиться за одним IP, но если вы не yandex.ru разумно предположить что 8 пользователей beeline на вашем сайте это достаточно?
Почитать:
NGINX proxy module.
Дырявые ведра или что такое burst?
Поучаствовать:
Программистам client-side js/ajax и c/c++ разработчик-искусственный интеллект, системы принятия решений — mailto://flx@msu.ru
Совместно с Центром телекоммуникаций и информационных технологий МГУ им. М.В. Ломоносова, мы занимаемся исследованиями DDoS.
Основная цель: разработать и донести до сообщества эффективные, доступные техники противодействия распределенным атакам на отказ в обслуживании.
В рамках исследовательской программы мы бесплатно предоставляем защиту. Все что нужно — передать трафик на наше оборудование любым удобным способом (изменить А запись DNS, GRE/IPIP tunnel).
В блоге проекта hll.msu.ru мы будем регулярно публиковать материалы, полученные в ходе исследований. Самые интересные случаи, методики, распространенные ошибки, — публиковать на Хабре.
В прошлую пятницу наблюдали ситуацию, в которой вполне вменяемый админ, к которому зашли в гости около 7 тыс ботов и, видимо, не очень радостный директор,
поддался панике и соорудил конструкцию вида:
NGINX -> apache -> mod_php -> memcached -> [кэшированая версия /]
Это бесспорно лучше чем генерация титульной страницы на каждый запрос с несколькими выборками для базы, но все еще недостаточно хорошо...
Настолько нехорошо, что даже те 3-8 запросов которые успевал сделать бот, до того как был распознан и забанен, создавали серьезные проблемы и время обработки запросов сервером составляло 1-2 секунды.
Вспомнив пару интересных новых “тематических” фич которые проходили за последних месяцев в NGINX, решили поупражняться в config-fu и в итоге получился вот такой вот забавный этюд…
http {
# даже обычные медленные клиенты, обычно дороги
reset_timedout_connection on;
client_header_timeout 15;
client_body_timeout 15;
send_timeout 5;
keepalive_timeout 30 15;
# введем две зоны ограничений.
# По открытым соединениям и по request rate
limit_req_zone $binary_remote_addr zone=qglob:16m rate=3r/s;
limit_zone cglob $binary_remote_addr 16m;
server {
listen 80;
server_name www.myhost.ru;
proxy_set_header Host $host;
# необходимо для работы proxy_store
proxy_buffering on;
# ограничим максимальное количество соединений с одного ip
# до 4х клиентов с одного ip по rfc2616
limit_conn cglob 32;
# Быстро отлавливаем “GET / “.
# Дописываем удобное имя файла.
location = / {
rewrite ^/$ /index.html last;
}
#Пост-рейт отдача статического index.html или загрузка с бэкенда.
location = /index.html {
internal;
open_file_cache_errors off;
limit_req zone=qglob burst=9 nodelay;
root /tmp/nginx/cache/;
error_page 404 = /cached$uri ;
}
location /cached/ {
internal;
alias /tmp/nginx/cache/;
proxy_pass phpfarm;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /tmp/nginx/tmp/;
}
#Жестоко зажатый на два запроса в секунду поиск.
location = /advanced_search_result.php {
limit_req zone=qglob burst=2;
proxy_pass phpfarm;
}
# И все остальное.
location / {
proxy_pass phpfarm;
}
}
}
Далее 5 минутный TTL на коленке…
nohup `while true; do rm -f /tmp/nginx/cache/index.html; sleep 300; done`&Что было необходимо и достаточно чтобы остановить 5000 ботов.
В качестве дополнительной меры можно выбирать наиболее назойливых по limiting requests из error_log и отправлять их в Null либо на ближайшем раутере либо в вашем netfilter.
Подумать:
Переработав этот конфигурацианный файл можно организовать и полное кэширование вашего сайта. Попробуем?
Хорошим тоном считается что все сервисы, и LAMP в том числе, на сервере стартуют сразу после его перезагрузки автоматически… И автоматически укладываются DDoS ом вместе с сервером.
Возможно стоит выбрать другую стратегию для initrc?
В случае например с NAT beeline огромное количество людей может находиться за одним IP, но если вы не yandex.ru разумно предположить что 8 пользователей beeline на вашем сайте это достаточно?
Почитать:
NGINX proxy module.
Дырявые ведра или что такое burst?
Поучаствовать:
Программистам client-side js/ajax и c/c++ разработчик-искусственный интеллект, системы принятия решений — mailto://flx@msu.ru
комментарии (29)
Это простой но эффективный способ отбиться от простой атаки. NGINX очень популярен. DDoS очень популярен. Вот они и нашли друг-друга.
Кстати, 5-10 тысяч ботов или меньше это каждый ВТОРОЙ случай с которым нам приходят.
Мы тут вовсе не нужны, все можно своими силами Ж)
Это не абсолют, это всего-лишь «путевые заметки». Пусть и с комментариями.
proxy_store нашли более «легким».
Это не абсолют, это всего-лишь «путевые заметки». Пусть и с комментариями.
proxy_store нашли более «легким».
limit_req_zone $binary_remote_addr zone=qglob:16m rate=3r/s;
а в limit_zone используется qulag
И кроме того burst это параметр всплеска относительно ограничения в rate, который будет задержен а не отброшен
Поправил.
Он будет задержан но не дропнут.
Если вам хочется получить вместо 2-3 запросов больше — добавьте опцию nowait.
Мы считаем что и необычных честных клиентов с залипшей F5 и ботов лучше попридержать.
#Жестоко зажатый на два запроса в секунду поиск.
limit_req zone=qglob burst=2;
По сути будет обработано 3 запроса в секунду, а 2 запроса сверх них будут задержаны до нормализации, остальные будут дропнуты.
Лично я понял фразу в коменте как то что будет обработано только 2 запроса. Возможно я не прав )
>Мы считаем что и необычных честных клиентов с залипшей F5 и ботов лучше попридержать.
согласен безусловно, сам такое использую для регулирования хайлода
У Сысоева-же эффективный burst=sustained+burst.
Все верно. На самом деле получается эффективных 3 запроса в секунду, хотя изначально подразумевалось sustained == burst.
Весь hotlist покэшированной статики осядет в vfs cache.
персонализированно.
самый быстрый запрос к базе — запрос которого небыло.
Почему 32? Если по Сысоеву:
location /cached/ {internal;
alias /tmp/nginx/cache/;
proxy_pass phpfarm;
что это? в описании директивы алиас сказано, что она говорит энджиниксу смотреть в другой локэйшн. а у вас мало того, что там не локэйшн, а какой-то путь в файловой системе торчит, так ещё и после этого эскалация запроса бэкэнду. приведу простой пример прямо из документации nginx:
location /images/ {
root /data/www;
error_page 404 = @fetch;
}
location @fetch {
internal;
proxy_pass backend;
proxy_store on;
proxy_store_access user:rw group:rw all:r;
proxy_temp_path /data/temp;
root /data/www;
}
кэшируется целая директория без костылей и сомнительных манипуляций. далее:
location = / {
rewrite ^/$ /index.html last;
}
зачем этот отдельный локэйшн? и разве не для этого и есть алиас, чтобы не городить тут рерайты? и почему здесь индекс не катит?