впечатления от работы с ipfilter под GNU/Linux

Большую часть десятилетия пользователи BSD, OpenBSD, NetBSD, Solaris и IRIX для построения межсетевых экранов и защиты индивидуальных систем от сетевых атак использовали программу ipfilter, написанную Дэрреном Ридом (Darren Reed). Теперь, после релиза ipfilter 4.1.1, GNU/Linux появилась в списке поддерживаемых платформ.
Несмотря на то, что GNU/Linux уже на протяжении определенного времени располагает собственными встроенными технологиями фильтрации пакетов (iptables и ipchains), возможность использования ipfilter под GNU/Linux может заинтересовать администраторов, работающих в неоднородной среде с большим количеством систем и желающих привести технологию фильтрации пакетов к единому стандарту. Повсеместное использование ipfilter определенно будет более простым решением, чем применение iptables на системах с GNU/Linux, ipfw под FreeBSD, pf для OpenBSD и ipfilter для систем Solaris.
Имея многолетний опыт использования ipfilter в частной и профессиональной деятельности, я был весьма рад возможности получить в свое распоряжение код последней версии ipfilter и посмотреть, чем конкретно он может быть полезен системе с установленной GNU/Linux. К сожалению, это было легче сказать, чем сделать.
Код сам по себе легко можно получить на веб-сайте ipfilter.
Мои главные претензии к ipfilter относятся к разбросанной документации и наличию временного лага между выходом последнего релиза и появлением соответствующей документации. Например, INSTALL-файл содержит следующий текст: «Linux is no longer supported». Даже если вы можете примириться с недостатками документации, далее вас будут ожидать некоторые более интересные вещи.
Поскольку FreeBSD 4.x изначально содержит ipfilter, его компилирование из исходников – это не то, к чему привыкли многие пользователи этой системы. Если они используют stable-ветвь, они периодически получают обновления к ipfilter, когда обновляют свои операционные системы.
Те же, кто желает обновиться до последней версии ipfilter между обновлениями операционной системы, может выбрать самостоятельную загрузку и установку ipfilter из исходных кодов. Данный процесс обычно выглядит примерно так: распаковка кода, переход в каталог с исходным кодом, легкая доработка изделия напильником путем правки по различным причинам некоторых файлов, make freebsd4 и make install-bsd. Само собой, это порядком утрированно - так сказать, высокоуровневый обзор процесса, но смысл вам должен быть ясен.
Компилирование ipfilter под GNU/Linux – пока непростая задача. Рид компилировал и тестировал ipfilter под Red Hat 9, поэтому вам, скорее всего проще будет тестировать программу именно на этой платформе. Я использую SuSe 8.2 Pro, и я испытал определенные сложности при компиляции и установке программы.
Вне зависимости от используемой вами платформы, вам придется править высокоуровневый Makefile в дистрибутиве ipfilter. Первое, что необходимо сделать – это проверить переменную LINUXKERNEL. Скорее всего, вам потребуется изменить значение этой переменной и указать местоположение исходного кода ядра вашей системы. Вам также может понадобится добавить флаг -O2 в конец строки CFLAGS, что должно определенным образом оптимизировать код – это может быть полезно, если вы планируете серьезно загрузить ваш ipfilter работой, прокачивая через него большие объемы данных. Для тестовых задач я решил не проводить оптимизацию.
Продолжая работу с Makefile, вы можете активизировать в программе так называемый «режим наивысшей производительности» (state top capability). Это позволит вам просматривать встроенные таблицы состояния в формате, подобном используемому в команде GNU/Linux top(1). Это прекрасная возможность, которая позволяет просматривать таблицы состояния практически в режиме реального времени. Для включения этой возможности вам надо проинсталлировать ncurses. Раскомментируйте строки STATETOP_CFLAGS, STATETOP_INC, STATETOP_LIB и внесите изменения, соответствующие вашей системе.
Наконец, вам необходимо решить: желаете ли вы, чтобы программа по умолчанию пропускала или блокировала проходящие через нее пакеты. Изначально пакет сконфигурирован на пропуск пакетов. Для изменения этой политики (чтобы пакеты по умолчанию блокировались), измените строку POLICY на:

POLICY=-DIPF_DEFAULT_PASS=FR_BLOCK

