[Предыдущая: Таблицы] [Содержание] [Следующая: Преобразование Сетевых Адресов]
Правила фильтрации определяют критерии, которым пакет должен соответствовать и действия, блокировать или пропускать, которые выполняются, когда найдено соответствие. Правила фильтрации оцениваются в последовательном порядке, от первого к последнему. Если пакет соответствует правилу содержащему ключевое слово quick, действия над пакетом будут выполнены сразу не дожидаясь проверки всех фильтрующих правил. Последнее правило будет объявлено "победителем" и будет диктовать какие выполнять действия над пакетом. Если выставить pass all в начале фильтрующих правил, это будет означать, что если пакет не соответствует каким либо другим фильтрующим правилам, то он будет пропущен и выполнимое над ним действие будет pass.
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]
Чтобы создать политику запрета по умолчанию, первые два правила фильтрации должны быть:
block in all
block out all
Будет блокирован весь трафик на всех интерфейсах, во все стороны, куда либо и откуда либо.
Некоторые примеры:
# Пропустить входящий трафик на интерфейс dc0 из локальной сети 192.168.0.0/24,
# на OpenBSD машину с IP адресом 192.168.0.1. Также пропустить возвращающийся
# трафик, выходящий на интерфейс dc0
pass in on dc0 from 192.168.0.0/24 to 192.168.0.1
pass out on dc0 from 192.168.0.1 to 192.168.0.0/24
# Пропустить входящий TCP трафик на интерфейс fxp0 на веб сервер, запущенный
# на OpenBSD машине. Интерфейс под названием fxp0 используется, как адрес
# назначения, поэтому пакеты будут соответствовать только этому правилу если
# они предназначены OpenBSD машине
pass in on fxp0 proto tcp from any to fxp0 port www
Ошибочно:
block in on fxp0 proto tcp from any to any port ssh
pass in all
В этом случае, строка блокировки block будет рассмотрена, но никогда не выполнится, поскольку затем следует правило, которое пропускает всё.
Правильно:
block in quick on fxp0 proto tcp from any to any port ssh
pass in all
Это правило рассматривается не много по другому. Если строка блокировки block подходит, пакет будет блокирован и остальная часть правил будет проигнорирована.
Хранение состояний имеет много преимуществ, включая упрощение правил и улучшенное выполнение фильтрации пакетов. PF способен распознавать пакеты движущиеся в обоих направлениях, это означает, что писать правило пропускающее обратный трафик нет необходимости. И поскольку пакеты соответствующие установленному соединению не проходят проверку правилами, время которое PF тратит на обработку этих пакетов существенно меньше.
Когда правило создаёт стейт(запись в таблице состояний), первый пакет соответствующий правилу создаёт "state" между отправителем и принимающим. Теперь, не только пакеты идущие от отправителя к получателю соответствуют состоянию(state) и не проверяются правилами, но тоже самое происходит и с пакетами идущими от получателя к отправителю.
Начиная с OpenBSD 4.1 все фильтрующие правила автоматически создают state запись когда пакет соответствует правилу. В более ранних версиях OpenBSD в правиле фильтрации должна была быть явно указана опция keep state.
Пример использования OpenBSD 4.1 и более поздних версий:
pass out on fxp0 proto tcp from any to any
Пример использования OpenBSD 4.0 и более ранних версий:
pass out on fxp0 proto tcp from any to any keep state
Эти правила разрешают любой исходящий трафик на интерфейсе fxp0 и также позволяют пройти через брандмауэр ответному трафику. Хранение состояний является полезным свойством и его использование значительно улучшает производительность брандмауэра, поскольку поиск установившихся соединений значительно быстрее чем пропуск пакета через правила фильтрации.
Опция modulate state работает так же, как keep state, за исключением того, что опция применяется только к TCP пакетам. С modulate state начальная последовательность номеров (ISN) исходящих соединений рандомизирована. Это применяется для защиты соединений инициированных некоторыми операционными системами, которые проделывают плохую работу по выбору ISNs. Начиная с OpenBSD 3.5, опция modulate state может быть использована в правилах, которые указывают протоколы отличные от TCP.
Хранение состояния на исходящие TCP, UDP, и ICMP пакеты и включить TCP ISNs:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state
Ещё одно преимущество хранения состояний заключается в том, что соответствующий ICMP трафик будет пропущен через брандмауэр. Например, если TCP соединение проходящее через брандмауэр будет отслеживать по состоянию, то ICMP сообщения относящиеся к этому соединению будут пропущены.
Область действия записи в таблице состояний контролируется глобальной опцией state-policy и через опции if-bound, group-bound, floating. Эти опции имеют тоже значение, как и при использовании опции state-policy. Например:
pass out on fxp0 proto { tcp, udp, icmp } from any \
to any modulate state (if-bound)
Правило предписывает, что пакеты будут соответствовать записи в таблице состояний только в том случае, если они проходят через интерфейс fxp0.
Заметьте, что nat, binat, и rdr правила тоже создают записи в таблице состояний, эти записи хранятся до тех пор, пока фильтрующие правила их пропускают.
Опции указываются внутри круглых скобок и непосредственно после одного или ключевых слов (keep state, modulate state, or synproxy state). Несколько опций указываются через запятые. Начиная с OpenBSD 4.1, опция keep state подразумевается по умолчанию для любых фильтрующих правил. Вопреки этому, когда указывается опция таблиц состояния, одно из ключевых слов должно быть использовано перед опциями.
Пример:
pass in on $ext_if proto tcp to $web_server \
port www keep state \
(max 200, source-track rule, max-src-nodes 100, max-src-states 3)
Это правило задаёт следующее поведение:
Отдельные ограничения могут быть размещены на TCP соединения, которые закончили 3-х этапное рукопожатие.
Обе этих опции автоматически вызывают опцию source-track rule и не совместимы с опцией source-track global.
Поскольку эти опции ограничивают только прошедшие 3х этапное рукопожатие TCP соединения, можно использовать более агрессивные дейcтвия, которые могут быть применены на неприятные вам IP адреса.
Пример:
table <abusive_hosts> persist
block in quick from <abusive_hosts>
pass in on $ext_if proto tcp to $web_server \
port www flags S/SA keep state \
(max-src-conn 100, max-src-conn-rate 15/5, overload <abusive_hosts> flush)
Читается как:
Для проверки TCP флагов в процессе оценки правилами, используется ключевое слово flags:
flags check/mask
flags any
mask сообщает PF просматривать только указанные флаги а check указывает какие флаги должны быть включены в заголовок. Для разрешения любых комбинаций флагов, используйте ключевое слово any.
pass in on fxp0 proto tcp from any to any port ssh flags S/SA
Вышеуказанное правило пропускает TCP трафик с установленным SYN флагом, хотя просматривает только SYN и ACK флаги. Пакет с флагами SYN и ECE будет соответствовать указанному правилу, а пакет с флагами SYN и ACK или просто ACK не будет.
Начиная с OpenBSD 4.1, применяемые флаги для TCP правил это flags S/SA. Скомбинированные с выставляемым по умолчанию keep state правилом фильтрации, эти два правила будут эквивалентны:
pass out on fxp0 proto tcp all flags S/SA keep state
pass out on fxp0 proto tcp all
TCP пакеты с SYN флагом буду подходить под каждое правило. Под каждое правило будут подходить TCP пакеты с установленным флагом SYN, и не подходить с флагом ACK, и каждое правило создаст запись в таблице состояний для подходящего пакета. Используемые по умолчанию флаги могут быть переписаны с помощью опции flags.
В OpenBSD 4.0 и более ранних версиях, применяемых флагов по умолчанию не было. В каждом правиле должны были задаваться флаги и указываться опция keep state.
pass out on fxp0 proto tcp all flags S/SA keep state
Необходимо быть осторожным при использовании флагов - понимайте что вы делаете и зачем и будьте осторожны с советами людей. Некоторые люди советуют создавать записи в таблице "только если установлен SYN флаг и никаких других". Подобное правило может оканчиваться так:
. . . flags S/FSRPAUEW плохая идея!!
Теоретически, стейт создаётся только на начало TCP сессии и сессия должна начинаться с SYN флага, и никакого другого. Проблема в том, что некоторые системы используют ECN флаг в начале сессии и любые системы делающие это будут отвергнуты подобным правилом. Гораздо лучшая политика вообще не указывать никакие флаги и позволить PF установить флаги используемые по умолчанию. Если вам необходимо самому указывать флаги, тогда следующая комбинация должна быть безопасна:
. . . flags S/SAFR
Это практично и безопасно, но нет необходимости проверять флаги FIN и RST, если трафик нормализован с помощью скраба. Процесс нормализации предписывает PF отбрасывать любые входящие пакеты с запрещёнными комбинациями TCP флагов (таких, как SYN и RST) и нормализовать потенциальные двусмысленные комбинации(такие, как SYN и FIN).
Обычно, когда клиент инициирует TCP соединение на сервер, PF пропускает пакеты рукопожатия между двумя конечными точками. PF имеет возможность, проксировать рукопожатие. При проксировании рукопожатия PF самостоятельно завершает рукопожатие с клиентом, инициирует рукопожатие с сервером и затем пропускает пакеты между ними. Преимущество этого процесса состоит в том, что никаких пакетов не посылается серверу, перед тем, как клиент завершит рукопожатие. Это исключает угрозу TCP SYN спуфинг флуда имеющего эффект на сервер, потому что рукопожатие не будет завершено.
Проксирование TCP SYN запускается ключевым слово synproxy state в правилах фильтрации. Пример:
pass in on $ext_if proto tcp from any to $web_server port www \
flags S/SA synproxy state
Здесь соединения на веб сервер будут проксироваться фильтром.
synproxy state также включает функциональность keep state и modulate state.
Проксирование SYN не будет работать если PF запущен на мосту(4).
PF предлагает защиту против спуфинга через ключевое слово antispoof:
antispoof [log] [quick] for interface [af]
Пример:
antispoof for fxp0 inet
Когда правило будет загружено, оно разложится в два правила. Предположим, что интерфейс fxp0 имеет IP адрес 10.0.0.1 и маску подсети 255.255.255.0 ( /24), antispoof правило будет выглядеть так:
block in on ! fxp0 inet from 10.0.0.0/24 to any
block in inet from 10.0.0.1 to any
Эти правила выполняют две вещи:
Обратите внимание: Правила фильтрации, которые используют antispoof правило могут также заблокировать пакеты посылаемые через кольцевой интерфейс локальным адресам. Хорошая практика не фильтровать трафик на кольцевом интерфейсе, но это просто необходимо при использовании антиспуф правил:
set skip on lo0
antispoof for fxp0 inet
Использование antispoof должно быть ограничено на интерфейсы, которым присвоены IP адреса. Использование antispoof на интерфейсе без IP адресов будет выглядеть как:
block drop in on ! fxp0 inet all
block drop in inet all
С такими правилами существует риск заблокировать весь входящий трафик на всех интерфейсах.
Начиная с OpenBSD 4.0 PF предлагает возможности Unicast Reverse Path Forwarding (uRPF). Когда пакет проходит через uRPF проверку, исходные IP адреса пакета проверяются в таблице маршрутизации. Если исходящий интерфейс в таблице маршрутизации такой же, как и интерфейс с которого только что пришёл пакет, тогда uRPF проверка пройдена. Если интерфейсы не совпадают, тогда возможно исходный адрес пакета был подделан(спуфинг атака).
uRPF проверка может выполняться на пакеты, через использование ключевого слова urpf-failed:
block in quick from urpf-failed label uRPF
Обратите внимание,что uRPF проверка имеет смысл только в условиях, когда маршрутизация симметрична.
uRPF предоставляет те же функции, как и при антиспуф правилах.
Пассивное определение Операционной Системы (OSFP) это метод пассивного определения типа операционной системы на удалённом хосте, основанный на некоторых TCP SYN характеристиках этого хоста. Эта информация может быть использована в качестве критерия в фильтрующих правилах.
PF определяет удалённую операционную систему сравнением TCP SYN характеристик с fingerprint файлом, который по умолчанию находится в /etc/pf.os. После включения PF текущий fingerprint список можно просмотреть с помощью команды:
# pfctl -s osfp
В фильтрующих правилах операционные системы могут быть указаны классами, версиями, или подтипами/уровнями. Каждый из этих параметров выводится на вывод через pfctl команду показанную выше. Для указания операционной системы в правиле, используется ключевое слово os:
pass in on $ext_if from any os OpenBSD keep state
block in on $ext_if from any os "Windows 2000"
block in on $ext_if from any os "Linux 2.4 ts"
block in on $ext_if from any os unknown
Указание класса операционной системы, как unknown, позволяет соответствовать пакетам, когда операционная система не известна.
Возьмите на заметку следующее:
pass in quick on fxp0 all allow-opts
ext_if = "fxp0"
int_if = "dc0"
lan_net = "192.168.0.0/24"
# таблица содержащая все IP адреса принадлежащие брандмауэру
table <firewall> const { self }
# не фильтровать трафик на кольцевом интерфейсе
set skip on lo0
# нормализовать входящие пакеты
scrub in all
# установка политики по умолчанию
block all
# активировать спуфинг защиту для всех интерфейсов
block in quick from urpf-failed
# разрешить ssh соединения только из локальной сети доверенного
# компьютера, 192.168.0.15. Используйте "block return" для того чтобы
# высылался TCP флаг RST для закрытия блокированных соединений немедленно.
# используйте "quick" чтобы правило не было перекрыто правилами расположенными
# ниже.
block return in quick on $int_if proto tcp from ! 192.168.0.15 \
to $int_if port ssh
# пропускать весь трафик в и из локальной сети.
# эти правила будут создавать записи в таблице состояний,
# благодаря дефолтной опции "keep state", которая будет применена
# автоматически
pass in on $int_if from $lan_net to any
pass out on $int_if from any to $lan_net
# выпустить tcp, udp и icmp трафик на внешнем (Интернет) интерфейсе.
# tcp соединения буду модулироваться, udp/icmp будут отслеживаться
# по таблице состояний.
pass out on $ext_if proto { tcp udp icmp } all modulate state
# разрешить входящие ssh соединения на внешнем интерфейсе, если они НЕ
# предназначены брандмауэру (например, они предназначены машине внутри
# сети). Логировать инициализационный пакет, так чтобы позже мы смогли
# сказать кто пытался соединиться. используйте tcp syn proxy для проксирования
# соединения. Флаг "S/SA" используемый по умолчанию будет автоматически
# применён к правилу.
pass in log on $ext_if proto tcp from any to ! <firewall> \
port ssh synproxy state
|
[Предыдущая: Таблицы] [Содержание] [Следующая: Преобразование Сетевых Адресов]