Стартовый минигид по пакетному фильтру FreeBSD ipfw


Активация ipfw в FreeBSD

Для начала активируем пакетный фильтр (здесь и далее: «пакетный фильтр» == «файрволл» == стандартный пакетный фильтр FreeBSD ipfw).
Правда, его (строго говоря, как и ЛЮБОЙ файрволл на ЛЮБОЙ платформе) ПЕРЕД использованием НЕОБХОДИМО адаптировать к наличным условиям.
ipfw помимо фильтрации пакетов может быть использован как минимум для управления пропускной способностью канала. Эту возможность в базовом обзоре я не рассматриваю.

В /etc/rc.conf добавляется следующий блок:

#
#### Basic network and firewall/security options: ###
# Set to YES to enable firewall functionality
firewall_enable="YES"
# Which script to run to set up the firewall
firewall_script="/etc/rc.firewall"
# Firewall type (see /etc/rc.firewall)
firewall_type="/etc/ipfw.rules"
# Set to YES to suppress rule display
firewall_quiet="NO"
# Set to YES to enable events logging
firewall_logging="YES"
# Flags passed to ipfw when type is a file
firewall_flags=""

Значение по умолчанию (для выбранного типа) поведения файрволла (правило под номером 65535), зашитое в ядро, может принимать либо разрешать, либо запрещать всем и всё (можно как рулить параметрами при сборке ядра, так и опциями в /etc/rc.conf).

Зашитое в GENERIC по умолчанию значение можно посмотреть (причём вовсе не обязательно при запущенном файрволле), например, командой:

# ipfw list

Выглядит это правило следующим образом:

65535 deny ip from any to any

Типы файрволла

Файрволл на базе ipfw может быть следующих типов:


open — пропускать весь трафик.
client — защищать только эту машину.
simple — защищать всю сеть.
closed — полностью отключить IP-трафик за исключением интерфейса loopback.
UNKNOWN — отключение загрузки правил файрволла.
имя_файла — абсолютный путь к файлу, содержащему правила.

В процитированном примере я уже заменил значение по умолчанию UNKNOWN на единственное удовлетворяющее меня CUSTOM (оно же имя_файла или путь к файлу, содержащему список правил файрволла).

Логика работы файрволла: получив пакет он, проверяет список правил на соответствие пакету; найдя первое правило, соответствующее полученному пакету, пакет обрабатывается в соответствии с данным правилом; и так далее для всех последующих пакетов.

Базовый набор правил, как уже было отмечено выше, записан в файле, который в моём случае именуется /etc/ipfw.rules.

Правила ipfw

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

Формат файла с правилами ipfw:

00100 allow all from any to any via lo0

Пояснения по столбцам:

Номер правила.
Выполняемое действие. Принимает значение allow (синонимом является pass) или deny с необязательной опцией log, указывающей на необходимость записи отчёта в журнал /var/log/security.
Протокол, на который распространяется правило. Ходовые варианты: icmp (Internet Control Message Protocol, иначе говоря — пинги), udp, tcp, ip (синонимом которого является all).
«Откуда?»: from $ADRESS $PORT. Обязательным является указание только первого параметра, допускается использование ключевого слова all. Пропуск любого из двух последующих значений означает, что правило распространяется на все возможные значения. Необязательный параметр адресации — порт. Допускается указание нескольких значений. Для диапазона — через дефис, для простого списка — разделителем значений является запятая.
«Куда?» Аналогичен предыдущему.
Тип трафика (входящий или исходящий). Фактически обретает смысл только при использовании сервера в качестве шлюза и активном использовании в правилах параметра адресации any. Иначе — фактически дублирует адресную часть.
Сетевой интерфейс.
Тип пакетов. За подробностями посылаю к странице руководства. Желающие ознакомиться поподробнее могут почитать описание стека протоколов TCP/IP. Я же отмечу только две группы: setup — TCP-пакеты, используемые при установлении соединения, и established — TCP-пакеты, используемые при передаче данных по уже установленному соединению. Аналогично уже описанному: если параметр присутствует, правило распространяется только на соответствующие указанному признаку пакеты, иначе — на все возможные значения этого признака.
И в случае использование динамической конфигурации файрволла в девятом столбце может указываться параметр keep-state, задающий необходимость пропустить поступающие в ответ на запрос пакеты.

