Введение
В Рунете есть множество статей о настройке FreeBSD и PF, но все они разрозненны и несистематичны. А за любыми более-менее интересными вещами, такими, как маршрутизация средствами файрвола (Policy Based Routing), приходится читать оригинальную документацию, например, OpenBSD PF FAQ. Однако, есть отличия в синтаксисе команд для FreeBSD и OpenBSD. В этом цикле статей мы пробуем систематизировать и разобрать возможности PF от простого к сложному. Наверняка, эта вводная статья будет похожа на все остальные статьи о Packet Filter. Поэтому тем, кто уже знаком с базовыми возможностями, будет не интересно. Однако, без вступления не обойтись, а мясо будет в следующих статьях.
PF — Packet Filter — это межсетевой экран, изначально созданный в рамках проекта OpenBSD. В 2003 году был портирован во FreeBSD. В 2004 году был интегрирован в основную систему. Основные возможности:
- Фильтрация на основе адресов, портов, протоколов, интерфейсов
- NAT — Source NAT, подмена адреса отправителя. Destination nat, подмена адреса получателя, проброс порта
- Scrub — нормализация сетевого трафика. Помогает от некоторых видов dos атак, основанных на формировании специально подготовленных пакетов
- SYN-proxy — Защита от SYN-flood атак
- Балансировка соединений
- Отказоустойчивость — pfcync позволяет синхронизировать состояние файрволов на нескольних хостах, что, в сочетании с протоколом CARP, позволяет создать отказоустойчивый файрвол, который продолжит обрабатывать соединения после падения активной ноды
- Прозрачный файрвол (Без собственного IP-адреса, включая фильтр 2 уровня)
- Макросы — аналог переменных
- Таблицы — динамически изменяемые без перезагрузки конфигурации списки IP адресов
- Метки — позволяет метить пакеты, если простой фильтрации недостаточно
- Якоря (anchors) — наборы правил, похожи на таблицы IPTables в Linux
- Сбор статистики и вывод графиков с помощью утилиты pfstat
- Автоматическая оптимизация правил при загрузке
Основное отличие от того же IPTables — непривычная схема работы. Обработка пакета не заканчивается после первого совпадения с правилом. То есть, если вы поставили первым правилом «запретить всё», то пакет не будет отброшен, а пометится как запрещенный, пойдёт дальше по правилам, и, если его не разрешит никакое правило, то будет отброшен. Это важно понимать и использовать. Однако, если нужно, это поведение можно отменить параметром quick в правиле.
Управление и полезные команды
Для включения PF достаточно в файле «/etc/rc.conf» указать опции:
pf_enable="YES" # включает pf и загружает модуль
pf_flags="" # дополнительные флаги pfctl
pf_rules="/etc/pf.conf" # файл конфигурации
pflog_enable="YES" # запуск pflog
pflog_flags="" # флаги pflog
pflog_logfile="/var/log/pflog" # файл лога
Основные команды управления файрволом:
pfctl - # Включить файрвол
pfctl -d # Выключить файрвол
pfctl -nf # Проверить синтаксис файла
pfctl -f # Перечитать правила из файла
pfctl -Rf # Перечитать правила фильтрации из файла
pfctl -Nf # Перечитать правила NAT из файла
pfctl -sa # Просмотр всех состояний
pfctl -s # Просмотр правил фильтрации
pfctl -sn # Просмотр правил NAT
pfctl -s Anchors -v # Просмотр дерева якорей
pfctl -ss # Просмотр текущих соединений
Структура файла конфигурации и базовые настройки
Файл конфигурации состоит из разделов:
- Макросы
- Таблицы
- Опции
- Правила нормализации трафика (scrub)
- Очереди, приоритезация и контроль скорости
- NAT трансляции адресов
- Фильтрация пакетов
Правила в общем случае имеют следующий синтаксис:
action [direction] [log] [quick] [on interface] [af] [proto protocol]
[from src_addr [port src_port]] [to dst_addr [port dst_port]]
[flags tcp_flags] [state]
action — что следует сделать с пакетом
direction — in out, направление
log — попадёт ли пакет в pflog
quick — если пакет попал под это правило, то дальнейшей обработки не будет. Это правило будет последним для пакета
interface — название сетевого интерфейса
af — address family, inet или inet6, IPv4 или IPv6 соответственно
protocol — протокол 4 уровня, к примеру: tcp, udp, icmp
scr_addr, dst_addr — адреса источника и назначения
src_port, dst_port — порты
tcp_flags — флаги tcp
state — опции сохранения состояния. Например, keep state будет означать, что соединение сохранится в таблице состояний, и ответные пакеты могут проходить. Поведение по умолчанию.
Возьмем простейший веб-сервер в вакууме. Необходимо открыть входящие соединения по портам tcp 22, 80, 443 (ssh, http, https). Также нужно открыть исходящие соединения по портам tcp 22, 80, 443 (ssh, http, https) и udp 53, 123 (dns и ntp). Всё остальное запретить.
# ee pf.conf
#macros section
permit_tcp_ports="22,80,443"
permit_udp_ports="53,123"
#table section
# в данный момент пустая
#options section
set block-policy return # разрываем соединения с ответом, а не просто дропаем пакеты
set skip on lo0 # пропускаем проверку на локальной петле, там фильтрация не нужна
#scrub section
scrub in all # нормализация всего входящего трафика
#Queueing section
# в данный момент пустая
#nat section
# пустая, у нас нечего транслировать
#filtering section
block all # запрет всего по умолчанию, помним, что это не означает окончание обработки пакета.
pass in proto tcp to port { $permit_tcp_ports } # разрешаем входящие соединения
pass out proto tcp to port { $permit_tcp_ports } # разрешаем исходящие соединения tcp
pass out proto udp to port { $permit_udp_ports } # разрешаем исходящие соединения udp
pass out inet proto icmp # разрешаем исходящий icmp
Затем вводим команду проверки синтаксиса:
pfctl -nf pf.conf
Если сообщений об ошибках нет, вводим команду применения правил:
pfctl -f pf.conf
Для проверки посмотрим правила фильтрации:
# pfctl -sr
scrub in all fragment reassemble
block return all
pass out proto tcp from any to any port = ssh flags S/SA keep state
pass out proto tcp from any to any port = http flags S/SA keep state
pass out proto tcp from any to any port = https flags S/SA keep state
pass out proto udp from any to any port = domain keep state
pass out proto udp from any to any port = ntp keep state
pass out inet proto icmp all keep state
pass in proto tcp from any to any port = ssh flags S/SA keep state
pass in proto tcp from any to any port = http flags S/SA keep state
pass in proto tcp from any to any port = https flags S/SA keep state
Как видно, макросы развернулись в отдельные правила по каждому порту, порядок изменен автоматически. В остальном всё так, как нужно.
Итог
Мы разобрались, что такое Packet Filter, узнали его основные возможности. Разобрались в структуре конфигурации PF и её основных секциях. Создали самую простую конфигурацию, которая, однако вполне функциональна, включает макросы, нормализацию пакетов и фильтрацию входящих и исходящих пакетов. В следующей статье разберем более подробно правила фильтрации, управление состояниями и флаги.
Наше решение, Интернет Контроль Сервер – это шлюз безопасности, построенный на базе FreeBSD. Данная система была выбрана ввиду своей стабильности, скорости сетевого стэка, встроенной в ядро поддержки ZFS и отсутствия заморочек с лицензиями. Кроме того, работа с FreeBSD достаточно приятна, хоть и не во всем проста. Но мы будем рады делиться с вами этим опытом!
ChePeter
Пакет на localhost после этой команды
set skip on lo0
пропускается или обрабатывается дальше?
M14xa Автор
Эта опция указывает PF полностью пропускать трафик на интерфейсе lo0. Пакет просто уйдет в ядро без проверки.