После того, как вы внесете все правки в Makefile, следует изменить еще два файла. Ipfilter - это фильтр пакетов с контекстной проверкой. Это значит, что вся контекстная информация должна где-то храниться. Ipfilter использует для хранения этой информации таблицу состояния (state table).
Максимальный размер таблицы состояния устанавливается при компиляции в файле ip_state.h. По умолчанию таблица состояния имеет размер, подходящий для использования в домашних условиях или в небольшой локальной сети. Для защиты более чем 20-30 хостов с помощью контекстных правил вам потребуется увеличить размер таблицы. Это делается для того, чтобы избежать остановки выполнения программы после полного заполнения таблицы. Если вы планируете построить межсетевой экран с помощью ipfilter для защиты сотен и сотен хостов, вам также надо изменить файл ip_hat.h для увеличения размера таблицы NAT. Поскольку я тестировал ipfilter с использованием небольшого количества компьютеров, я решил оставить в обоих файлах значения по умолчанию.
Вкратце описанный здесь процесс сборки/инсталляции ipfilter предполагает наличие файла ipfboot, находящегося в подкаталоге Linux/. Так или иначе, этот файл не был включен в дистрибутив, и я написал его самостоятельно. Файл ipfboot – это простой chkconfig-совместимый shell-скрипт, который запускает и останавливает сервис. Если вы загрузили готовый файл или изготовили собственный, не забудьте поместить его в подкаталог Linux/, где находится распакованный код, иначе компиляция закончится неудачей. Затем мне некоторое время пришлось править код и build-файлы.
Когда все это будет сделано, вы готовы к компиляции программы. Используйте следующую последовательность команд:

make linux
make install-linux


Вы можете получить предупреждение об использовании GNU-версии make. Не обращайте на него внимания и продолжайте. Если все прошло, как планировалось, вы сможете отыскать в своей базе данных RPM установленный пакет ipfilter.
Итак, вы получили установленную программу: что дальше? Дальше потребуется написать некоторый набор правил. Большинство правил ipfilter выглядит примерно так:

pass in quick on eth0 proto tcp from any to 172.19.3.3/32 port = 80 flags S/SA keep state keep frags
block in quick on eth0 proto tcp/udp from any to any port = 137
pass out on eth0 proto tcp/udp from 172.19.3.3/32 to any keep state keep frags
pass out quick on eth0 proto icmp from 172.19.3.3/32 to any keep state keep frags

Приведенные правила весьма бесхитростны. Первая строка разрешает входящий TCP-трафик к IP-адресу 172.19.3.3, порт 80 на адаптере Ethernet eth0. Оно отслеживает состояние соединения (keep state), но создает запись состояния только в том случае, если в пакете установлены корректные флаги S/SA. Мы также отслеживаем фрагменты (keep frags) пакетов, которые из-за своего размера были разбиты на части по пути к нам. Мы теперь отслеживаем состояние соединения, поэтому, когда пакеты идут к конечному пользователю (или серверу) или от него, эти пакеты не проходят проверку правилами, если они соответствуют ожиданиям таблицы состояния. Проверка пакетов прекращается, как видно выше из примера, как только они совпадут с правилом.
Вторая строка блокирует входящий TCP/UDP-трафик, приходящий откуда угодно, порт 137. Это может быть полезным для защиты Windows-систем или просто для предотвращения засорения ваших логов большим количеством NBT-пакетов.
Третья строка разрешает исходящий TCP/UDP-трафик от 172.19.3.3. В этом случае состояние также сохраняется, что означает, что исходные пакеты определены как часть этого состояния соединения, не проходящего через набор правил.
Четвертая строка разрешает исходящий ICMP-трафик. Некоторые ребята забывают, что ICMP – это протокол, отличный от TCP и UDP и что они должны явно разрешить его прохождение через межсетевой экран, если они желают его использовать.
Очевидно то, что приведенный набор правил не является полным или наилучшим. Некоторые онлайновые ресурсы разбирают процесс составления правил куда более подробно, чем я собираюсь сделать здесь. Дабы избежать ненужного дублирования великолепных работ, я попрошу вас обратиться к первоисточникам, если вы заинтересованы в составлении собственного набора правил ipfilter.
Используя свой опыт работы с ipfilter, я решил создать небольшой специальный набор правил для того, чтобы немного протестировать работу пакета. К сожалению, через несколько секунд после запуска ядро моей системы выдало ошибку. Это мне не понравилось, и я попробовал еще раз, на этот раз с runlevel 3. Еще один сбой ядра.
Несколько новых экспериментов и новых перезагрузок выявили, что использование возможностей keep state режима ipfilter гарантирует появление неприятностей с ядром. Поэтому я переписал свой тестовый набор правил, удалив из него все контекстные правила. Теперь ipfilter должен был действовать как простой фильтр пакетов. Это решило проблему, и система опять стала устойчивой.
Некоторые проведенные тесты показали, что действующий ipfilter оказывает незначительное воздействие на скорость работы сети. Копирование файла размером около 450 Mb с помощью scp практически не повлияло на скорость сети, но вызвало некоторое увеличение загрузки CPU. Ipfilter не оказал никакого влияния на работу NFS как в случае входящих сетевых запросов, так и Web- и DNS-сервисов.
Теперь, располагая стабильной системой, я был готов опробовать работу ipfilter с NAT. Я поставил систему с работающей FreeBSD за фаерволл, построенный на основе ipfilter для GNU/Linux и настроил правильную адресацию. Затем я написал свои правила для NAT.
Большинство правил ipfilter для NAT обычно сохраняются в /etc/ipnat.conf. Мой тестовый набор правил выглядел примерно так:

map eth0 192.168.1.0/24 -> 172.19.3.3/32 portmap tcp/udp auto
map eth0 192.168.1.0/24 -> 172.19.3.3/32


Директива map – это то, что устанавливает соединение в пуле NAT. В этом случае я даю ipfilter команду переписывать все соединения от сети 192.168.1.0/24 таким образом, что они как будто бы исходят от 172.19.3.3, если пакеты уходят через eth0. Директива portmap tcp/udp говорит ipfilter, что он может переписать значение исходящего порта на какое-либо выбранное ipfilter значение (auto) для TCP- и UDP- пакетов.
Директива, не включающая опцию преобразования номеров портов, работает со всеми протоколами, не являющимися TCP или UDP. Эти протоколы будут включать ICMP, GRE и подобные.
Я испытываю определенную слабость к движку ipfilter для NAT, поскольку в прошлом использовал его для выполнения некоторых нестандартных манипуляций, связанных с перенаправлением или переписыванием пакетов.
Мне очень хотелось иметь возможность добавить GNU/Linux к тем платформам, на которых я мог бы делать вещи-которые-не-рекомендуется-делать-с-NAT ;). Написав свой небольшой тестовый набор правил, а также отконфигурировав и настроив несколько систем, я загрузил набор правил для NAT и запустил несколько тестов.
К сожалению, функционирование NAT, похоже, было нарушено ipfilter, действующим под GNU/Linux. Несмотря на то, что сама по себе система межсетевого экрана могла получить доступ к различным сетевым ресурсам, любые запросы, которые проходили через систему NAT были проигнорированы целевыми серверами. Например, если я выполнял на GNU/Linux-фаерволле команду

host www.gnu.org

я получал IP-адрес веб-сервера GNU. Точно такая же команда, но выполненная на системе, находящейся за GNU/Linux-фаерволлом, приводила к DNS-таймауту.
Используя tcpdump можно было увидеть, что пакеты покидают GNU/Linux-фаерволл и достигают различных целевых серверов. Однако не было видно, чтобы какой-либо ответ поступал с целевых серверов или достигал GNU/Linux-фаерволла. Это привело меня к убеждению, что использование механизма работы с NAT в ipfilter для GNU/Linux приводит к незначительному искажению пакетов. Испорченные пакеты затем, вероятно, отбрасываются целевыми серверами.
Подведем итог: если вы не можете использовать ipfilter как средство контекстной проверки пакетов и не можете работать с NAT, то к чему же вы можете его приспособить? Допустим, вы можете запускать программу под ядром 2.4.20. Это похоже на анекдот, однако я наглядно убедился, что запуск ipfilter под 2.4.25 делает платформу даже менее стабильной, чем такая операция под 2.4.20. Я не испытывал программу совместно с ядром 2.6 и не имею сведений о таких попытках других людей. Тем не менее, испытав трудности с работой программы под 2.4.20, я бы не поставил на то, что ядро версии 2.6 должно стать ответом на проблемы со стабильностью.
Если говорить о текущем моменте, то люди, тестирующие ipfilter под GNU/Linux должны быть теми, кто ищет единый фаерволл, который может быть развернут на значительном количестве UNIX или UNIX-подобных платформ. Когда программа пройдет некоторую доводку, эти ребята могут приступить к стандартизации их программного обеспечения для построения фаерволлов.
Те же, кому необходим готовый к работе с Internet межсетевой экран для GNU/Linux, лучше присмотреться к другим программным пакетам до той поры, когда ipfilter еще немного дозреет для использования на этой платформе. Возможности ipfilter для GNU/Linux пока более чем скромны, в силу чего я не могу рекомендовать его для использования в реальной рабочей обстановке.
Как бы то ни было, не теряйте ipfilter из вида. Программа уверенно развивается и когда пакет будет немного лучше работать с GNU/Linux, он имеет все шансы стать серьезной альтернативой iptables и другим межсетевым экранам, доступным для GNU/Linux.

David Bogen, перевод Алексея Кутовенко.
обсуждение статьи



Сетевые решения. Статья была опубликована в номере 09 за 2004 год в рубрике software

©1999-2024 Сетевые решения