Разделителем параметров в файле является пробел. «#» традиционно является символом комментария.

Пример файла с правилами для ipfw

В качестве примера для построения желаемой рекомендации очень неплохо почитать скрипт примера в Handbook, используя информацию о реальной конфигурации сети (и /etc/services) в качестве дополнительного справочника.

Минимальный, балансирующий на грани достаточности пример приведу и я:

# Немалая часть приложений под *nix
# использует сетевой интерфейс loopback,
# фильтровать трафик через который
# в нулевом приближении — смысла никакого.
add 100 allow all from any to any via lo0
# Пинги тоже разрешаем — я добрый. Пока.
add 300 allow icmp from any to any
# И передачу почты разрешаем.
add 500 allow tcp from any to any 25 setup
# Запрещаем broadcast.
add 700 deny all from any to $MYNET.255 in
add 703 deny ip from any to 255.255.255.255 in
#
# Правило-метка, означающее переход
# к динамической части блока правил.
add 900 check-state
# Разрешается передавать пакеты по уже
# установленным на момент запуска файрволла
# соединениям.
add 920 allow tcp from any to any established
# Разрешаю устанавливать соединения
# данным сервером со всеми.
add 2100 allow all from $MYNET.$MYHOST to any setup keep-state
# Разрешаю устанавливать соединения
# с сервером всем компьютерам своей сети
add 2200 allow all from $MYNET.0/24 to $MYNET.$MYHOST setup keep-state
# Всё остальное запрещаю. Информацию
# о запретах файрволла по доступу на типовые
# порты пишу в лог /var/log/security, а остальное
# сбрасываю тихо.
add 60000 deny log all from any to any 20,21,22,23,53,80,110,137,138,139,443,563,8080,8888
add 60010 deny all from any to any

Жёстко определённое правило по умолчанию в такой конфигурации работать не должно.

Запуск ipfw и работа с ним

Теперь файрволл можно запускать:
# /etc/rc.d/ipfw start

Просмотр статистики применения правил осуществляется командой:
# /sbin/ipfw show

Формат вывода — следующий:

Номер правила Число пакетов Байты Правило
00100 0 0 allow all from any to any via lo0

(Число пакетов (байт) == число пакетов, к которым было применено данное правило.)

Динамическое (не сохраняемое в файле) добавление правил осуществляется следующим образом:

# /sbin/ipfw -q add 4000 deny log icmp from 194.186.213.105 to 194.186.213.118

Вывод списка правил в формате конфигурационного файла осуществляется командой:

# /sbin/ipfw list

Посвящается fly4life, или В чём глубокий смысл журнала /var/log/security

Часто в процессе поиска причин неработоспособности сетевого приложения разработчики рекомендуют убедиться в том, что оной причиной является не конфигурация файрволла. При этом отдельные особо некомпетентные и неблагонадёжные разработчики рекомендуют попросту отключить файрволл.

Правильным же путём является использование параметра log и анализ журнала /var/log/security.

Если разработчики не потрудились предоставить внятного описания принципов работы, то не остаётся ничего кроме как в последнее правило прописать параметр log и шерстить весь журнал. Иначе — в правиле, например, с номером 60004 придется прописать запрет на пропуск пакетов приложения с логированием: если пакеты пропускаются одним из ранее прописанных правил, они и так пройдут; если же они режутся по умолчанию и тихо, то это правило засветит фильтруемые файрволлом пакеты в /var/log/security.

Обновлено: 12.03.2015