mail@highloadlab.com skype: highloadlab
Отбиваем 5000 ботов на NGiNX
01/09

В прошлую пятницу наблюдали ситуацию в которой вполне  вменяемый админ, к которому зашли в гости около 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;

                        limit_req   zone=qglob  burst=9 nodelay;

                        open_file_cache_errors off;

                        root /tmp/nginx/cache/;

                        error_page 404 = /cached$uri ;

                        }

 

     

                location  /cached/ {

                        internal;

                        alias /tmp/nginx/cache/;

                        proxy_pass http://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=qulag  burst=2;

                        proxy_pass http://phpfarm;

                }

 

# И все остальное.

                location / {

                        proxy_pass http://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 пользовтелей билайн на вашем сайте это достаточно ?

 

Что огорчило админа больше ?  Боты или Директор ?

 

 

Почитать еще:

 

NGINX  proxy module .

 

Дырявые ведра или что такое burst?

 

 

 

Комментарии (8)
Гость#
по моему моя схема посильнее будет для защиты от доса нужно
1 расширить и отюнить ядро для обработки соеденений и работой с нджинксом
2 обойтист без апача (Fastcgi)
дополнение для пакетных забивок
1 норошие сетевушки (интел) для режима поллинга
2 грамотная настройка PF c баном
3 А если совсем тяжело то пару серверов и кластер PF (CARP) и не надо не какой циски-гуард
Гость#
rate=3r/s; этого мало для сайта где много графики и всего того что тянет браузер бекграундом для дайлапа максимальное количество одновременных потоков браузер делает как минимум 5 и что же выходит энджи будет гасить остальные запросы ?
Гость#
хочу вас обрадовать - давно существует proxy_cache и proxy_store можно забыть как страшный сон
HighloadLab.#
Спасибо, мы вкурсе и уже давно используем proxy_cache там где его использовать удобно и уместно. Proxy_store легче и проще в терминах nginx.
Гость#
> И автоматически укладываются DDoS ом вместе с сервером.
укладываются по полосе пропускания провайдера?
видимо в вашей конфигурации система уходила в своп и отзывчивость исчезала. Надо лимитировать количество обработчиков у apache чтобы хватало памяти.
Гость#
а как это связано с обьемом потребляемой процессом апача памятью ? можно спокойно употребить всю доступную в системе память и одним процессом. А зечем менять в сорцах, когда в сегодняшнем Apache есть директива MaxClients ?
HighloadLab.#
0. Забить полосу пропускания даже среднего провайдера, это достаточно дорогое удовольствие в терминах стоимости ресурсов ботнета.
1. Вдумчиво проставленный ServerLimit вовсе не гарантирует того что к вам не прийдет OOM, особенно если у вас mod_php и какой-нибудь акселератор.
2. swap для веб-приложения - вещь скорее вредная, чем бесполезная.
3. пока на один запрос стоимостью N, будет выполняться действий на N^10 - есть много других не менее забавных способов отсечь администратора от доступа посредством ssh, а возможно и посредством KVM.
4. смысла поднимать apache всеравно не очень много - зачем он если ваш db layer скорее всего в рассыпавшемся состоянии ?
Все это - простые и очевидные мысли, лежащие на поверхности.... .... о которых почему-то очень часто забывают.
mousus22 октября 2009, 23:39#
а почему количество запросов с определённого ip надо резать на 7 уровне ? если можно потратить меньше памяти и зарезать количество tcp соединений с одного IP адреса встроеным фаерволом на 3 уровне модели OSI и не тратить драгоценную память на 7 уровень в юзерспейсе а резать на уровне ядра, ipfw это прекрасно умеет, да даже если нет и фаервола то неплохо можно заносить в чёрный список используя конструкцию вида

route add banned_ip blach_hole_destination_ip metric