Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

в 8:18, , рубрики: asn, BGP, ddos, geoip, iptables, linux, Блог компании FastVPS LLC, метки: , , , , ,

Введение

В свете новогодних праздников с их неотъемлемым атрибутом — повышенной активностью DoS/DDoS атак хотелось бы поднять один довольно редко используемый (но при этом довольно эффективный) способ отражения атак — блокировка на основании принадлежности блоков IP адресов определенному провайдеру/Дата Центру.
Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

В интернете и на Хабре было очень много публикаций на тематику защиты, но в основном они сводятся к следующим подходам основанным на группировке IP по различным признакам:

  • Блокировка отдельных IP атакующих ботов
  • Блокировка целых подсетей, к которым принадлежат боты
  • Блокировка целых стран/городов, к которым принадлежат атакующие боты
  • Блокировка всех IP адресов, кроме разрешенных явно
  • Блокировка IP адресов на основании определенного алгоритма (включая использование специализированного аппаратного обеспечения)

Но при этом совершенно не заслуженно упускается еще один способ группировки (а следовательно и блокировки) IP адресов — их принадлежность к автономным системам (ASN). Что же такое ASN? Это группа IP адресов, которые обслуживаются одним провайдером либо Дата Центром. Условно, это более высокий уровень иерархии, следующий сразу за понятием сеть/подсеть, но имеющий организационное происхождение. Возьмем в пример компанию Yandex, их номер автономной системы 13238 и ему принадлежат следующие блоки IP адресов: bgp.he.net/AS13238#_prefixes как можно заметить, никакой закономерности кроме принадлежности к одной ASN у данных адресов нет. Еще стоит обратить внимание, что ASN бывают двух видов — 16 битные (до 65635) и 32 битные (до 2^32-1).

Но чем же данный технический экскурс поможет защититься от злоумышленников? Дело в том, что есть довольно широкий список провайдеров (как ISP, так и Дата Центров), которые мягко говоря не лучшим образом заботятся о безопасности своих сетей (не блокируют исходящие DDoS атаки, не реагируют на жалобы и проч.) и, как следствие, довольно часто являются источниками DDoS атак. Блокировка таких автономных систем (временная, разумеется) может сильно помочь при защите от атак. С подробной статистикой автономных систем, которые чаще всего являются источниками атак Вы можете ознакомиться на сайте: stopddos.ru/current/ (статистика почти в реальном времени)
Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

Определение номера автономной системы, к которой принадлежит IP адрес

Как определить автономную систему, к которой принадлежит IP адрес/сеть? Это довольно просто. В случае, если IP адрес находится в Европе (а следовательно — в юрисдикции RIPE), то можно использовать команду: whois ip_адрес/сеть. Попробуем на Яндексе:

whois 93.158.146.0

Обращаем внимание на поле ORIGIN, в нем как раз и указан номер автономной системы.

Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

Если же IP адреса принадлежат другому RIR (AFRINIC, LACNIC и проч.), то для них нет понятия route объекта и тут самый универсальный совет, который я могу дать — это воспользоваться специальным сервисом, который позволяет преобразовать IP адрес в номер ASN: www.team-cymru.org/Services/ip-to-asn.html

Чем еще замечателен сервис от CymRu, так это возможностями по автоматизации и вызову из консоли данной операции, что будет очень к месту в случае использования (при защите от реальных атак без него не обойтись) автоматизированных анализаторов трафика, log файлов для поиска закономерностей и аномалий в контексте определенных ASN.

Хорошо, допустим, на данном этапе мы обнаружили ASN (обычно, конечно же, их от нескольких штук до нескольких десятков), из которой идет атака, следующим шагом требуется проверить, кому она принадлежит и для каких целей служит, чтобы случайно не отсечь своих же клиентов, это можно сделать через сервис от Hurricane Electric, bgp.he.net/ASXXXX, где вместо XXXX нужно поставить обнаруженный номер автономной системы.

Блокировка трафика из/в определенной ASN

Но как нам блокировать трафик, который идет к нам из определенной ASN? Данная функция есть у любого магистрального провайдера, дата центра либо оператора связи (и реализуется она посредством протокола BGP), но получить эту функцию для конечного пользователя почти невозможно. Поэтому мы будем использовать Debian Wheezy и пакетный фильтр iptables для отсечения трафика с паразитных ASN.

Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

