Нам потребуется Ostinato для генерации произвольных пакетов. Wireshark для захвата сетевых пакетов, а так же виртуальная машина на CentOS, в которую мы установим tcpdump (работа с этой программой будет показана позднее).
Модель будет такая:
- С реальной машины мы будем генерировать поток произвольных пакетов (для примера возьмём ICMP), направленный на виртуальную машину.
- На виртуальной машине фиксируем входящий трафик (поток ICMP).
- Средствами iptables ограничим поток принимаемых пакетов.
Итак, поехали.
Настраиваем генератор пакетов Ostinato
Надеюсь, вы прошли простой урок по ссылке вверху и работа с Ostinato для вас не является проблемой. Создаём новый поток пакетов (Stream).
После этого начинаем заполнять характеристики протокола. Нам нужен ICMP протокол, поэтому выставим примерно такой формат:
Указываем MAC-адрес назначения (нашей виртуальной машины). В качестве источника оставляем нули (наша собственная станция).
Заполняем остальные поля IP протокола. В частности IP-адреса источника и назначения.
Указываем параметр ICMP-запроса.
Настраиваем “поток”, я указал параметр 4 пакета в секунду. А так же возврат на начало после того, как поток истечёт (что означает бесконечный выброс пакетов).
Запускаем (play) в главном окне программы (не забыв нажать кнопку Apply!!). Фиксируем исходящий поток данных.
Проверяем выход пакетов Wireshark
На виртуальной машине запускаем:
# tcpdump -i eth0 icmp
для фиксации пакетов ICMP-протокола. Я немного поздновато снял скриншот, увидите почему.
Итак, самое интересное – сохраняем правила файрволла в файл, затем открываем его для редактирования:
# iptables-save > /etc/sysconfig/iptables
# vi /etc/sysconfig/iptables
и добавляем там следующие правила в цепочку INPUT
-A INPUT -p icmp -m limit --limit 1/sec --limit-burst 1 -j ACCEPT
-A INPUT -p icmp -j DROP
Что это значит? Мы используем модуль limit. Его можно представить в качестве большого сосуда объёмом в –limit-burst пакетов (в нашем случае 1). Сосуд опустошается со скоростью –limit 1 пакет в секунду. Вот пока наш сосуд не переполнился – правила идут по его действию (-j ACCEPT), то есть принимаются. Как только “сосуд переполняется”, пакеты следуют к следующим правилам, а следующее у нас -j DROP.
Если бы у нас был сосуд ёмкостью в 10 пакетов (т.е. параметр –limit-burst был бы равен 10), то первые 10 пингов бы мы приняли, а затем они бы начали дропаться.
Теперь посмотрим, что мы получили. По идее, к нам приходят 4 пакета в секунду. Мы принимаем только один. Остальные будем дропать.
Проверим это:
# watch -n 1 iptables -vnL INPUT
Эта команда раз в секунду (параметр -n) выполнит команду iptables -vnL для цепочки INPUT, т.е. показывает статистику по пакетам/байтам.
Мы увидим два счётчика, причём у первого правила счётчик увеличивается на 1 каждую секунду, а второй счётчик – на три каждую секунду. Как раз то, что мы и хотели!
Иногда будет не совсем ровно считать, потому что пакеты приходят с небольшим запазданием и в эту секунду может посчитать 2 пакета дроп, а в следующую – 4.
Вроде получилось! Теперь как мы можем это использовать?
Выводы
Ограничить число TCP-сегментов со статусом NEW (флаги SYN) на порт локального SSH, что позволит существенно замедлить работу переборщика паролей (бруфорсера).
Но тут всплывает существенный недостаток:
Если переборщик будет активен, мы тоже не сможем залогиниться, потому что не попадём в “ёмкость”. Нам нужно организовать отдельную “ёмкость” для каждого source IP. Тогда пусть он как хочет переполняет свою – мы попадём в нужную очередь свободно! Для этого можно использовать другой модуль – hashlimit. Попробуем реализовать эту возможность.
Дальше я продолжаю писать статью на другой виртуалке (помощнее), здесь у меня изменились IP-адреса. Для CentOS (виртуалка) 192.168.56.10, для генератора пакетов соответственно 192.168.56.1.
Перепишем наши правила следующим образом:
-A INPUT -p icmp -m hashlimit --hashlimit 1/sec --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name ICMPFLOOD -j ACCEPT
-A INPUT -p icmp -j DROP
Здесь почти всё то же самое, что и у limit (ещё бы, hashlimit – прямой его потомок), но добавили параметры:
- hashlimit-mode srcip (режим разделения хеша. srcip – означает для каждого source ip свой хеш, т.е. источника пакетов. Может быть dstip, srcport).
- hashlimit-name ICMPFLOOD (произвольное имя для таблицы хешей). Таблицы лежат в /proc/net/ipt_hashlimit/ с теми же именами.
Запущу в том же Ostinato второй поток с немного другим Source IP, с похожими параметрами. Попутно будем отслеживать содержимое нашей таблицы:
# watch -n 1 cat /proc/net/ipt_hashlimit/ICMPFLOOD
Здесь мы видим несколько значений. Каждая строка – отдельный источник пакетов.
Первая цифра – счётчик (у нас 9) это значение по умолчанию, мы могли бы его указать прямо в правиле файрволла, (–hashlimit-htable-expire) но по дефолту 10 секунд. Это время жизни хеша в таблице. Каждую секунду счётчик уменьшается на 1. Но если пакеты попадающие под это правило продолжают поступать – счётчик снова выставляется в исходное значение. Далее идёт IP адрес источника, что очевидно. Три последние числа – весьма характерны. Первое из них – текущее значение счётчика пакетов, умноженное на определённый коэффициент. Второе – значение burst с этим же коэффициентом. А третье – средний интервал между пакетами (в секундах) умноженный на 32000.
Кстати, моё правило можно заменить другим, попроще:
-A INPUT -p icmp -m hashlimit --hashlimit-above 1/sec --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name ICMPFLOOD -j DROP
И всё! В этом правиле мы отмечаем, что будем дропать пакеты свыше (-above) 1/секунду.
Comments: