[Из песочницы] Обнаружение DDoS-атак «на коленке»
Приветствую, Хабр! Я работаю в небольшом интернет провайдере масштаба области. У нас транзитная сеть (это значит, что мы покупаем интернет у богатых провайдеров и продаем его бедным). Несмотря на небольшое количество клиентов и такое же небольшое количество трафика протекающего по нашей сети, довольно часто приходится иметь дело с весьма внушительными DDoS-атаками по 10–20Гбит/с. (чаще всего конечно это атаки гораздо меньшего калибра). И хотя некоторые из наших клиентов обзавелись уже системами обнаружения таких атак и могут самостоятельно отправить жертву в блек-холл, гораздо чаще обнаружение атаки и бан конкретного IP жертвы ложится на наши плечи (тем более, если атака способна забить наши внешние каналы).
О решении, которое помогает обнаруживать эти самые атаки и которое принято у нас в сети, я и хотел бы рассказать. Оно бесплатно, основывается на анализе данных NetFlow, поэтому просто и весьма эффективно.
На самом деле систем для обнаружения Ddos-атак основанных на анализе данных протоколов NetFlow/SFlow/IPFIX существует довольно много (вероятно почти все?). В первом приближении, суть всех таких систем сводится к установлению порогов по количеству пакетов/потоков/октетов на определенный тип трафика к конкретному IP, при превышении которого система сигнализирует о возможной атаке. И наше решение ничем от них в этом плане не отличается. Однако, основная проблема — большинство из них платные. А бесплатные версии предлагают довольно грубый анализ, который часто неэффективен (к примеру, позволяет устанавливать порог только на весь трафик к конкретному IP, без его предварительной фильтрации, что в случае анализа транзитного трафика почти всегда бесполезно).
Итак, сперва необходимо настроить протокол NetFlow на сетевом оборудовании с минимально возможным active timeout (интервал с котором экспортируются данные с оборудования на коллектор) — это 60с для Cisco и Juniper.
forwarding-options {
sampling {
input {
rate 2000;
run-length 0;
}
family inet {
output {
flow-inactive-timeout 15;
flow-active-timeout 60;
flow-server 10.0.0.10 {
port 9999;
autonomous-system-type origin;
source-address 10.0.0.1;
version 5;
}
}
}
}
}
Здесь:
- rate и run-length отвечают за семплирование статистики. Для анализа трафика берется один из 2000 пакетов. Данные взяты из рекомендаций Juniper для 10G интерфейсов. (К удивлению обнаружил, что сейчас не могу найти этих рекомендаций)
- flow-active-timeout 60; — вышеуказанный интервал с котором экспортируются днные на коллектор
- flow-inactive-timeout 15; — интервал неактивности, после которого поток считается завершенным.
- autonomous-system-type origin; — Экспортировать номер AS источника (Для нашей задачи не нужно, но для Traffic Engineering необходимая вещь)
- version 5 — здесь надо сделать небольшое отступление. Выбор 5й версии, а не 9й обусловлен двумя причинами. Во-первых, для работы 9й версии нужна доп плата в Juniper. Во-вторых, выбранный коллектор должен понимать 9ую версию (спойлер: он не понимает). Однако для нашей задачи вполне подойдет и 5ая версия.
Затем вешаем его на интерфейсы, где будем собирать статистику (как минимум это должны быть uplink интерфейсы):
interfaces {
ae1 {
vlan-id ...;
family inet {
sampling {
input;
output;
}
address ...
}
}
}
Далее, нам необходимо настроить NetFlow коллектор, который будет собирать данные статистики с оборудования.
В качестве коллектора решено было использовать многим знакомый flow-capture из набора утилит flow-tools. Именно набор утилит, который позволяет строить разнообразные и подробные отчеты на основе собранной статистики является главным достоинством этого пакета. (К слову в наборе утилит также есть и flow-dscan для обнаружения сканирования хостов/портов и другой нежелательной активности). В недостатки можно записать отсутствие веб-оболочки и отсутствие поддержки 9й версии NetFlow. Однако, повторюсь, гибкость таких утилит как flow-nfilter, flow-report и, конечно же, свободное распространение с легкостью все перекрывают.
# cd /usr/ports/net-mgmt/flow-tools
# make install clean
Добавляем в /etc/rc.conf:
flow_capture_enable="YES"
flow_capture_localip="10.0.0.10" #локальный ip на который принимается поток
flow_capture_remoteip="10.0.0.1" #ip с которого льется поток
flow_capture_port="9999" #порт на который льется поток
flow_capture_datadir="/var/db/flows" #директория с файлами собранной телеметрии
flow_capture_flags="-z0 -n1439 -N3 -E10G -e0 -S1" #параметры
Здесь:
-z0 — сжатие файлов (0 — выключено)
-n1439 — количество файлов, которое создаст коллектор в сутки. По умолчанию 95 — это один файл в 15 минут. 1439 — максимальное значение — это один файл в минуту. Нам необходимо, чтобы файлики создавались как можно быстрее.
-N3 — это уровень вложенности файлов и папок (YYYY/YYYY-MM/YYYY-MM-DD/flow-file)
-E10G — ограничение на занимаемое пространство на диске. Будет удалять старые файлы таким образом, чтобы общий объем файлов с телеметрией был менее этого числа. Очень полезная штука, жаль не подчищает созданные директории.
-e0 — тоже самое только про количество файлов (0 — не следить)
-S1 — логировать каждую минуту сообщение о полученных/потерянных/обработанных потоках
Из всего набора утилит flow-tools нас будут интересовать три:
- Flow-nfilter — позволяет фильтровать статистику по таким параметрам как ip адрес/протокол/порт. Нам она нужна будет для своеобразного белого списка IP, которые нужно исключить из проверки. Например, ip-адреса гугл-кэш серверов в вашей сети (или любых других кэшей), где достаточно высокий поток трафика может ложно сигнализировать о ддос-атаке. Создадим файл filters.cfg с фильтром (ip-адреса для примера):
filter-primitive white-list-ip type ip-address-prefix deny 8.8.8.8 deny 64.233.160.0/19 default permit filter-definition white-list match ip-destination-address white-list-ip match ip-source-address white-list-ip
- Flow-report — утилита позволяющая строить отчеты, группируя трафик и сортируя данные по заданным параметрам. Чем-то похожа на функцию Groups By в SQL. Типов отчетов, которые она может сгенерировать множество (многие из них могут быть полезны для Traffic Engineering). Нас интересуют следующие:
- ip-destination-address/ip-source/destination-port — группировка потоков, как не сложно догадаться, по ip-destination адресу, source/dest порту. Это значит, что будут объединены все потоки с одинаковыми ip-destination-address & ip-source & destination-port и представлены в отчете в отсортированном порядке, например, по потокам или пакетам (если конечно эту сортировку задать). Такого рода отчет позволит выявить так называемые DDoS-атаки с отражением на какой-нибудь сервис. К примеру, если зафиксировано аномально большое количество потоков с порта 53 на порт 80 какого-нибудь хоста, можно говорить о возможной атаке. Это удобно, так как в большинстве случаев такого рода потоков немного, и при правильно настроенном пороге можно выявить атаку даже с минимальным результирующим трафиком. Для того что бы задать отчет, нужно создать файл с его описанием. Создадим файл reports.cfg:
stat-report sdport_flows type ip-destination-address/ip-source/destination-port output format ascii options -header,-xheader,-totals,-names fields +flows,-octets,-packets,-duration sort +flows stat-definition sdport_flows report sdport_flows
- ip-destination-address/ip-destination-port — более грубая группировка, учитывающая только два параметра. Но работать она будет по пакетам. Добавим в созданный файл reports.cfg:
stat-report dport_packets type ip-destination-address/ip-destination-port output format ascii options -header,-xheader,-totals,-names fields -flows,-octets,+packets,-duration sort +packets stat-definition dport_packets report dport_packets
- ip-destination-address — и самая грубая группировка по результирующему трафику на конкретный ip. Здесь мы создадим два отчета по потокам и по пакетам.
stat-report flows type ip-destination-address output format ascii options -header,-xheader,-totals,-names fields +flows,-octets,-packets,-duration sort +flows stat-definition flows report flows stat-report packets type ip-destination-address output format ascii options -header,-xheader,-totals,-names fields -flows,-octets,+packets,-duration sort +packets stat-definition packets report packets
- ip-destination-address/ip-source/destination-port — группировка потоков, как не сложно догадаться, по ip-destination адресу, source/dest порту. Это значит, что будут объединены все потоки с одинаковыми ip-destination-address & ip-source & destination-port и представлены в отчете в отсортированном порядке, например, по потокам или пакетам (если конечно эту сортировку задать). Такого рода отчет позволит выявить так называемые DDoS-атаки с отражением на какой-нибудь сервис. К примеру, если зафиксировано аномально большое количество потоков с порта 53 на порт 80 какого-нибудь хоста, можно говорить о возможной атаке. Это удобно, так как в большинстве случаев такого рода потоков немного, и при правильно настроенном пороге можно выявить атаку даже с минимальным результирующим трафиком. Для того что бы задать отчет, нужно создать файл с его описанием. Создадим файл reports.cfg:
- Flow-print — позволяет отобразить собранную телеметрию.
Результирующий скрипт (Python 3) с установленными порогами для каждого отчета будет анализировать собранную телеметрию и в случае обнаружения атаки (то есть превышения порога для отчета), сбрасывать письмо на почту с расшифровкой трафика на IP жертвы за данную минуту.
Код скрипта я приводить не буду, он с файлами filters.cfg и reports.сfg доступен на GitHub
Для его работы достаточно сконфигурировать некоторые параметры в config.ini. И добавить его в крон на исполнение в каждую минуту.
[REPORTS]
sdport_flows
dport_packets
flows
packets
# Reports(rules) options
# threshold - threshold value
# key_field - report field index number to which the threshold applies
# filter - name of a filter described in FiltersFileName
[sdport_flows]
threshold = 300
key_field = 4
filter = white-list
[dport_packets]
threshold = 3000
key_field = 3
filter = white-list
[flows]
threshold = 2000
key_field = 2
filter = white-list
[packets]
threshold = 5000
key_field = 2
filter = white-list
- threshold — пороговое значение, IP адреса в отчете с количеством потоков/пакетов превышающим это значение считаются атакуемыми.
- key_field — индекс поля в выводе отчета (начиная с 1), к которому применяется порог.
- filter — имя фильтра применяющегося к данным статистики до группировки данных отчетом flow-report.
Задать пути расположения файлов и настройки отправки почты:
[FILES]
# Dir with flow-tools binary files
FlowToolsBinDir = /usr/local/bin/
# Dir with Whois, AWK binary files
SysBinDir = /usr/bin/
FlowsDir = /var/db/flows/
ReportsFileName = reports.cfg
FiltersFileName = filters.cfg
[EMAIL]
SMTPServer = localhost
# 0-default port
SMTPPort = 0
MailFrom = mail@example.com
MailTo = mail@example.com
Subject = [DDoS Detect]
# Amount of flow-print records in an email
FlowPrintTail = 50
# Use TLS (if True, Auth must be the same)
Secure = False
# Use Login and Password
Auth = False
# Notification Frequency about current DDoS attack - every value minutes
# if 0 - don't send email, print victims ip to stdout
NotifyFreq = 5
# Act if Auth = True
[EMAIL-AUTH]
Login = ...
Password = ...
Письмо с уведомлением об атаке выглядит так:
Скрипт позволяет добавлять/убирать свои отчеты по которым будет происходить анализ трафика, задавать для каждого отчета свой фильтр из файла filters.cfg, менять частоту уведомлений для текущей DDoS-атаки. Позволяет также вывести список атакуемых IP на stdout, не отправляя письмо.
Еще раз ссылка на GitHub
Вот собственно и все. Спасибо за внимание!