среда, января 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 комментариев:

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

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

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

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

Unknown комментирует...
Этот комментарий был удален автором.
Рамиль комментирует...

Отвечаю
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 :)