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

    Введение


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


    В интернете и на Хабре было очень много публикаций на тематику защиты, но в основном они сводятся к следующим подходам основанным на группировке 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 (статистика почти в реальном времени)


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


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

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



    Если же 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.



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

    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?).



    Чтобы добиться возможности использования номеров 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!
    FASTVPS LLC
    61,00
    Хостинг Вашего Успеха с 2006 года.
    Поделиться публикацией

    Комментарии 11

      +1
      Кстати есть готовые утилиты для блокировки по базе GeoIP на базе стран blog.scopenco.net/soft-ddos-protection/
        0
        Спасибо, интересные скрипты! И вариант с ip route blackhole будет работать очень эффективно за счет обратки по очень эффективным алгоритмам внутри ядра, но он может блокировать лишь весь трафик, если нужно отсечь часть — это не выйдет.
          +1
          Все верно, для этого есть вариант с iptables
            0
            Да, в случае GeoIP в принципе префиксов не так много на страну,

            Топ 10 выглядит примерно так:
            cat /tmp/GeoIPCountryWhois.csv | sed 's/[,"]/ /g' | awk '{print $5}'|sort |uniq -c | sort -g |tail -n 10
            2541 UA
            2573 NL
            2732 PL
            2863 AU
            2965 CA
            3035 FR
            4772 DE
            5401 RU
            6236 GB
            8327 US
            


            Хотя если используется десятка стран, то это почти 50 000 правил, что не лучшим образом скажется на производительности.
        +1
        Все верно, для этого есть вариант с iptables
          +3
          К какому кейсу можно применить данное руководство?
          1) Злоумышленник арендовал 20 серверов с гигабитным шаредом в OVH и съел канал.
          Именно для этого случая используется BlackHole Community 666 на BGP шлюзе. Ваш способ не подходит, канал итак забит.
          2) Атака является распределенной. Данный способ также не поможет.
            0
            FreeLSD, задача поиска «универсального средства отражения DoS/DDoS» не стояла перед нами, рассматривался лишь один из подходов — фильтрация по ASN. Который, к слову, может быть использован для отражения атак любой емкости с любым числом атакующих узлов с небольшими изменениями (разумеется, меняется реализация, вместо iptables потребуются высокопроизводительные фаерволлы и роутеры, в которые должна быть загружена информация об атакующих узлах).

            1) Уж не знаю как поможет BGP Blackhole «отбить атаку», так как он предназначен для полного отсечения трафика на определенный свой IP, а не для блокировки IP/сетей злоумышленников. BGP Blaсkhole может быть использован как средство защиты Дата Центра/инфраструктуры, но это вовсе не средство для борьбы с атакой и ее отражения.

            К слову, приведенный Вами OVH довольно «субъективно» относится к безопасности своих сетей и это отчетливо видно по странице: stopddos.ru/current/

            2) В статье хорошо описано, что как раз на случай распределенных атак это становится актуально. По нашим наблюдениям ботнеты обычно создаются на базе определенного Датацентра/провайдера.

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

            Если кому интересны кейсы кроме отбива атак могу привести несколько идей наскидку:
            — Блокировка/разрешение доступа к определенным ресурсам на основании провайдера (например, в случае локальных ресурсов, которые частично смотрят в сеть)
            — Сбор статистики о провайдерах посетителей сайта
            — Отсечение тех или иных «особо назойливых» ботов
            — Включите фантазию :)
            +1
            Для бана школьников достаточно tcpdump + iptables. Только это не DDos. А вот если не зайти на консоль, когда развлекаются от гигабита, то кроме железа от Juniper на уровне ДЦ ничего не поможет.
              0
              Ну почему же, 10 и 40 гигабит подводимые к оконечному оборудованию (серверу) уже вовсе не редкость. Тем более, Linux ничем не хуже по части роутинга, чем специализированное железо. А если учесть новые карты на рынке класса Intel 540, то вообще ничем-ничем не хуже.

              Кроме этого, Вы же понимаете, что «железо от Juniper» не поможет даже от половины типов атак. Все более-менее нестандартные атаки отражаются сложным анализом трафика от клиентов и последующей генерацией правил для сетевого оборудования.
              0
              Тема стара как мир, но ихмо, не понятно зачем это делать на уровне ОС :)
                0
                А на каком делать? Если вопрос касается анализа трафика в бизнес-приложении, то, разумеется, правильнее сделать его на уровне приложения через тот же GeoIP, но если же задача реализуется на уровне системного администрирования — то, увы, это самый эффективный способ.

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

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