С распределенными атаками типа «отказ в обслуживании» (DDoS) в последние годы сталкивались компании практически из всех отраслей экономики. Они используются хакерами довольно давно, и чрезвычайно эффективно могут остановить работу публичных ресурсов компании. В результате — финансовый ущерб и репутационные риски, справиться с которыми может быть довольно сложно, особенно молодым компаниям. В этом посте мы поговорим о том, как защитить инфраструктуру компании от DDoS-атак с помощью CrowdSec и Cloudflare.
Коротко о DDoS
Концепция распределённой атаки на отказ в обслуживании до примитивного проста: целевой хост бомбардируют множеством запросов с разных IP-адресов. Вынужденный обрабатывать все эти запросы, хост выходит из строя, в результате чего сервисы, которые он предоставлял, становятся недоступными для обычных пользователей. За прекращение атаки обычно просят выкуп.
Основные типы DDoS-атак — Layer 3 и Layer 7. Они названы так в соответствии с уровнями сетевой модели OSI, на которых выполняются.
Layer 3 DDoS нацелен на сетевое оборудование и соединения. В ходе атаки создаётся огромный паразитный трафик, например, с помощью SYN-пакетов (syn-flood). Этот трафик забивает канал связи и блокирует прохождение легитимных пакетов. В настоящее время большинство крупных хостинг-провайдеров и дата-центров сегодня хорошо защищены от атак Layer 3 , поэтому в этом посте мы сосредоточимся на другой разновидности атак, противостоять которой несколько сложнее.
DDoS-атаки Layer 7 нацелены непосредственно на приложения, которые работают на сервере. Цель здесь — не отключить сеть, а добиться остановки приложения или даже сервера путём перегрузки его штатными прикладными запросами. Это приводит к нехватке ресурсов процессора, оперативной памяти или и того и другого и фактически останавливает работу.
Существует множество способов и инструментов для проведения такого рода атак и множество способов защиты. Сегодня мы сосредоточимся на защите от распределённых атак на отказ в обслуживании на уровне приложений (уровень 7), сокращенно L7 DDoS.
Как работают атаки Layer 7
Стандартной практикой для таких атак является отправка множества запросов с различных публичных IP-адресов. Например, для атаки на интернет-магазин это могут быть http/https-запросы, вызывающие интенсивную работу с базой данных — регистрация нового пользователя или поиск товаров.
Сложность в защите от таких атак состоит в том, чтобы отличить запрос обычного пользователя от вредоносного запроса. Если в распоряжении атакующего имеется достаточный пул IP-адресов, он может направлять с каждого из них буквально два-три запроса, после чего переходить к следующему. Это обеспечивает перегрузку целевого хоста, но делает невозможным блокировку атаки по IP-адресу.
Меры противодействия
Остановить такие атаки позволяет блокировка IP-адреса по геолокации или по автономной системе (AS). Если атаки в основном идут из стран X и Y или автономных систем M и N, их блокировка позволит частично решить проблему. Но запрет будет означать, что легитимные пользователи из этих стран и автономных систем не смогут получить доступ к сайту. Такой подход неприемлем, если речь идёт об обороне интернет-магазина или провайдера услуг, который доставляет товары и предоставляет услуги по всему миру.
Но не всё так плохо. Вместо блокировки по IP-адресам можно включить показ капчи. Это позволит легальным пользователям спокойно пройти проверку, а атакующие боты останутся снаружи.
Давайте посмотрим, как реализовать такую защиту с помощью CrowdSec.
Тестовая атака
В качестве цели для атаки мы запустили сервер t2.medium (2 ядра Xeon @2.4Ghz / 4Gb RAM) с Apache и MySQL под управлением WordPress с WooCommerce.
Для атаки мы использовали сторонний сервис для стресс-тестирования (проведения DoS/DDoS-атак). Запустив 20-минутную атаку Layer 7 с этой платформы, мы успели зафиксировать запросы с более тысячи разных IP-адресов, но уже через минуту или около того, сайт рухнул:
Утилизация процессора оставалась высокой в течение всей атаки:
При этом трафик постепенно снижается из-за недоступности сайта:
Во время атаки мы зафиксировали 70 тыс. HTTP-запросов с 1150 уникальных IP-адресов (достаточно хорошо распределенных по адресному пространству IPV4).
Наш взгляд на проблему
Мы предположили, что, как это часто бывает с «продвинутымии» DDoS-атаками Layer 7, увидим только один или два http-запроса на каждый атакующий IP-адрес и что нам нужно иметь возможность принимать решения на уровне страны или AS. И именно здесь в игру вступает баунсер Cloudflare в составе Crowdsec.
Cloudflare через свой API позволяет устанавливать правила, нацеленные не только на диапазоны IP, но и на AS и страны, что удобно для нашего случая, а в качестве дополнительных средств защиты в нём имеются капча и JavaScript-челлендж.
Вот чего мы хотели бы добиться (национальные флаги изображены произвольно и не имеют отношения к реальности):
Во время атаки Layer 7 для стран, откуда в основном идет атака, будет показываться капча (Китай, Индонезия и Индия в нашем примере), но легитимные пользователи оттуда всё равно попадут на сайт, в то время как пользователи из других стран (здесь — Франция и Испания) будут проходить без проверок.
Для достижения этой цели агент CrowdSec будет читать журналы Apache, обнаруживать источники атаки и выдавать решения, которые будет использовать баунсер Cloudflare, чтобы отправить Cloudflare команду блокировки атакующих.
Далее мы создали сценарий CrowdSec для обнаружения чрезмерного трафика из определенной страны, автономной системы или любого заданного IP/диапазона. Этот сценарий через API Cloudflare включает капчу для источника атаки — страны/AS/диапазона/IP.
Для корректной работы Apache должен быть настроен на работу с HTTP-заголовком X-forwarded-for, чтобы отображать реальные IP атакующих, а не адреса Cloudflare.
Испытание огнем
Установка
Мы установили CrowdSec на сервер прямо по документации вместе с баунсером Cloudflare. Для запуска CrowdSec не потребовалось никакой специальной настройки.
В панели Cloudаlare мы видим, что наши правила попадают точно в цель:
Что касается ресурсов, потребляемых машиной, результаты очень разные. В течение пяти минут после начала атаки ресурсы пришли в норму, причём две минуты из этих пяти ушли на применение правил Cloudflare; процессор и сеть также приходят в норму в течение пяти минут:
Вот короткое видео, показывающее, как выглядит атака и устранение последствий:
Используемый сценарий
Сам сценарий довольно прост и заключается в одновременном подсчёте количества IP-адресов, исходящих из одного и того же диапазона, страны или AS. Если это число достигнет порогового значения, мы включаем капчу на страну, диапазон или AS источника:
type: leaky
#debug: true
name: crowdsecurity/http-ddos-by-ASN
description: "Detect and prevent applicative DDoS by leveraging CF-like bouncers"
filter: "evt.Meta.ASNNumber != '0' && evt.Meta.service == 'http' && evt.Meta.http_status == '200' && evt.Parsed.static_ressource == 'false'"
groupby: "evt.Meta.ASNNumber"
distinct: "evt.Meta.source_ip"
capacity: 20
leakspeed: "10s"
blackhole: 5m
labels:
service: http
type: scan
remediation: true
scope:
type: AS
expression: evt.Meta.ASNNumber
---
type: leaky
#debug: true
name: crowdsecurity/http-ddos-by-cn
description: "Detect and prevent applicative DDoS by leveraging CF-like bouncers"
filter: "evt.Meta.IsoCode != '' && evt.Meta.service == 'http' && evt.Meta.http_status == '200' && evt.Parsed.static_ressource == 'false'"
groupby: "evt.Meta.IsoCode"
distinct: "evt.Meta.source_ip"
capacity: 50
leakspeed: "30s"
blackhole: 5m
labels:
service: http
type: scan
remediation: true
scope:
type: Country
expression: evt.Meta.IsoCode
Вот сценарий, фильтрующий входящие http-запросы, не направленные на статические ресурсы:
filter: "evt.Meta.IsoCode != '' && evt.Meta.service == 'http' && evt.Meta.http_status == '200' && evt.Parsed.static_ressource == 'false'"
События будут группироваться по странам-источникам с учётом отдельных IP-адресов, поскольку целью является подсчет количества уникальных IP-адресов, исходящих из страны в определенное время:
groupby: "evt.Meta.IsoCode"
distinct: "evt.Meta.source_ip"
Мы будем разрешать 50 различных IP-адресов каждые 30 секунд:
capacity: 50
leakspeed: "30s"
blackhole: 5m
Если сценарий срабатывает, он запускает исправление в отношении страны-источника.
labels:
remediation: true
scope:
type: Country
expression: evt.Meta.IsoCode
Использование баунсера Cloudflare
После обнаружения источников атак мы можем задействовать функции Cloudflare для выборочной остановки атак: баунсер будет создавать и обновлять правила брандмауэра в Cloudflare через его API. Мы не хотим запрещать доступ легальным пользователям из заблокированных стран, поэтому можем установить правила, которые будут заставлять пользователей проходить только капчу.
Правило, сгенерированное баунсером, включает капчу для различных стран, IP и AS, эффективно блокируя ботов.
Что дальше?
Мы уже довольны первыми результатами, но это далеко не всё, что можно было сделать. В части дальнейшего совершенствования защиты мы определили для себя следующие направления:
сделать автоматическую настройку пороговых значений в сценариях для разных инфраструктур и разных компаний — это реализуется путем наблюдения за средним трафиком по странам в нормальных условиях;
подобрать более качественный сервис для проведения DDoS-атак Layer 7, поскольку тот, который мы использовали, крайне нестабилен: количество задействованных IP-адресов меняется, но не превышает 1200;
усовершенствовать текущие сценарии, чтобы они подходили не только для для блокировки потоковых атак Layer 7 , но и решали другие бизнес-кейсы, например, автоматизированный «пробив» банковских карт кардерами.
Теперь вы знаете, как легко смягчить DDoS-атаку прикладного уровня с помощью CrowdSec и Cloudflare. Попробуете сами?