Материал просмотрен 505 раз(а)

Нам потребуется Ostinato для генерации произвольных пакетов. Wireshark для захвата сетевых пакетов, а так же виртуальная машина на CentOS, в которую мы установим tcpdump (работа с этой программой будет показана позднее).

Модель будет такая:

  1. С реальной машины мы будем генерировать поток произвольных пакетов (для примера возьмём ICMP), направленный на виртуальную машину.
  2. На виртуальной машине фиксируем входящий трафик (поток ICMP).
  3. Средствами iptables ограничим поток принимаемых пакетов.

Итак, поехали.

Настраиваем генератор пакетов Ostinato

Надеюсь, вы прошли простой урок по ссылке вверху и работа с Ostinato для вас не является проблемой. Создаём новый поток пакетов (Stream).

Создаём новый пакет Stream

Создаём новый пакет Stream

После этого начинаем заполнять характеристики протокола. Нам нужен ICMP протокол, поэтому выставим примерно такой формат:

Задаём характеристики протокола

Задаём характеристики протокола

Указываем MAC-адрес назначения (нашей виртуальной машины). В качестве источника оставляем нули (наша собственная станция).

Указываем MAC-адрес назначения

Указываем MAC-адрес назначения

Заполняем остальные поля IP протокола. В частности IP-адреса источника и назначения.

Заполняем адреса источника и назначения

Заполняем адреса источника и назначения

Указываем параметр ICMP-запроса.

Формируем ICMP-запрос

Формируем ICMP-запрос

Настраиваем “поток”, я указал параметр 4 пакета в секунду. А так же возврат на начало после того, как поток истечёт (что означает бесконечный выброс пакетов).

Устанавливаем силу потока

Устанавливаем силу потока

Запускаем (play) в главном окне программы (не забыв нажать кнопку Apply!!). Фиксируем исходящий поток данных.

Проверяем выход пакетов Wireshark

Wireshark фиксирует поток

Wireshark фиксирует поток

На виртуальной машине запускаем:

# tcpdump -i eth0 icmp

для фиксации пакетов ICMP-протокола. Я немного поздновато снял скриншот, увидите почему.

__1

Итак, самое интересное – сохраняем правила файрволла в файл, затем открываем его для редактирования:

# 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 пингов бы мы приняли, а затем они бы начали дропаться.

___3

Теперь посмотрим, что мы получили. По идее, к нам приходят 4 пакета в секунду. Мы принимаем только один. Остальные будем дропать.

Проверим это:

# watch -n 1 iptables -vnL INPUT

Эта команда раз в секунду (параметр -n) выполнит команду iptables -vnL для цепочки INPUT, т.е. показывает статистику по пакетам/байтам.

Мы увидим два счётчика, причём у первого правила счётчик увеличивается на 1 каждую секунду, а второй счётчик – на три каждую секунду. Как раз то, что мы и хотели!

Иногда будет не совсем ровно считать, потому что пакеты приходят с небольшим запазданием и в эту секунду может посчитать 2 пакета дроп, а в следующую – 4.

____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 – прямой его потомок), но добавили параметры:

  1. hashlimit-mode srcip (режим разделения хеша. srcip – означает для каждого source ip свой хеш, т.е. источника пакетов. Может быть dstip, srcport).
  2. 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/секунду.