Разумеется, стандартного решения, которое позволит сделать что-то в стиле:

iptables -I INPUT -p tcp --dport 80 -m asn --asn-number 11222 -j DROP

Пока не существует, поэтому нам придется импровизировать!

В голову сразу приходит два различных подхода — ipset и geoip (да, у Вас возникнет вопрос — какое отношение он имеет к вопросу, но об этом чуточку позже). ipset позволяет блокировать трафик принадлежащий набору IP адресов либо набору IP сетей, что в принципе нам подходит. Но это не особенно гибко и я не уверен, что ядро Linux будет довольно, если мы создадим, допустим, 120 хешей под нужные нам автономные системы да и управление таким набором хэшей будет очень и очень проблематично.

Совершенно случайно в процессе изучения модуля xtables GeoIP мне пришла в голову мысли, что там используется примерно такой же алгоритм определения принадлежности сети к определенной стране, который нам и нужен для определения принадлежности к определенной автономной системе. Кроме этого, есть ряд веских замечаний от автора xtables GeoIP, судя по которым подход используемый им является более оптимальным: xtables-addons.sourceforge.net/geoip.php

Итак, давайте сначала соберем и установим модуль xtables geoip и после этого займемся его унификацией для решения начальной задачи — блокировки по ASN.

Установка модуля xtables GeoIP

Таких инструкций было множество, они довольно краткие поэтому позволю себе привести здесь полную инструкцию.
Устанавливаем требуемые пакеты:

apt-get install xtables-addons-common xtables-addons-source

В Debian Wheezy была проделана очень большая работа с Xtables и теперь не нужно проводить никаких дополнительных телодвижений, чтобы получить рабочие модули из пакета Xtables. Также за счет использования фреймворка DKMS не потребуется пересобирать модули вручную при обновлении/замене ядра — система все это решит автоматически.

Теперь пару слов о том, как работает GeoIP. Там используется довольно умный (на мой взгляд) подход, когда списки IP сетей, принадлежащих определенной стране приводятся в бинарный формат, сохраняются в файловой системе сервера и при вызове команды iptables затрагивающей данную страну, загружаются в память. Это позволяет обеспечить высокую скорость работы и сэкономить память, так как полный набор IP адресов всех сетей в мире занимает почти 500 мегабайт в несжатом виде.

Для xtables GeoIP используются базы сопоставления сеть-страна взятые с сайта компании MaxMind, но загружать и конвертировать в формат, который примет модуль ядра xtables, geoip требуется вручную.
Поехали:

cd /tmp
/usr/lib/xtables-addons/xt_geoip_dl

После данной операции в текущей папке будут найдены два файла с расширением CSV, в которых соответственно находятся списки IP сетей для протоколов IPv6 и IPv4 с указанием, к каким странам они принадлежат.
Теперь нам нужно конвертировать эти файлы в бинарный формат:

mkdir -p /usr/share/xt_geoip
/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip *.csv

В процессе конвертации мы увидим много интересных информационных сообщений, например, число IP v4/v6 диапазонов для каждой из стран:

759 IPv6 ranges for RU Russian Federation
5401 IPv4 ranges for RU Russian Federation

Все, мы готовы к работе, попробуем отсечь трафик, который идет, например, из Зимбабве:

iptables -I INPUT -p tcp --dport 80  -m geoip --src-cc ZW -j DROP

В тот момент, когда мы дадим эту команду, из файловой системы будет взят и загружен в ядро файл /usr/share/xt_geoip/LE/ZW.iv4, в котором находится список IP стран.

Обращаю внимание, друзья! Ни в коем случае не используйте подобное в продакшене НИ-КОГД-ДА. Это лучшая практика, как нельзя делать в сети интернет. Такое допускается делать лишь временно, например, в случае активного противодействия DDoS/DoS атакам либо просто для подсчета — сколько трафика идет с каждой страны. Всегда держите в памяти, что актуальность баз GeoIP оставляет желать лучшего и в забаненой Вами Зимбабве могут оказаться Ваши ключевые клиенты из Нью-Йорка (разумеется, лишенные доступа к Вашему ресурсу).

Создание базы по сетям принадлежащим ASN в формате MaxMind.

Чтобы максимально упростит себе жизнь давайте попробуем создать базы сопоставления сеть-ASN в том же формате, что MaxMind хранит данные сопоставления сеть-страна. При таком подходе мы сможем использовать скрипт xt_geoip_build без каких-либо изменений.

Как же создать подобную базу? Во-первых, нам понадобится текущий отпечаток роутинг-таблицы Интернета, так как информация о принадлежности сетей определенной ASN меняется ежеминутной и поэтому нет возможности всегда иметь актуальную базу. Где же взять этот отпечаток? Он всегда имеется в актуальном виде в формате MRT TABLE DUMP V2 на сайте Routevievs.org: archive.routeviews.org/bgpdata/.

Но есть небольшая проблема с данным форматом — он очень сложен для анализа и поэтому нам потребуется конвертер, который разрабатывается RIPE и называется BgpDump: bitbucket.org/ripencc/bgpdump/wiki/Home
К сожалению, в репозитории Debian данного конвертера нету и нам придется собрать его из исходного кода, это довольно тривиально, привожу инструкцию ниже:

apt-get install -y libbz2-dev 
cd /usr/src
wget http://www.ris.ripe.net/source/bgpdump/libbgpdump-1.4.99.13.tgz
tar -xf libbgpdump-1.4.99.13.tgz 
cd libbgpdump-1.4.99.13
./configure --prefix=/opt/libbgpdump
mkdir /opt/libbgpdump
make 
mv bgpdump /opt/libbgpdump

Но и формат данных, которые генерирует BgpDump не совпадает с форматом MaxMind и нам потребуется еще один конвертер (к счастью, много более простой), который мы реализовали на Perl, взять его можно по адресу: raw.github.com/FastVPSEestiOu/xt_asn/master/bgp_table_to_text.pl, после этого положите его по адресу /opt/bgp_table_to_text.pl и поставьте exec флаг (chmod +x).

Теперь у нас имеется полный комплект ПО, для генерации базы ASN-сеть в формате MaxMind. Для реализации всей задачи требуется выполнить ряд bash команд:

rm -f /opt/bgp/asn.csv
mkdir /opt/bgp
# http://phpsuxx.blogspot.com/2011/12/full-bgp.html
yesterday_date=$(date --date='1 days ago' '+%Y.%m')
yesterday_date_with_day=$(date --date='1 days ago' '+%Y%m%d')
# get routing data for yesterday at 5 o'clock 
wget http://archive.routeviews.org/bgpdata/${yesterday_date}/RIBS/rib.${yesterday_date_with_day}.0600.bz2 -O /opt/bgp/rib.bz2
# Обращаю внимание, что следующие команды выполняются мягко говоря "долго" (25 минут на i7 2600)
/opt/libbgpdump/bgpdump /opt/bgp/rib.bz2 | /opt/bgp_table_to_text.pl > /opt/bgp/asn.csv

После этого конвертируем по той же схеме как и данные Max Mind GeoIP:

/usr/lib/xtables-addons/xt_geoip_build -D /usr/share/xt_geoip /opt/bgp/asn.csv

В результате работы команды в папке /usr/share/xt_geoip/LE/ будет создано почти 100 тысяч файлов (по 2 для каждой ASN) и они будут использоваться для загрузки в модуль фильтрации ядра.

Модификация xtables geoip для использования его для определения принадлежности IP к определенной ASN

Если мы попробуем заменить название страны ZW в команде iptables на номер ASN, например, 11222, то мы получим ошибку:

geoip: invalid country code '11222'

Что же делать? Посмотреть во внутренности xt_geoip. Тут пару слов о том, как устроен GeoIP — он состоит из плагина для iptables (userspace), который загружает правила в ядро и модуля ядра (kernel space, соответственно). После беглого поиска по коду, мы обнаруживаем, что Country Code в формате ISO3166 хранится в формате беззнакового 16 битного числа, которое может хранить в себе числа вплоть до 65535.

