Защита от легкого DDoS'a

    Совсем недавно на хабре уже появилась рекламная статья о борьбе с DDoS атаками на уровне приложения. У меня был аналогичный опыт поиска оптимального алгоритма противодействия нападениям, может кому пригодится — когда человек в первый раз сталкивается в DDoS-ом его сайта, это вызывает шок, поэтому полезно заранее знать, что всё не так уж страшно.
    DDoS — распределенная атака на отказ — грубо говоря, бывает нескольких видов. DDoS сетевого уровня — IP-TCP-HTTP, DDoS уровня приложения — когда поток запросов сильно снижает производительность сервера или делает его работу невозможной, и я бы еще добавил DDoS уровня хостера — когда сайт работает, но нагрузка на сервер превышает установленную хостером квоту, в результате чего у владельца сайта тоже возникают проблемы.

    Если вас ддосят на сетевом уровне, то вас можно поздравить, что ваш бизнес поднялся до таких высот, и вы сами наверняка знаете, что в этом случае делать. Мы рассмотрим два других вида ддоса.

    Боты


    Любую CMS можно наполнить, разукрасить и оттюнинговать так, что даже один запрос в секунду будет давать недопустимую нагрузку даже на Хецнеровском VDS. Поэтому в общем случае задача стоит отфильтровать по возможности все ненужные запросы к сайту. В то же время, человек должен гарантированно на сайт попадать и не испытывать неудобств от наличия DDoS защиты.

    Боты бывают нескольких типов. Полезные (нужные поисковые), бесполезные (ненужные поисковые и спайдеры) и вредные (те, что вредят). Первые два типа — это добропорядочные боты, которые в своем User-Agent'e говорят о себе правду. Бесполезные боты отфильтровываются в .htaccess, полезные пропускаются на сайт, а вредных будем ловить. Случай, когда вредный бот представляется Яндекс ботом, например, мы опустим для простоты (для него тоже есть решение — Яндекс по ip дает возможность узнать, их это бот или нет, и таких можно сразу банить).

    Не допустив вредных ботов к бэкэнду получим необходимое снижение нагрузки на сервер.

    Вредные боты можно разделить на два типа: умные (которые понимают cookie и javascript) и глупые (которые не понимают). Есть мнение, что ддос-ботов, понимающих javascript, вообще не существует, но это для серьезных сетевых DDoS атак. В наших условиях даже чрезмерно активный анонимный спайдер формально становится ддос-ботом, которого надо нейтрализовать.

    Пока займемся глупыми ботами.

    Защита


    Код защиты приводить не будем, он простой — несколько десятков строчек на php; намного короче и проще этой статьи. Опишем логику. Будем записывать клиенту куку (метод проверки на куки используется даже при защитах от мощных DDoS атак). С любым именем и любым содержимым, можно использовать уже устанавливаемую сайтом куку.

    Для простоты считаем, что на сайт есть единая точка входа, туда встраиваем наш ddos-shield. Сразу проверяем у запроса нашу куку: если она есть — безусловно пропускаем на сайт. Если нету, то записываем пару ip и юзер-агент в виде отдельного файла в отдельную директорию /suspected. Файл имеет название ip-ua.txt, где ua — dechex(crc32($_SERVER[«HTTP_USER_AGENT»])) — просто короткий хэш юзер-агента.

    В сам файл пишем разделяя переводом строки время запроса, страницу (url) запроса, User-Agent, и еще можно использовать Sypex Geo или зарегистрироваться на maxmind.com и на пять дней заиметь бесплатный доступ к их geoip базе — по ip они выдают географическое местоположение, его тоже в этот файл.

    Если файл с таким именем ip-ua.txt уже существует, то добавляем всю эту информацию нового запроса в конец файла.

    Еще один момент — AJAX запросы нашего сайта. Если они есть, то их тоже нужно безусловно пропускать, определяя по своим меткам. Вероятность того, что боты тоже будут бить именно по ним — минимальна.

    Теперь пропущенный шаг — до того, как мы записываем или дописываем ip-ua.txt, мы проверяем, что запрос с этого ip уже приходил, причем, не обращаем внимания на User-Agent:

    count(glob(__DIR__ . "/suspected/$ip-*.txt")) > 0

    Смысл в том, что мы даем каждому ip один шанс на получение куки. Если он приходит второй раз без нее, то срабатывает это неравенство, и мы перенаправляем клиента на отдельную страницу check-human.php, где он с помощью гугловской рекапчи будет проходить тест Тьюринга с витринами и транспортными средствами. Если не прошел — до свидания (опять рекапча), если прошел — создаем в еще одной специальной директории /whitelist файл ip-ua.txt. И в самом начале вместе с проверкой куки проверяем и на попадание пары ip-ua в наш /whitelist — этих тоже безусловно пропускаем. При такой тактике мы сможем дать возможность работать на сайте тем людям, у которых в браузере отключена поддержка куки и включен javascript, либо наоборот — отключен javascript но работают куки.

    image

    Ботнет


    В принципе и всё. Глупых ботов отфильтровали, теперь умные. Для умных и подход уже интеллектуальный — открываем директорию /suspected, сортируем файлы по размеру. Вверху самые большие — десятки и сотни килобайт настойчивых попыток к нам пролезть. Открываем и смотрим, убеждаемся, что это действительно бот — по ip, по местоположению, по времени запроса, по периодам запросов, по страницам запросов, по сменам юзер-агента — обычно это хорошо видно, всё перед глазами. В принципе, можно выбрать все файлы с, к примеру, 10+ безуспешных попыток, и отправить их ip в бан через .htaccess. Но это нехорошо, лучше отправлять их на капчу — все-таки бывает, что несколько человек выходят в инет через один ip.

    Это очень неплохо решает и вопрос умных ботов. Почему? Потому что если вас заказали, то, скорей всего, одному ддосеру. А они тоже бывают умные и глупые. И глупые обычно используют для умных и глупых своих ботов один ботнет, с одними ip. Таким образом, вы заблокируете и тех ботов, которые принимают куки и исполняют javascript. Кроме того, умных ботов намного меньше, стоят они дороже и работают медленней, поэтому данный метод эффективен для борьбы с абсолютным большинством рассматриваемых атак.

    По моим наблюдениям, по данной схеме через капчу пришлось пройти порядка 1%-2% реальных пользователей сайта, остальные вообще ничего не заметили — что вполне юзер френдли. Кроме того, даже зашедшие в первый раз люди не видят никаких «заглушек» (в отличие от способа по ссылке в начале поста), а спокойно работают с сайтом.

    Определенные неудобства возможны у людей, использующих специальный брузерный софт для анонимизации — динамически меняющий ip и юзер-агент клиента, стирающий куки, но мы этот вариант не рассматриваем.

    В моем случае нагрузка на сервер упала сразу. Боты долбились еще какое-то время; через пару дней я заметил, что они ушли — ддосеры тоже не любят тратить ресурсы вхолостую. Снял защиту.

    Развитие логики


    Можно варьировать логику защиты — добавить проверку на javascript (он и будет ставить куку, например); можно мониторить тех, кто был перенаправлен на капчу и не прошел ее, чтобы не допускать случая «плохого» поведения по отношению к человеку; можно делать именные куки, следить за числом захода клиента и при превышении лимита так же отправлять его на капчу; можно реализовать систему токенов; можно пускать ботов по цепи редиректов с временными задержками, чтобы затормозить их; можно анализировать ip ботов и банить целыми сетками, как Роскомнадзор — но это уже по мере надобности. По закону 20-80 самые простые нужные решения решают просто всё, что нужно.

    Главное — оперативно вычленив и забанив очевидно зловредные ip из /suspected, вы сразу ощутимо снизите нагрузку на сервер и получите время для подготовки дальнейших действий по отражению атаки.

    Вот таким нехитрым способом можно наказать нечистоплотных конкурентов на деньги.

    Disclaimer: данная статья написана только для легких DDoS атак уровня приложения, преимущественно для сайтов на shared хостинге, лимит доступных ресурсов которых ограничен.
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 15

      0
      Есть небольшие вопросы по реализации. У некоторых поисковых ботов нет чётко закрепленных адресов, например у googlebot. В то же время под них могут подделывать заголовок другие боты. А также по ajax запросам. запрос fetch не имеет характерного заголовка поэтому если такие запросы не имеют выделенного url например /api/… Определить что пришёл ajax невозможно.
        –2
        Я поисковых ботов определяю не по адресам, а по юзер-агенту. Яндекс и Гугл — проходи, остальным разворот. Если вредный бот подстраивается под них, так как и написано, можно запрашивать у поисковиков проверку — их ip или нет (у Яндекса я точно видел такой сервис).

        Но с моей точки зрения, всё это второстепенно. Ддос-боты редко подделываются под поисковые, потому что так их проще отрубить. Если то решение, которое я привел в статье не спасет, тогда уже нужно копать дальше. И файлы в директории /suspected очень сильно помогут в анализе атаки и определении направления дальнейшего движения. После того, как вы забаните самые активные вредоносные ip, можно уже будет спокойно думать.

        Просто логи вебсервера даже с анализаторами так наглядно источники атаки не покажут.
          0
          По поводу fetch — там можно установить в HTTP запросе свой заголовок и на сервере проверять его, например. Или добавлять какой-то параметр.

          Но, это абсолютно не критично — ведь fetch будет всегда (по идее) передавать куку. Случай с fetch — теоретический, когда пользователь открыл сайт, потом перешел из одной wifi, например, сети в другую, сменил ip адрес. И всё равно должно работать, по идее…

          Возможно, я перестраховался по ajax. У меня SPA и такой специальной проверки (пропуск ajax) не было, и все и так работало при включенной защите.
            +1
            Поисковых роботов нужно вайтлистить так: support.google.com/webmasters/answer/80553?hl=ru
            Нельзя вайтлистить ни по юзерагенту ни по адресу. Юзерагент- подделывается, адреса у ботов меняются, + с гуглосети могут ходить не только поисковые боты. Этот же способ справедлив для яндекса.

            Но тут есть момент, если на каждый запрос спрашивать днску, то получаем +много времени ответа, особенно если обратной записи нет совсем. Приходится проверять ип постфактум в фоновом режиме, затем сохранять результаты в редис и после этого уже можно быстро узнать принадлежит ли адрес гуглоботу.
              0
              Ну, да, у Яндекса подобная штука. Но с моей точки зрения, это перебор. Только если есть подозрения, что гугл это не гугл, а так юзер-агента достаточно.
            +1

            Реализовать защиту от ддоса на php и javascript, подключать базу от maxmind, писать сигнатуры в текстовый файл, потом парсить его…
            Вам и ддоса не надо, вы сами свой сайт положите своими проверками.

              +1
              Я просто описал свой реальный случай, как смог избавиться от подобной DDoS атаки.

              Вы на что злитесь?
                0

                судя по простоте мер, которые сумели помочь — это была пара ленивых индусов.
                DDos начинается когда трудно пробиться на ssh сервера, до этого только ленивые эксперименты досеров.

                  0
                  Специально для вас я написал дисклеймер в конце статьи.
                  У вас свои проблемы, у других — свои
                    0
                    Для порядка надо бы добавить фразу о том, что это решение подходит для сайтов с небольшой нагрузкой.
                0
                Да ладно вам, пишет человек свой аналог fail2ban, пусть пишет.
                  +1
                  Вы не видите разницу между собственным сервером и shared hosting-ом в возможностях установки желаемого софта?
                    0

                    Я думал шаред мёртв давно

                      +1
                      Зато флуд жив
                0

                Я бы сказал, что это скорей меры против спам ботов и (иногда) скачивальщиков страниц, остальные боты обычно более злые.

                Only users with full accounts can post comments. Log in, please.