Это очень удобный и пакетный фильтр пришёл во FreeBSD из OpenBSD. Синтаксис здесь позволяет разного рода вольности, то есть части правил можно опускать. В статье будет показан простой пример правил для шлюза, в котором разрешены только определённые порты, так сказать самые необходимые.
Тестовый стенд: FreeBSD 8.1
1) Подгружаем модули для работы с pf.
Для начала нам понадобится подгрузить сам модуль pf.ko:
#kldload pf
Если нужно логгирование, то заодно и модуль pflog:
#kldload pflog
Что бы после ребута не подгружать их заново, добавим их в /etc/rc.conf:
pf_enable="YES"
pf_rules="/etc/pf.rules"
pflog_enable="YES"
Здесь мы указали так же путь к файле с правилами /etc/pf.rules.
2) Пишем правила.
Введём макросы для наших сетевых интерфейсов (внутренний и внешний):
ext_if="em0"
int_if="em1"
Теперь добавим нормализацию трафика:
scrub in all
Правило трансляции (NAT):
nat on $ext_if from $int_if:network to any -> $ext_if
Блокируем всё (если что-то нужно разрешить, мы потом разрешим)
block all
Разрешаем трафик по loopback’y
pass on lo0
Разрешаем из локалки доступ в инет только на указанные порты:
pass in on $int_if proto tcp from $int_if:network to any port {22,80,110,143,445}
pass out on $ext_if proto tcp from $ext_if to any port {22,80,110,143,445}
Разрешим использовать DNS из инета. Если только локальные, тогда вместо any поставить нужные адреса локальных серверов
pass in on $int_if proto udp from $int_if:network to any port 53
pass out on $ext_if proto udp from $ext_if to any port 53
Разрешаем пинг везде
pass on $ext_if proto icmp from any to any
pass on $int_if proto icmp from any to any
Примечание:
Во FreeBSD Начиная с 7.0 и в OpenBSD с 4.1 ко всем правилам по умолчанию используется опция keep-state. Поэтому, если не нужно, что бы файервол создавал ответное динамическое правило, добавляем к правилу no state.
3) Логгирование.
Часто возникают ситуации, когда вроде бы всё открыто, но не работает. Что бы понять, какие порты нужно открыть, применяют логгирование правил.
Для логгирования правила нужно выполнение 2 условий:
– наличие интерфейса pflog0
– наличие ключевого слова log в правиле
Первый пункт достигается либо подгрузкой модуля pflog либо пересборкой ядра с опцией options pflog. Наличие интерфейса pflog0 узнать можно через команду ifconfig:
#ifconfig | grep pflog0
pflog0: flags=141 metric 0 mtu 33200
Для логгирование правил добавляем в правило ключевое слово log:
block log all
Логи можно смотреть только в режиме реального времени и делать можно с помощью команды tcpdump:
#tcpdump -i pflog -v -t
Собственно можно использовать все ключи команды tcpdump для фильтрации.