FastNetMon

Wednesday, 24 December 2014

Как работает механизм SYN Cookie в ядре Linux?

Всем привет! 

Итак, давайте определимся, чем же опасен для нас SYN флуд? Он опасен в первую очередь тем, что вынуждает сервер создавать тысячи и миллионы записей в системных таблицах/хэшах трекинга соединений.  Это вызывает две проблемы - замедление обработки и возможность упереться в лимит размера соотвествующей таблицы соединений. В этом случае самый очевидны способ спастись - не сохранять информацию о каждом пришедшем соединении.

Именно это и делает SYN cookie. В ответ на клиентский SYN пакет мы НЕ сохраняем никакой информации о соединении, а пакуем ее в ответный SYN+ACK пакет и отправляем клиенту. И лишь в случае, когда клиент ответит нам своим ACK передав эту информацию - мы ее проверим, распакуем информацию содержащуюся в нем и создадим запись о таком соединении и откроем обмен данными.

Уверен, многие в своей ежедневной практике используют  механизм  syn cookie, который позволяет решать проблемы с syn флудом.

Как известно, эта фича включается так:
sysctl -w net.ipv4.tcp_syncookies = 1
Но когда именно они включаются? Как работают? Всегда ли это панацея? На эти вопросы я постараюсь ответить ниже.

Вся обработка входящего tcp соединения начинается в файле net/ipv4/tcp_input.c в функции tcp_conn_request. Там сразу после приема пакета осуществляется следующая проверка:
if ((sysctl_tcp_syncookies == 2 || inet_csk_reqsk_queue_is_full(sk)) && !isn) {      want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name); }
Дословно она означает, что syn cookie включаются (не посылаются! А просто включаются!) если параметр sysctl -w net.ipv4.tcp_syncookies = 2 либо когда переполнится syn очередь для сокета (а она в свою очередь задается через параметр net.ipv4.tcp_max_syn_backlog = 2048).

Уже сейчас можно понять, что 2048 - это очень много и почти любое приложение после получения такого числа запросов на подключение погибнет. При этом syn cookie включенные в режиме "1" еще даже не включатся!

Чуточку дальше в том же файле tcp_input.c осуществляется проверка - а не переполнена ли очередь ожидания на слушающем (listen) сокете, она в свою очередь задается на уровне приложения, через второй аргумент системного вызова listen. И если она полна - то соединение просто отбрасывается, безотносительно режиму syn cookie вообще! Система предполагает, что приложение не может больше отработать и в принципе не принимает трафик. На этом обработка кончается. Если же очередь не забита - мы движемся дальше.

Обращаю внимание! Что syn cookie еще НЕ был отправлен! Даже если он был включен на какой-то из предыдущих проверок.

Теперь мы вызываем функцию cookie_init_sequence, которая в свою очередь дергает cookie_v4_init_sequence, которая объявлена в net/ipv4/syncookies.c. И там параметры входящего соединения хэшируются с помощью хэш функции sha1 (secure_tcp_syn_cookie). В свою очередь, стоит обратить внимание, что sha1 - это довольно тяжелая функция для процессора и довольно серьезный Intel E5 2620 может хэшировать не более 400 мегабайт/секунду в расчете на 1 ядро. Постойте пугаться! Не съедят syn cookie Ваш процессор, даже довольно слабый 2620 может обработать до 32Gb/s чисто на хэшировании, это огромные цифры, так что нагрузки на процессор пугаться не стоит - я просто привел информацию о том, что это не бесплатная операция.

И после того как эта cookie сформирована, мы посылаем ее клиенту. Как можно заметить - режим "2" работы syn cookie на сервере, где ожидаются атаки - предпочтительнее. Но стоит понимать, что syn cookie - это хак, который не особо согласуется с протоколом tcp и бывает, что он приводит к неработоспособности ряда фич, поэтому использовать его нужно лишь после тщательных тестов. Но при этом такой подход все равно  не защищает приложения должным образом.

Как хорошее и надежное решение данной проблемы стоит использовать iptables/netfilter цель SYN PROXY, которая блокирует  syn флуд раньше, чем они пойдет в обработку ядром (на этапе фильтрации через netfilter). Но тут стоит отметить, что данный функционал был добавлен в 3.12 ядре и присутствует только в RHEL/CentOS 7, в более младших версиях дистрибутивов такой возможности нету и вряд ли появится.

Но я бы хотел добавить, что syn cookie должны быть ВКЛЮЧЕНЫ в обязательном порядке. Вообще без них Linux упадет от самой слабой атаки syn флудом.

В чем же отличия 1 и 2го режимов syn cookie? В первом режиме они подключаются, когда переполняется очередь syn соединений на 1 порт, а во втором режиме они включаются безусловно даже очередь пуста. То есть для ВСЕХ соединений.

Подробнее читайте в документации ядра Linux - тут :) Все рассуждения основаны на анализе ядра ядра 3.18, в Вашей версии ядра все может быть ИНАЧЕ!

2 comments :

  1. > бывает, что он приводит к неработоспособности ряда фич

    А каких, например? Например тех, которые приходят как tcp опции в syn пакете?

    ReplyDelete
    Replies
    1. Именно про них и речь. Как-то запихать их в стек никак не получится. Если размер окна модно изменить отдельно, то ряд опций - не получится.

      Delete

Note: only a member of this blog may post a comment.