среда, января 30, 2008

pf и freebsd 6.2

Обстоятельства диктуют переходить с ipfw на pf. Ну чтобы не попасть в просак решил я для начала поставить его на домашнем сервере.

Самое главное в осмыслении работы любого фаервола это понять принцип его работы. На самом деле все просто. Нужно рассматривать прохождение пакетов через интерфейсы относительно системы на которой установлен фаервол. Я хочу сказать что пакет входящий может может прийти в систему из интернета или из локальной сети (LAN). А исходящий пакет - это пакет в интернет или в LAN. Это очень важно.

В нашем случае требовалось обеспечить следующее.
  • Сетевых интерфейсов 2 (внешний и внутренний), включен nat.
  • С сервера наружу в интернет можно все.
  • Ping можно везде.
  • Из интернета на сервер можно пассивный ftp, ssh.
  • Из LAN и обратно можно все через туннель.
  • Из LAN в интернет можно dns, ssh, pop3, smtp, 1723, gre (остальное через прокси).
  • Необходимо пробросить порт на определенную машину в LAN чтобы работал torrent.
В ядро добавляем опции и компилим новое ядро. Как это сделать смотрите здесь

options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_PRIQ
options ALTQ_NOPCC
device pf
device pflog
device pfsync

Вообще в нашем конкретном случае все опции не нужны, но я думаю прогодятся в будущем. Добавлять опции в ядро не обязательно, но мне так больше нравится.

Далее добавим в /etc/rc.conf следующие строчки

gateway_enable="YES"
pf_enable="YES"
pf_rules="/etc/pf.conf"
pf_flags=""
pflog_enable="YES"
pflog_logfile="/var/log/pflog"
pflog_flag=""

А теперь собственно сам файл /etc/pf.conf с пояснениями.


#int_if - внутренний интерфейс, ext_if - внешний интерфейс
int_if = "rl0"
ext_if = "fxp0"
#comp_rdr_lan на этот комп пробросим порты
comp_rdr_lan = "192.168.2.2"
#порты пробрасываемые внутрь локалки на комп comp_rdr_lan (торент)
comp_rdr_port = "6881, 55555"
#локальная сетка через туннель
lan_work = "192.168.1.0/24"
#Разрешаем из локалки эти порты
tcp_udp_out = "53, 6112"
tcp_out = "22, 25, 110, 1723"
#tcp_services - сервисы на нашем серваке 21 - фтп, 35500:35600 - порты фтп
# для пассивного режима, использую proftpd эти порты указаны в proftpd.conf
# для пассивного режима, порт 113 идент - вроде как используется некоторыми
# сервисами, 22 - ssh
tcp_services = "{ 21, 35500:35600, 113, 22 }"
#icmp_types - какие типы icmp принимать
icmp_types = "echoreq"
# списки приватных сетей, для блокировки их на внешнем интерфейсе
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
#Поведение по умолчанию для правил фильтра, когда срабатывает правило block
# в нашем случае для отброшенных пакетов TCP отсылается TCP RST, для прочих
#ICMP Unreacheble
set block-policy return
#Нормализация входящего трафика
scrub in all
#Натим пакеты из локалки
nat on $ext_if from $int_if:network to any -> ($ext_if)
#Проброска портов в локалку на comp_rdr_lan
rdr pass on $ext_if inet proto { tcp, udp } from any to ($ext_if) \
port { $comp_rdr_port } -> $comp_rdr_lan
# по умолчанию запрещаем все
block all
#разрешаем все через локальный интерфейс
pass quick on lo0 all
#Блокируем приватные сети на внешнем интерфейсе
block drop in quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets
#Разрешаем доступ к нашему серваку снаружи к определенным портам
pass in on $ext_if inet proto tcp from any to $ext_if port $tcp_services \
flags S/SA keep state
#Разрешаем входящие icmp ping
pass in inet proto icmp all icmp-type $icmp_types keep state
#Разрешаем все через туннель
pass on tun0 all
pass on tun1 all
#Разрешить из локалки доступ к внутреннему интерфейсу и к локалке работы
pass in quick on $int_if from $int_if:network to { $int_if, $lan_work } \
keep state
#Разрешить из локалки tcp и udp на tcp_udp_out
pass in quick on $int_if inet proto { tcp, udp } from $int_if:network to any \
port { $tcp_udp_out } keep state
#Разрешить из локалки tcp на tcp_out
pass in quick on $int_if inet proto tcp from $int_if:network to any port \
{ $tcp_out } keep state
#Разрешить из локалки gre
pass in quick on $int_if inet proto gre from $int_if:network to any keep state
#Разрешить в локалку все через внутренний интерфейс
pass out on $int_if from any to $int_if:network keep state
#Разрешить наружу tcp через внешний интерфейс
pass out on $ext_if proto tcp all modulate state flags S/SA
#Разрешить наружу udp, icmp, gre через внешний интерфейс
pass out on $ext_if proto { udp, icmp, gre } all keep state


Ну и как памятка некоторые команды.

pfctl -sn Показать текущие правила NAT.
pfctl -sr Показать текущие правила фильтра.
pfctl -ss Показать текущую таблицу состояний.
pfctl -sa Показать все что можно.

P.S. Конфигурационный файл взят с абсолютно рабочей машины.



Обсудить сообщение можно в форуме admins.arg.su

7 комментариев:

andrey i. mavlyanov комментирует...

у меня два вопроса:

1) что за обстоятельства? чего нет в ipfw что есть в pf?

2) почему если pf то не openbsd?

andrey i. mavlyanov комментирует...
Этот комментарий был удален автором.
Айзятуллен Рамиль комментирует...

Отвечаю
1. Есть несколько внешних каналов. Задача настроить симметричную маршрутизацию для правильного возврата пакетов в канал из которого было инициировано соединение, независимо от настроики default route.
2. Нет проблем, осталось только freebsd снести и openbsd поставить. :)

m0ps комментирует...

спасибо огромное. как-раз искал инфу по настройке PF. Сделал все как написано, вроде все работает, но вот с чем столкнулся:
при тесте порта в uTorrent показывает что порт открыт, но вот соединения устанавливаются как-то не естественно. из ~50 сидов соединяюсь всего с 1-3. такое впечатление что подключаться могут только ко мне, а я не могу.
так же хотелось бы узнать что значит:
Из LAN и обратно можно все через туннель.
эт об VPN?


p.s. вобще огромное спасибо за море инфы, которой я нашел в этом блоге.

Айзятуллен Рамиль комментирует...

1 возможно у вас изнутри запрещено коннектиться наружу, воспользуйтесь tcpdump для диагностики
2 tun0 это туннельный интерфейс
3 обсуждаем статьи здесь http://admins.arg.su

Анонимный комментирует...

реально, такие же проблемы как у m0ps.

с p2p сетями, при канале в 2мбита (200 кб примерно) торрент сначала скачет 170-100 кб,
потом устаканивается и качает примерно 20кб.
изнутри наружу открыто все, есть локальный п2п шареман, такая же проблема скорость оч маленькая. при этом к примеру фтп тянет нормально 200 килобайт.
Поставил пфстат, буду смотреть графики, может есть какие соображения почему так ?

Рамиль комментирует...

Пишите в форум http://admins.arg.su и выложите свой конфиг pf :)