Я запускаю общедоступный сервис на основе UDP на AWS. Несколько недель назад начали срабатывать сигналы тревоги, свидетельствующие о действии атаки UDP-флуда.
Несколько лет назад, в результате предыдущей атаки DDOS, я обновил код сокета, чтобы обнаруживать эти типы атак и игнорировать входящие пакеты с любого IP-адреса, пытающегося заполнить порт поддельными запросами.
Перенесемся в сегодняшний день. Новая атака была на порядок масштабнее, чем что-либо ранее. Поэтому я создал несколько новых экземпляров для балансировки нагрузки и настроил код для более агрессивного регулирования. Кризис предотвращен.
У меня также возникла идея попробовать собрать все IP-адреса всех флудеров и просто заблокировать каждый IP-адрес с помощью вызова iptables ниже.
sudo iptables -A INPUT -s 1.2.3.4 -j DROP
куда 1.2.3.4
был заменен реальным IP-адресом. А затем у меня был скрипт, который бы запретил запускать эту команду для более чем 2000 IP-адресов, которые были задействованы во флуд-атаке, на основе других скриптов, которые я запускал. Я сделал это на одном конкретном экземпляре AWS, оставив другие экземпляры в покое. Идея состоит в том, что было бы более эффективно блокировать нарушающие IP-адреса на уровне брандмауэра, чем позволять самому коду сервера заниматься этим.
В результате загрузка ЦП резко возросла (более 50%) на экземпляре со всеми правилами iptables. Другие машины полагались на свой собственный программный код для сброса IP-адресов лавинной рассылки и были на нормальном уровне ЦП. Я закончил удаление правил из этого конкретного экземпляра.
Я бы подумал, что поиск IP-адреса в таблице будет дешевой операцией порядка O(1)
с хеш-таблицей разумного размера. Возможно, это линейно или просто потому, что iptables нужно регистрировать и вести учет каждого заблокированного пакета. Возможно, есть лучший способ массово заблокировать такое количество IP-адресов.
Как лучше всего заблокировать 2000+ IP-адресов без дополнительных затрат на ЦП?
Правила, как вы их написали, будут просматриваться одно за другим, и потребуется время, чтобы их обработать. Скорее всего, вы ищете ipset.
ipset create banned-hosts hash:ip
ipset add banned-hosts 1.2.3.4
:
ipset add banned-hosts 2.4.6.8
и сопоставьте на нем:
iptables -A INPUT -m set --match-set banned-hosts src -j DROP
Вы добавляете IP-адреса как отдельные правила в цепочке, что означает, что ядро должно пройти все правила для всех пакетов.
Может помочь пара оптимизаций:
DROP
правило к IPTables raw
стол вместо обычного filter
стол. Это означает, что для этих пакетов не создаются записи отслеживания соединений, что экономит ресурсы. Использовать iptables -t raw -A input -s 192.168.100.100 -j DROP
добавить к raw
стол.