Защита от легкого 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 хостинге, лимит доступных ресурсов которых ограничен.
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 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

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

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое