Программируемая защита от DDoS: создавайте свою логику фильтрации атак в Magic Transit

Мы с гордостью представляем Programmable Flow Protection — систему, созданную для того, чтобы клиенты Magic Transit могли внедрять собственную пользовательскую логику защиты от DDoS-атак и развертывать ее в глобальной сети Cloudflare. Это обеспечивает точную, состоятельную защиту для пользовательских и проприетарных протоколов, построенных на UDP. Система спроектирована для обеспечения максимально возможного уровня настройки и гибкости для отражения DDoS-атак любого масштаба.

Programmable Flow Protection в настоящее время находится в стадии бета-тестирования и доступна для всех клиентов Magic Transit Enterprise за дополнительную плату.

Programmable Flow Protection настраивается

Наши существующие системы защиты от DDoS были разработаны для понимания и защиты популярных, хорошо известных протоколов от DDoS-атак. Например, наша система Advanced TCP Protection использует определенные известные характеристики протокола TCP для выдачи челленджей (challenge) и установления легитимности клиента. Точно так же наша система Advanced DNS Protection строит профиль DNS-запросов для каждого клиента, чтобы смягчать DNS-атаки. Наша общая платформа защиты от DDoS также понимает общие шаблоны для множества других известных протоколов, включая NTP, RDP, SIP и многие другие.

Однако пользовательские или проприетарные UDP-протоколы всегда были проблемой для систем защиты от DDoS Cloudflare, потому что наши системы не обладают соответствующими знаниями о протоколе, чтобы принимать интеллектуальные решения о пропуске или отбрасывании трафика.

Programmable Flow Protection решает эту проблему. Теперь клиенты могут написать собственную программу eBPF, которая определяет, какие пакеты являются «хорошими» и «плохими», и как с ними поступать. Cloudflare затем запускает эту программу по всей нашей глобальной сети. Программа может либо отбрасывать, либо проверять «плохие» пакеты, не давая им достичь источника клиента.

Проблема атак на основе UDP

UDP — это протокол транспортного уровня без установления соединения. В отличие от TCP, в UDP нет рукопожатия или состоятельных соединений. Он не гарантирует, что пакеты придут по порядку или ровно один раз. UDP вместо этого делает приоритет на скорости и простоте и поэтому хорошо подходит для онлайн-игр, VoIP, потокового видео и любых других случаев использования, где приложению требуется связь в реальном времени между клиентами и серверами.

Наши системы защиты от DDoS всегда могли обнаруживать и смягчать атаки на хорошо известные протоколы, построенные поверх UDP. Например, стандартный DNS-протокол построен на UDP, и каждый DNS-пакет имеет известную структуру. Если мы видим DNS-пакет, мы знаем, как его интерпретировать. Это облегчает нам обнаружение и отбрасывание DNS-атак.

К сожалению, если мы не понимаем протокол внутри полезной нагрузки UDP-пакета, у наших систем защиты от DDoS во время смягчения атак есть ограниченные возможности. Если злоумышленник отправляет большой поток UDP-трафика, который не соответствует ни одному известному шаблону или протоколу, Cloudflare может либо полностью заблокировать комбинацию IP-адреса и порта назначения, либо применить к ней ограничение скорости. Это грубая «последняя линия обороны», предназначенная только для того, чтобы остальная часть сети клиента оставалась онлайн, и она может быть проблемной по нескольким причинам.

Во-первых, блокировка или общее ограничение скорости не отличает хороший трафик от плохого, а значит, эти меры, скорее всего, приведут к тому, что легитимные клиенты столкнутся с задержками или потерей соединения — делая работу за злоумышленника! Во-вторых, общее ограничение скорости может быть слишком строгим или слишком мягким в зависимости от клиента. Например, клиенту, который ожидает получения 1 Гбит/с легитимного трафика, вероятно, требуется более агрессивное ограничение скорости по сравнению с клиентом, который ожидает получения 25 Гбит/с легитимного трафика.

Introducing Programmable Flow Protection: custom DDoS mitigation logic for Magic Transit customers

Иллюстрация содержимого UDP-пакета. Пользователь может определить допустимую полезную нагрузку и отклонять трафик, не соответствующий заданному шаблону.

Платформа Programmable Flow Protection была создана для решения этой проблемы, позволяя нашим клиентам диктовать, как на самом деле выглядит «хороший» и «плохой» трафик. Многие из наших клиентов используют пользовательские или проприетарные UDP-протоколы, которые мы не понимаем — и теперь нам это и не нужно.

Как работает Programmable Flow Protection

