Как в iptables блокировать все соединения SYN_RECV?

Идет жуткий SYN-FLOOD на сервер, необходимо блокировать все соединения SYN_RECV.

Сейчас блокирую просто по IP:
netstat -n4 | grep SYN_RECV  | awk {'print $5'} | awk -F ':' {'print $1'} | sort | uniq -c | awk {'print $2'} | xargs -t -l iptables -A INPUT -p tcp -j DROP -s

Но в iptables уже порядка 10к айпишников и надо поступить иначе.
  • Вопрос задан
  • 12128 просмотров
Решения вопроса 1
DerBlogger
@DerBlogger

SYN_RECV - это состояние tcp-соединения во время three-handshake, означающее что сервер принял пакет с установленным флагом SYN (запрос на соединение), отправил SYN/SYN-ACK клиенту и ожидает от клиента пакет с флагом ACK.

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

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

Соответственно, Вам нужно выяснить закономерность (периодичность, количество запросов и т. п.), позволяющую отличить легитимный хост от атакующего конкретно в Вашем случае, и в соответствии с ней создать правила.

Если говорить обобщенно, то в Вашем случае, я думаю, проблему можно решить с помощью модуля recent в iptables. Уверен, его функционала Вам будет достаточно. Сможете обойтись несколькими правилами. Алгоритм следует применить примерно такой:

1. Сначала разрешаете входящий tcp-трафик по соединениям в состояниях ESTABLISHED и RELATED (модуль conntrack).

iptables -I INPUT 1 -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

2. Открываете нужные порты, разрешая пропуск пакетов по этим правилам только в случаях если:
- установлен флаг SYN (опция --syn);
- соединение находится в состоянии NEW (модуль conntrack);
- не превышен лимит соединений с одного ip-адреса (модуль recent).
Примерно так:
iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW -m recent --name webtraffic --update --seconds 5 --hitcount 16 -j DROP

iptables -A INPUT -p tcp -m multiport --dports 80,443 --syn -m conntrack --ctstate NEW -j ACCEPT


Первое правило будет применено только к пакетам с установленным флагом SYN, которые приходят с отдельно взятого IP-адреса со скоростью более 16 пакетов в течение 5 секунд. Этим правилом будет отброшен флуд.

Второе правило пропустит пакеты, не подошедшие под предыдущее правило (легитимный трафик).

Разумеется, все нужно адаптировать под Ваши условия и нагрузку. Подробности по модулям смотрите в man iptables-extensions. Настоятельно рекомендую ознакомиться с описанием модуля recent для лучшего понимания.

3. Дропаете весь остальной tcp-трафик либо отдельным правилом, либо политикой по-умолчанию.

Также, дабы легитимных пользователей не откидывало при попытке подключения, Вы можете увеличить очередь SYN-пакетов в sysctl, в соответствии с имеющимися системными ресурсами. За это отвечает параметр net.ipv4.tcp_max_syn_backlog, и уменьшить таймаут для соединений в состоянии SYN_RECV, за что отвечает параметр net.netfilter.nf_conntrack_tcp_timeout_syn_recv.
Рекомендуемые параметры индивидуальны для каждой системы. У меня используются такие:
net.ipv4.tcp_max_syn_backlog = 262144
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 20

Ответ написан
Пригласить эксперта
Ответы на вопрос 1
EvilMan
@EvilMan
В новых ядрах появилась поддержка SYN-PROXY, что очень сильно может ВАМ помочь.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы