Понедельник, 04.08.2025, 09:47

Блог Владимира Степанова

Реклама
Статистика
Яндекс.Метрика
Онлайн всего: 1
Гостей: 1
Пользователей: 0
Меню
Категории раздела
FreeBSD OpenBSD [1]
Установка [4]
Настройка [21]
WWW [1]
Мелочи [1]
Файловая система [0]
Вход на сайт
Реклама
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Главная » Статьи » Unix системы » Настройка

    Настройка Policy Based Routing с помощью pf

    Настройка Policy Based Routing с помощью pf


    Возникла необходимость настроить роутер, для маршрутизации пакетов между сетями. Так как на cisco начальство раскошеливаться не захотело(это намек =)), пришлось
    ставить на компутер ОС, понятное дело, что я поставил чертенка, и настраивать должным образом файрвол. Выбирать firewall долго не пришлось,
    вспомнив, как я мучился с ipfw и natd я тут же остановил свой выбор на packet filter(pf).
    pf во FreeBSD, как и ipfw нужно подключать отдельно. Во FreeBSD версии < 5.x pf нужно было ставить из портов(/usr/ports/security/pf), но начиная
    с 5-ой ветки начать работу с pf можно либо перекомпилировав ядро, либо подгрузив модуль pf.ko. Я пошел по первому пути, поэтому для начала давайте
    соберем собственное ядрышко, добавив туда следующие опции:

    device pf
    device pflog
    device pfsync
    options ALTQ

    После этого можно компилировать ядро и устанавливать его:


    shield@/usr/src/sys/i386/conf> config kernel-pf
    Kernel build directory is ../compile/kernel-pf
    Don't forget to do ``make cleandepend; make depend''
    shield@/usr/src/sys/i386/conf> cd ../compile/kernel-pf
    shield@/usr/src/sys/i386/compile/kernel-pf> make cleandepend && \
    ? make depend && make && make install && reboot

    После перезагрузки у вас в системе будет работающий firewall — pf. Теперь можно переходить непосредственно к настройке firewall'а.
    Хотя нет, я погорячился... Сначала нужно... нет, просто НЕОБХОДИМО нарисовать схемку сети и продумать, какие пакеты будут ходить, кому
    и куда можно. Короче просто продумать основные моменты. После этого можно приступать к написанию конфигурационного файла файрвола.
    Конфиг pf находится по адресу: /etc/pf.conf. Его и будем мучать. Перед тем, как я опубликую свой конфигурационный файл, я хочу рассказать Вам о
    структуре моей сети. Это необходимо, для понимания правил файрвола. Итак, все нижеописанное, Вы можете увидеть на данной схемке.
    Роутер, на котором мы буде настраивать pf именуется shield, у него имеется 6 сетевых интерфейсов: 5 физических и один — VPN:


    shield@/> ifconfig -a
    dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=8<VLAN_MTU>
    inet 192.168.98.2 netmask 0xffffff00 broadcast 192.168.98.255
    ether 00:05:1c:1e:6f:9e
    media: Ethernet autoselect (100baseTX <full-duplex>)
    status: active
    dc1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=8<VLAN_MTU>
    inet 172.16.0.30 netmask 0xffffff00 broadcast 172.16.0.255
    ether 00:80:ad:0b:c7:9c
    media: Ethernet autoselect (100baseTX <full-duplex>)
    status: active
    dc2: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=8<VLAN_MTU>
    inet 192.168.3.2 netmask 0xffffff00 broadcast 192.168.3.255
    ether 00:05:1c:1e:5a:a0
    media: Ethernet autoselect (100baseTX <full-duplex>)
    status: active
    fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=8<VLAN_MTU>
    inet 192.168.1.254 netmask 0xffffff00 broadcast 192.168.1.255
    ether 00:00:4b:51:07:84
    media: Ethernet autoselect (100baseTX <full-duplex>)
    status: active
    fxp1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=b<RXCSUM,TXCSUM,VLAN_MTU>
    inet 10.10.20.1 netmask 0xffffff00 broadcast 10.10.20.255
    ether 00:02:b3:e8:21:ee
    media: Ethernet autoselect (100baseTX <full-duplex>)
    status: active
    pfsync0: flags=0<> mtu 2020
    pflog0: flags=100<PROMISC> mtu 33208
    lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    inet 127.0.0.1 netmask 0xff000000
    ng0: flags=88d1<UP,POINTOPOINT,RUNNING,NOARP,SIMPLEX,MULTICAST> mtu 1440
    inet 1.1.1.1 --> 172.17.0.1 netmask 0xffffffff
    shield@/>

    Из этих интерфейсов, два провайдера(dc0 и dc1), две локальных сети(dc2 и fxp0), DMZ(fxp1) и VPN(ng0), который соединяется с VPN-сервером в сети
    172.16.0.0/24(dc1).
    Маршрутом по умолчанию является 192.168.98.1(dc0). Почему он? Да потому что он более дешевый. ))) Тем более он будет больше всего загружен, так
    как внешний интерфейс(ng0) будет использоваться только для входящих соединений на web-server, ftp, ssh, radmin и тд., и для исходящих
    соединений по ssh, radmin, icq.
    В принципе про сеть все что хотел, сказал. Осталось только составить pf.conf:


    ## Описываем переменные, содержащие имена интерфейсов

    int_if="fxp0"
    ext_if="ng0"
    isp_if="dc0"
    prov_if="dc1"
    iikt_if="dc2"
    dmz_if="fxp1"

    ## ip-адреса хостов, которые нам понадобятся

    web_server="10.10.20.2"
    ext_gateway="172.17.0.1"
    mail="192.168.1.245"
    proxy="192.168.3.2"
    pinguin="192.168.3.3"
    spider="192.168.1.250"
    veterok="192.168.1.197"
    backup="192.168.1.249"

    ## табличка с хостами, которым разрешен доступ в обход прокси. ))
    table <servers> const { $spider, $mail, $backup }

    ## отбрасывать пакеты будем тихо, чтобы никто не догадался.. ))
    set block-policy drop
    ## Игнорируем петлевой интерфейс
    set skip on lo0

    ## нормализуем входящий трафик
    scrub in all fragment reassemble
    ## нормализуем исходящтй трафик
    ## max-mss необходим из-за низкого mtu на внешнем канале
    scrub out all random-id max-mss 1440

    ## пакеты, пришедшие на внешний интерфейс на порт 80, 221,
    ## 768, 799 или 20000 отправляем внутрь сети и метим их
    rdr on $ext_if inet proto tcp to $ext_if port www tag WEB_SERVER -> \
    $web_server port www
    rdr on $ext_if inet proto tcp to $ext_if port 221 tag FTP_SERVER -> \
    $web_server port ftp
    rdr on $ext_if inet proto tcp to $ext_if port 768 tag SSH_SERVER -> \
    $spider port ssh
    rdr on $ext_if inet proto tcp to $ext_if port 799 tag VETEROK -> \
    $veterok port 4899
    rdr on $ext_if inet proto tcp to $ext_if port 20000 tag PINGUIN -> \
    $pinguin port 2004
    ## Отдаем пакеты идущие к ftp серверам нашей проксе
    rdr pass on $int_if inet proto tcp from $int_if:network to !$web_server \
    port ftp -> 127.0.0.1 port 8021

    ## натим все пакеты на внешнем(ng0) интерфейсе, которые помечены
    nat on $ext_if inet proto tcp tagged WEB_SERVER -> ($ext_if)
    nat on $ext_if inet proto tcp tagged FTP_SERVER -> ($ext_if)
    nat on $ext_if inet proto tcp tagged SSH_SERVER -> ($ext_if)
    nat on $ext_if inet proto tcp tagged VETEROK -> ($ext_if)
    nat on $ext_if inet proto tcp tagged PINGUIN -> ($ext_if)
    nat on $ext_if inet proto tcp tagged RADMIN -> ($ext_if)
    nat on $ext_if inet proto tcp tagged SSH -> ($ext_if)
    nat on $ext_if inet proto tcp tagged ICQ -> ($ext_if)
    ## Наш ftp сервер сможет работать только в активном режиме,
    ## поэтому натим пакеты идущие от его 20 порта
    nat on $ext_if inet proto tcp from $web_server port 20 to \
    !$int_if:network -> ($ext_if)
    ## натим пакеты на интерфейсе другого ISP(dc0),
    ## идущие от прокси сервера одной из сетей
    nat on $isp_if inet proto tcp from $proxy to !$web_server port www -> ($isp_if)
    ## Натим пакеты на интерфейсе dc0, идущие к mail серверам
    nat on $isp_if inet proto tcp from $int_if:network to any port \
    { smtp, pop3 } -> ($isp_if)
    ## Разрешаем доверенным хостам ходить через дешевый интернет канал(dc0)
    nat on $isp_if inet proto tcp from <servers> to any port www -> ($isp_if)

    ## запрещаем все входящие соединения на внешнем интерфейсе
    block in on $ext_if
    ## На пинги отвечаем через тот же интерейс, откуда он пришел
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto \
    icmp from any to $ext_if keep state
    ## отвечаем через тот же интерфейс, через который пришел пакет.
    ## по сути меняем для помеченный пакетов route.
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto tcp \
    tagged WEB_SERVER keep state
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto tcp \
    tagged FTP_SERVER keep state
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto tcp \
    tagged SSH_SERVER keep state
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto tcp \
    tagged VETEROK keep state
    pass in on $ext_if reply-to ($ext_if $ext_gateway) inet proto tcp \
    tagged PINGUIN keep state
    ## Разрешаем все исходящие соединения на данном интерфейсе
    pass out on $ext_if keep state

    ## Блокируем все входящие пакеты на внутреннем интерфейсе
    block in on $int_if
    ## разрешаем входящие пакеты к squid
    pass in on $int_if inet proto tcp from $int_if:network to $int_if \
    port 3128 keep state
    ## отправляем пакеты, идущие к внешним ssh серверам, по другому маршруту
    pass in on $int_if route-to ($ext_if $ext_gateway) inet proto tcp from\
    $int_if:network to { !$int_if, !$web_server, !$proxy } port 22 tag SSH keep state
    ## разрешаем соединяться по ssh внутри сети
    pass in on $int_if inet proto tcp from $int_if:network to \
    { $int_if, $web_server, $proxy } port 22 keep state
    ## куда же без dns? ;)
    pass in on $int_if inet proto udp from $int_if:network to \
    $int_if port 53 keep state
    ## Разрешим сети соединяться с почтовыми службами
    pass in on $int_if inet proto tcp from $int_if:network to any \
    port { smtp, pop3 } keep state
    ## Пускаем пакеты, идущие к внешним radmin серверам, метим их и меняем маршрут
    pass in on $int_if route-to ($ext_if $ext_gateway) inet proto tcp from \
    $int_if:network to any port 4899 tag RADMIN keep state
    ## Разрешаем обращение к внутренним radmin сервера
    pass in on $int_if inet proto tcp from $int_if:network to $pinguin \
    port 2004 keep state
    ## Разрешаем доверенным хостам соединяться с www серверами в обход прокси
    pass in on $int_if inet proto tcp from <servers> to any port www keep state
    ## Пропускаем аську и меняем для нее маршрут
    pass in on $int_if route-to ($ext_if $ext_gateway) inet proto tcp from \
    $int_if:network to any port 5190 tag ICQ keep state
    ## Разрешаем snmp запросы на внутреннем интерфейсе
    pass in on $int_if inet proto udp from $mail to $int_if port snmp keep state
    ## разрешаем icmp пакеты. Как ни крути, но нужны они! ))
    pass in on $int_if inet proto icmp from $int_if:network to $int_if keep state
    ## Разрешаем все исходящие соединения
    pass out on $int_if keep state

    ## Запрещаем все входящие соединения на интерфейсе одного из провайдеров(dc0)
    block in on $isp_if
    ## Разрещаем входящие соединения для пользователя proxy,
    ## из-под него работает ftp-proxy
    ## Это альтернатива открытию всех портов, которые больше 49152
    pass in on $isp_if inet proto tcp from any to $isp_if user proxy keep state
    ## И еще разок пинги.
    pass in on $isp_if inet proto icmp from any to $isp_if keep state
    ## Разрешаем все исходящие пакеты
    pass out on $isp_if keep state

    ## Блокируем все входящее
    block in on $prov_if
    ## Разрешаем только пинги и...
    pass in on $prov_if inet proto icmp from $prov_if:network to $prov_if keep state
    ## ... все исходящие соединения
    pass out on $prov_if keep state

    ## Запрещаем на интерфейсе локальной сети -- dc2
    block in on $iikt_if
    ## Разрешаем обращаться к нашему dns
    pass in on $iikt_if inet proto udp from $pinguin to $int_if port 53 keep state
    ## разрешаем запросы к squid'у
    pass in on $iikt_if inet proto tcp from $iikt_if:network to \
    $iikt_if port 3128 keep state
    ## разрешаем пинги
    pass in on $iikt_if inet proto icmp from $iikt_if:network to $iikt_if keep state
    ## разрешаем все исходящие
    pass out on $iikt_if keep state

    ## на интерфейсе DMZ блочим все
    block in on $dmz_if
    ## Меняем маршрут для пакетов, идущих от порта ftp-data ftp сервера.
    pass in on $dmz_if route-to ($ext_if $ext_gateway) inet proto tcp from $web_server \
    port 20 to !$int_if:network keep state
    ## серверам в DMZ нужно общаться с dns
    pass in on $dmz_if inet proto udp from $dmz_if:network to $dmz_if port 53 keep state
    ## Ну и информационные сообщения тоже не повредят
    pass in on $dmz_if inet proto icmp from $dmz_if:network to $dmz_if keep state
    ## разрешаем все исходящие соединения
    pass out on $dmz_if keep state

    Вот такой вот конфиг. )) Вроде нормально прокомментирован. Если неохота заниматься копированием, то этот же конфиг лежит здесь.
    Ну вот вроде и все что хотел рассказать. Про pf много чего рассказать можно, чем я и займусь в ближайшее время...



    Ссылка на обсуждение: http://forum.lissyara.su/viewtopic.php?t=10010.

    размещено: 2006-11-08,
    последнее обновление: 2006-11-08,
    автор: fr33man

    Категория: Настройка | Добавил: Raxxell5059 (22.12.2010)
    Просмотров: 1077 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]