В предыдущих записях блога мы описывали, как «flowtrackd», наша состоятельная система защиты от DDoS на сетевом уровне, защищает пользователей Magic Transit от сложных TCP- и DNS-атак. Мы также описывали, как мы используем такие технологии Linux, как XDP и eBPF, для эффективного смягчения распространенных типов масштабных DDoS-атак.

Programmable Flow Protection объединяет эти технологии новым способом. С помощью Programmable Flow Protection клиент может написать собственную программу eBPF, которая решает, пропускать, отбрасывать или проверять отдельные пакеты на основе произвольной логики. Клиент может загрузить программу в Cloudflare, и Cloudflare будет выполнять ее для каждого пакета, предназначенного для его сети. Программы выполняются в пользовательском пространстве, а не в пространстве ядра, что дает Cloudflare гибкость для поддержки различных клиентов и сценариев использования на платформе без ущерба для безопасности. Программы Programmable Flow Protection запускаются после всех существующих средств защиты Cloudflare от DDoS, поэтому пользователи по-прежнему получают выгоду от наших стандартных средств защиты.

Существует много сходств между программой eBPF XDP, загруженной в ядро Linux, и программой eBPF, работающей на платформе Programmable Flow Protection. Оба типа программ компилируются в байт-код BPF. Оба они проходят через «верификатор», чтобы обеспечить безопасность памяти и проверить завершение программы. Они также выполняются в быстрой, легковесной виртуальной машине для обеспечения изоляции и стабильности.

Однако программы eBPF, загруженные в ядро Linux, используют множество специфичных для Linux «вспомогательных функций» для интеграции со стеком сети, поддержания состояния между выполнениями программы и отправки пакетов на сетевое устройство. Programmable Flow Protection предлагает ту же функциональность по выбору клиента, но с другим API, специально предназначенным для реализации защиты от DDoS. Например, мы создали вспомогательные функции для хранения состояния клиентов между выполнениями программы, выполнения криптографической проверки и отправки пакетов-челленджей клиентам. С помощью этих вспомогательных функций разработчик может использовать мощь платформы Cloudflare для защиты собственной сети.

Объединение знаний клиента с сетью Cloudflare

Давайте рассмотрим пример, чтобы проиллюстрировать, как специфичные для протокола знания клиента можно объединить с сетью Cloudflare для создания мощных средств защиты.

Допустим, клиент размещает игровой сервер на UDP-порту 207. Игровой движок использует проприетарный заголовок приложения, специфичный для игры. Cloudflare не имеет знаний о структуре или содержимом заголовка приложения. Клиент подвергается DDoS-атакам, которые перегружают игровой сервер, и игроки сообщают о задержках в игровом процессе. Атакующий трафик поступает с высоко рандомизированных исходных IP-адресов и портов, и данные полезной нагрузки также кажутся случайными.

Чтобы смягчить атаку, клиент может использовать свои знания о заголовке приложения и развернуть программу Programmable Flow Protection для проверки действительности пакета. В этом примере заголовок приложения содержит токен, уникальный для игрового протокола. Следовательно, клиент может написать программу для извлечения последнего байта токена. Программа пропускает все пакеты с правильным значением и отбрасывает весь остальной трафик:

#include <linux/ip.h>
#include <linux/udp.h>
#include <arpa/inet.h>

#include "cf_ebpf_defs.h"
#include "cf_ebpf_helper.h"

// Пользовательский заголовок приложения
struct apphdr {
    uint8_t  version;
    uint16_t length;   // Длина токена переменной длины
    uint8_t  token[0]; // Токен переменной длины
} __attribute__((packed));

uint64_t
cf_ebpf_main(void *state)
{
    struct cf_ebpf_generic_ctx *ctx = state;
    struct cf_ebpf_parsed_headers headers;
    struct cf_ebpf_packet_data *p;

    // Разобрать заголовки пакета с помощью предоставленной вспомогательной функции
    if (parse_packet_data(ctx, &p, &headers) != 0) {
        return CF_EBPF_DROP;
    }

    // Отбрасывать пакеты, адресованные не на порт 207
    struct udphdr *udp_hdr = (struct udphdr *)headers.udp;
    if (ntohs(udp_hdr->dest) != 207) {
        return CF_EBPF_DROP;
    }

    // Получить заголовок приложения из полезной нагрузки UDP
    struct apphdr *app = (struct apphdr *)(udp_hdr + 1);
    if ((uint8_t *)(app + 1) > headers.data_end) {
        return CF_EBPF_DROP;
    }

    // Выполнить проверки памяти для удовлетворения верификатора
    // и безопасного доступа к токену
    if ((uint8_t *)(app->token + token_len) > headers.data_end) {
        return CF_EBPF_DROP;
    }

    // Проверить последний байт токена на соответствие ожидаемому значению
    uint8_t *last_byte = app->token + token_len - 1;
    if (*last_byte != 0xCF) {
        return CF_EBPF_DROP;
    }

    return CF_EBPF_PASS;
}