Как мы уже упомянули ранее, формат ASN в данный момент принят 32х битный, поэтому чтобы отфильтровать трафик из/в 32 битную ASN (например, 190111) потребуется немного импровизации — потребуется найти свободный номер ASN в первых 65 тысячах (например, в данный момент свободна ASN 170) и перенести список сетей в бинарном формате в нее (mv /usr/share/xt_geoip/LE/190111.iv4 /usr/share/xt_geoip/LE/170.iv4), но при этом не забыв, что номер ASN используется «замененный».

Такой хак отлично сработает даже если Вам нужно оперировать со всеми ASN мира! Их суммарное число на сегодняшний день составляет ~46000 и легко помешается с учетом перестановок в 16 битовое беззнаковое число. Если же на момент прочтения статьи ASN станет более 65 тысяч, то придется накладывать патч на ядерную составляющую модуля GeoIP, но он будет достаточно прост — потребуется заменить short int на полноценный int или даже long (а вдруг появятся 64 битные ASN?).

Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

Чтобы добиться возможности использования номеров ASN вместо двухбуквенных кодов стран мы немного пропатчим код. А именно, закомментируем блок, в котором идет проверка, чтобы указанный аргумент iptables «страна» был именно двухбуквенным ISO кодом страны:

//if (strlen(cc) != 2) /* Country must be 2 chars long according
//                                               to the ISO3166 standard */
//  xtables_error(PARAMETER_PROBLEM,
//      "geoip: invalid country code '%s'", cc);
 
// Verification will fail if chars aren't uppercased.
// Make sure they are..
//for (i = 0; i < 2; i++)
//  if (isalnum(cc[i]) != 0)
//      cc[i] = toupper(cc[i]);
//  else
//      xtables_error(PARAMETER_PROBLEM,
//          "geoip:  invalid country code '%s'", cc);

И после этого заменим код упаковки двух 8 битных символов в 16 битное число на код, который просто читает 16 битное число из строки и сохраняет его:

//cc_int16 = (cc[0] << 8) | cc[1];
// Convert 16 bit unsinged integer (up to 65535) 
sscanf(cc, "%d", &cc_int16);

Также потребуется изменить код, который отображает код страны используя внутренне числовое представление страны (16 битовое число), теперь мы просто отображаем число без преобразований:

-printf("%s%c%c", i ? "," : "", COUNTRY(info->cc[i]));
+printf("%sxas%d", i ? "," : "", info->cc[i]);

В данном случае я позволил себе заменить asn на xas, так как в ряде случаев (32 битные ASN) это не реальный номер ASN (а подстановочный) и это мне хотелось подчеркнуть.

Итоговый файл с наложенным патчем можно взять здесь, в нашем репозитории на GitHub: raw.github.com/FastVPSEestiOu/xt_asn/3e3eebe8b2136d148fe71adc1218a656c363ada2/libxt_geoip_patched.c

Теперь дело за малым, нам нужно скомпилировать пакет xtables-addons-common (как раз в нем размещается модуль-расширение для iptables, работающий в пространстве пользователя) наложив на него данный патч:

cd /usr/src
apt-get install -y dpkg-dev devscripts build-essential fakeroot
apt-get source  xtables-addons-common
apt-get build-dep -y  xtables-addons-common
cd xtables-addons-1.42
# заменяем на патченную версию
wget https://raw.github.com/FastVPSEestiOu/xt_asn/3e3eebe8b2136d148fe71adc1218a656c363ada2/libxt_geoip_patched.c -Oextensions/libxt_geoip.c
dpkg-source --commit
Вводим "Patch for xtables geoip - ASN resolver"
debuild -us -uc

Теперь устанавливаем пропатченный пакет:

dpkg -i /usr/src/xtables-addons-common_1.42-2_amd64.deb

И после этого можно использовать 16 битные номера ASN в правилах ipables:

iptables -I INPUT -p tcp --dport 80 -m geoip --dst-cc 11222 -j DROP

Теперь Вы готовы отразить еще один тип атак! Кроме этого, аналогичные методы могут быть использованы для анализа легитимного трафика, который идет на Ваш сервер :)

Друзья! Успехов Вам в будущем году и поменьше DDoS атак, Ваш FastVPS!
Защита от DoS/DDoS атак с помощью фильтрации по номеру автономной системы (ASN)

Автор: pavelodintsov

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js