07.03.2006

Очередные странности ipset

В системе фильтрации Netfilter/iptables уже достаточно давно поддерживается модуль ipset, предназначенный для работы с наборами адресов/номеров портов в фильтрах iptables. Однако поддерживаемые модулем средства восстановления наборов из файлов, отличаются рядом странностей, о которых я неоднократно писал автору модуля, но обсуждение всякий раз завершалось ответом типа: “Это не ошибка, а особенность программы”.

В системе фильтрации Netfilter/iptables уже достаточно давно поддерживается модуль ipset, предназначенный для работы с наборами адресов/номеров портов в фильтрах iptables. Этот модуль обеспечивает мощные средства создания динамических фильтров (см., например, статью "Создание динамических правил фильтрации пакетов"). Однако поддерживаемые модулем средства восстановления наборов из файлов, отличаются рядом странностей, о которых я неоднократно писал автору модуля, но обсуждение всякий раз завершалось ответом типа: “Это не ошибка, а особенность программы”.

На сей раз обнаружилась еще одна странность, которая на мой взгляд весьма осложняет использование возможностей ipset и позволяет с легкостью создавать пакетные фильтры, которые будут вести себя совершенно неадекватно. Рассмотрим простой пример. Предположим, что мы используем фильтрацию для достаточно крупных блоков адресов IP (например, фильтрация спама из сетей ADSL). Для снижения числа правил зачастую приходиться использовать конструкции, которые блокируют диапазон адресов (префикс), но из этого диапазона нужно исключить несколько более узких диапазонов. Например, вы хотите заблокировать прием почты из блока адресов американских сетей кабельного телевидения 24.0.0.0/8, но по каким-то причинам хотите сохранить возможность приема почты из блока 24.77.77.0/24. В таком случае логично будет создать два набора адресов типа nethash. Ниже приведен пример такой конструкции с использованием синтаксиса ipset

-N NetBlockReturn nethash --hashsize 7776 --probes 2 --resize 50

-A NetBlockReturn 24.77.77.0/24

-N NetBlockSMTP nethash --hashsize 60000 --probes 8 --resize 50

-A NetBlockSMTP 24.0.0.0/8

Первая пара правил будет исключать из списка блокировки сеть 24.77.77.0/24, а вторая – блокировать весь префикс 24.0.0.0/8. В фильтрах iptables создаются два правила, в соответствии с которыми весь почтовый трафик из адресов набора NetBlockSMTP, фильтруется, а трафик из набора NetBlockReturn беспрепятственно проходит через фильтр. Например, это можно сделать так.

-A RejectBySet-SMTP -j LOG --log-prefix "IPTABLES-RejectBySet-SMTP: "

-A RejectBySet-SMTP -j REJECT --reject-with icmp-host-unreachable-A MailProcessing -m set --set HostBlockReturn src -j RETURN

-A MailProcessing -m set --set NetBlockReturn src -j RETURN

-A MailProcessing -m set --set HostBlockSMTP src -j RejectBySet-SMTP

-A MailProcessing -m set --set NetBlockSMTP src -j RejectBySet-SMTP

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

-N NetBlockReturn nethash --hashsize 7776 --probes 2 --resize 50

-N NetBlockSMTP nethash --hashsize 60000 --probes 8 --resize 50

-A NetBlockReturn SmallBlock1

-A NetBlockReturn SmallBlock2

...

-A NetBlockReturn SmallBlockN

-A NetBlockSMTP BigBlock

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

Но автор ipset приготовил нам очередной сюрприз и если вы создадите файл по типу показанного в последнем примере и потом загрузите наборы с помощью команды ipset -R, то результат просмотра списка вас немало удивит. Логично предположить, что в результате загрузки набор из файла, содержащего показанные в примере наборы адресов мы по команде ipset -L NetBlockReturn увидим

SmallBlock1

SmallBlock2

...

а по команде ipset -L NetBlockSMTP

BigBlock

...

Однако на практике все выглядит иначе и набор NetBlockReturn для приведенного выше примера окажется пустым, а набор NetBlockSMTP будет содержать

SmallBlock1

SmallBlock2

...

BigBlock

...

Таким образом, мы вместо того, чтобы принимать почтовый трафик из блоков SmallBlockN, будем фильтровать его наряду с трафиком из BigBlock. Как говорили наши деды: “Вот тебе, бабушка, и Юрьев день.”

Николай Малых

или введите имя

CAPTCHA