Программа eBPF для фильтрации пакетов в соответствии со значением в заголовке приложения.

Эта программа использует специфичную для приложения информацию для создания более целенаправленной защиты, чем та, которую Cloudflare может разработать самостоятельно. Теперь клиенты могут сочетать свои собственные знания с мощью глобальной сети Cloudflare, чтобы поглощать и отражать масштабные атаки лучше, чем когда-либо прежде.

Выходя за рамки файрволов: отслеживание с сохранением состояния и челленджи

Многие проверки по шаблону, подобные выполненной в примере выше, можно осуществить с помощью традиционных файрволов. Однако программы предоставляют полезные примитивы, недоступные в файрволах, включая переменные, условное выполнение, циклы и вызовы процедур. Но что действительно отличает Programmable Flow Protection от других решений, так это его способность отслеживать потоки с сохранением состояния и проверять клиентов, требуя доказательств их легитимности. Распространенный тип атаки, демонстрирующий эти возможности, — это атака повторного воспроизведения (replay attack).

Introducing Programmable Flow Protection: custom DDoS mitigation logic for Magic Transit customers

При атаке повторного воспроизведения злоумышленник многократно отправляет пакеты, которые были действительны в какой-то момент и, следовательно, соответствуют ожидаемым шаблонам трафика, но больше не являются валидными в текущем контексте приложения. Например, злоумышленник может записать часть своего легитимного игрового трафика и использовать скрипт для дублирования и отправки этого же трафика с очень высокой скоростью.

С помощью Programmable Flow Protection пользователь может развернуть программу, которая проверяет подозрительных клиентов и отбрасывает скриптированный трафик. Мы можем расширить наш исходный пример следующим образом:


#include <linux/ip.h>
#include <linux/udp.h>
#include <arpa/inet.h>

#include "cf_ebpf_defs.h"
#include "cf_ebpf_helper.h"

uint64_t
cf_ebpf_main(void *state)
{
    // ...
 
    // Получить статус для этого исходного IP-адреса (отслеживается с сохранением состояния)
    uint8_t status;
    if (cf_ebpf_get_source_ip_status(&status) != 0) {
        return CF_EBPF_DROP;
    }

    switch (status) {
        case NONE:
		// Выдать пользовательский челлендж для этого исходного IP
             issue_challenge();
             cf_ebpf_set_source_ip_status(CHALLENGED);
             return CF_EBPF_DROP;


        case CHALLENGED:
		// Проверить, проходит ли этот пакет челлендж
		// с помощью пользовательской логики
             if (verify_challenge()) {
                 cf_ebpf_set_source_ip_status(VERIFIED);
                 return CF_EBPF_PASS;
             } else {
                 cf_ebpf_set_source_ip_status(BLOCKED);
                 return CF_EBPF_DROP;
             }


        case VERIFIED:
		// Этот исходный IP прошел проверку
		return CF_EBPF_PASS;

	 case BLOCKED:
		// Этот исходный IP был заблокирован
		return CF_EBPF_DROP;

        default:
            return CF_EBPF_PASS;
    }


    return CF_EBPF_PASS;
}

Программа eBPF для проверки UDP-соединений и управления соединениями с сохранением состояния. Этот пример упрощен для иллюстрации.

Программа отслеживает с сохранением состояния исходные IP-адреса, которые она видела, и отправляет пакет с криптографической задачей (челленджем) обратно неизвестным клиентам. Легитимный клиент, работающий на валидном игровом клиенте, способен правильно решить задачу и ответить доказательством, а скрипт злоумышленника — нет. Трафик от атакующего помечается как «заблокированный», и последующие пакеты отбрасываются.

С этими новыми возможностями клиенты могут отслеживать потоки с сохранением состояния и гарантировать, что только реальные, проверенные клиенты могут отправлять трафик на их исходные серверы. Хотя мы сосредоточили пример на играх, потенциальные случаи использования этой технологии распространяются на любой протокол, основанный на UDP.

Начните сегодня

Мы рады предложить функцию Programmable Flow Protection клиентам Magic Transit Enterprise. Поговорите со своим менеджером по работе с клиентами, чтобы узнать больше о том, как вы можете включить Programmable Flow Protection для защиты своей инфраструктуры.