Документация по ОС FreeBSD Суббота, 11.05.2024, 17:23
Приветствую Вас Гость | RSS
Меню сайта

Категории каталога
IPFW [58]

Главная » Статьи » FireWall » IPFW

Разбираем простой конфиг PF [2008]
Настройка pf. (обзор возможностей + разбор конфига + пример ip spoofing'a)

Часть 1. Обзор возможностей, установка.


Что умеет PF :

  • транслировать адреса Network Address Translation (NAT);
  • позволяет строить отказоустойчивый кластер фаерволлов с использованием Common Address Redundancy Protocol (CARP);
  • поддерживает несколько видов приоритезации трафика (ALTernate Queuing);
  • пробрасывать определенный порт на определенный комп в локальной сети (Port Forwarding);
  • выступать в качестве прокси для входящих соединений, защищая внутренний сервер от атак SYN-flood (SYN-proxy);
  • передавать нагрузку на пул серверов, отслеживая их состояние. Получается, опять же, отказоустойчивый кластер + балансировка нагрузки несколькими способами (Load balancing);
  • фильтровать пакеты по типам (tcp, udp, icmp) и подтипам (icmp echoreq, icmp unreach);
  • поддерживает макросы и таблицы. Например, можно завести таблицу брутфорсеров и динамически ее пополнять;
  • выступать в роли низкоуровнего Ethernet моста, не имеющего собственного IP адреса (Bridging Firewall);
  • метить пакеты специальными метками. Полезно когда нельзя принять решение о судьбе пакета основываясь только лишь на адресе подсети и номере порта (tags);
  • фиксировать любую сетевую активность и рисовать графики в различных разрезах с помощью утилиты pfstat
    (смотрим тут какая красота получается);
  • нормализовать пакеты. Полезно от некоторых видов dos атак; (scrub).
    Вроде все, ничего не забыл.

    Установка :

    OpenBSD.
    OpenBSD является материнской платформой для PF (именно на ней он появился впервые,
    а потом был портирован на остальные BSD), поэтому он присутствует во всех ее версиях.
    Для включения PF в OpenBSD требуется :

    /etc/rc.conf.local
    
    pf=YES
    

    и можно еще указать конфиг файл
    pf_rules=/etc/pf.conf 
    

    FreeBSD.
    Во всех свежих версиях FreeBSD он уже присутствует в качестве загружаемого модуля.
    Но я включил его в ядро явно (это необязательно) :

    device pf
    device pflog
    device pfsync
    

    и ОБЯЗАТЕЛЬНО включите следующие опции в ядро Вы хотите использовать приоритезацию и очереди ALTQ
    options ALTQ
    options ALTQ_CBQ # Class Bases Queuing (CBQ)
    options ALTQ_RED # Random Early Detection (RED)
    options ALTQ_RIO # RED In/Out
    options ALTQ_HFSC # Hierarchical Packet Scheduler (HFSC)
    options ALTQ_PRIQ # Priority Queuing (PRIQ)
    options ALTQ_NOPCC # Required for SMP build
    

    Все опции файла rc.conf, касающиеся PF:
    pf_enable="NO" 
    pf_rules="/etc/pf.conf"
    pf_program="/sbin/pfctl" 
    pf_flags="" 
    pflog_enable="NO" 
    pflog_logfile="/var/log/pf.log" 
    pflog_program="/sbin/pflogd" 
    pflog_flags="" 
    pfsync_enable="NO"
    pfsync_syncdev=""
    pfsync_ifconfig="" 
    

    включим PF
    
    pf_enable="YES" 
    

    и ведение лога (как смотреть лог - файл читайте в конце 2 части)
    pflog_enable="YES"
    

    Изменения вступят после перезагрузки. Чтобы не перезагружать компьютер можно дать команду
    (требует рутовых прав)
    # pfctl -e
    

    должно появиться pf enabled. А после перезагрузки он будет запускаться согласно rc.conf

    NetBSD
    О том, как заставить PF работать в NetBSD читайте в [1].

    Часть  2. Разбор конфигурационного файла.

    Вообще говоря, конфиг делится на несколько секций, которые должны иметь строгий порядок и не должны
    пересекаться. Порядок следующий :

  • 1) макросы
  • 2) таблицы
  • 3) опции
  • 4) параметры нормализации
  • 5) приоретизация и очереди ALTQ
  • 6) правила трансляции
  • 7) правила фильтра

    Ниже приведен конфиг с моего домашнего шлюза, не претендует на полноту, т.к. здесь нет таблиц и
    очередей ALTQ, но в качестве примера сойдет, тем более что я буду комментировать :

    ##### BEGIN CONFIG
    ###############################################################################
    ## The gateway1's pf ruleset BASIC v. 0.02a ##
    ###############################################################################
    # СЕКЦИЯ макросы, (фактически макросами называется то же самое что в языках
    ## программирования называется переменной)
    ## интерфейсы
    int_if="xl0" # внутренний интерфейс, который "смотрит" ко мне в домашнюю
    ## локалку.
    ext_if_cheap="tun0" ## виртуальный pppoe интерфейс, безлимит.
    ## Здесь берется адрес интерфейса tun0.
    ## Это удобно, т.к. провайдер может назначать динамический адрес.
    ## Используя этот макрос нам не придется корректировать файл правил pf когда 
    ## провайдер по какой - то причине станет выдавать нам другой IP адрес.
    ext_if_expensive="tun1" ## виртуальный pppoe интерфейс, помегабайтная оплата
    game_ports="7777" ## порт игры Unreal Tournament
    icmp_types="{ echoreq, unreach}" ## разрешенные типы icmp сообщений.
    ## Первое необходимо для работы UNIX traceroute (для win tracert этого
    ## не требуется), а второе нужно когда пытаемся коннектиться 
    ## к хосту, который в дауне.
    udp_services="{ domain, ntp }" ## разрешенные типы udp сервисов
    
    # сети и хосты
    trusted_lan="192.168.0.0/24" ## доверенная домашняя локалка
    untrusted_lan="10.0.0.0/8" ## внешняя локалка провайдера, 
    ## будем называть ее WAN
    localnet="127.0.0.0/8" ## сеть интерфейса петли, ну это понятно
    game_server="192.168.0.15/32" ## адрес игрового сервера в 
    ## домашней локалке
    wan_services="{ 85.113.63.251/32, 85.113.59.8/32, 85.113.62.200/32 }" 
    ## серверы в WAN провайдера (игровые, файловые). 
    ## Если мы захотим добавить в этот список еще несколько серверов,
    ## например 1.1.1.1 и 2.2.2.2, то список будет выглядеть так 
    ## wan_services="{ 85.113.63.251/32, 85.113.59.8/32, 
    ## 85.113.62.200/32, 1.1.1.1/32, 2.2.2.2/32}"
    ## и править больше ничего не потребуется. Вот оно, удобство макросов.
    
    # СЕКЦИЯ глобальные опции
    set block-policy return ## сбрасываем соединение вежливо,
    ## по умолчанию стоит агрессивное drop
    set skip on lo0 ## полностью пропускаем проверку на петле 
    ## (повзоляет сэкономить немного вычислительных ресурсов)
    set skip on $int_if ## полностью пропускаем проверку на интерфейсе,
    ## к которому подключена домашняя локалка. 
    ## Вредителей в ней у меня нет. (также повзоляет сэкономить немного
    ## вычислительных ресурсов)
    
    # СЕКЦИЯ параметры нормализации
    scrub in all ## нормализуем все входящие пакеты на всех 
    ## интерфейсах. Что это значит?
    ## Пакеты приходят частями (фрагментами). scrub сначала собирает 
    ## пакет у себя на шлюзе и только потом передает его дальше, 
    ## во внутреннюю сеть. Позволяет защититься от некоторого
    ## вида dos атак сбрасывая фрагменты TCP с некорректно 
    ## установленными флагами.
    
    # СЕКЦИЯ приоретизация и очереди ALTQ
    ## у меня пустая, т.к. не использую шейпинг и очереди. 
    ## Всем компам домашней сети доступна
    ## полная ширина канала без ограничений.
    
    # СЕКЦИЯ port forwarding & NAT
    rdr on $ext_if_expensive proto { tcp, udp } from $untrusted_lan to \ 
    $ext_if_expensive port $game_ports -> $game_server port $game_ports
    ## Здесь пробрасываем всех кто коннектится по интерфейсу 
    ## ext_if_expensive на порт
    ## game_ports НА game_server порт game_ports, т.е. :
    ## from 10.0.0.0/8 to ext_if_expensive:7777 ПРОБРОСИТЬ НА
    ## 192.168.0.15:7777
    ## вот что получается если посмотреть с точки зрения PF
    ## (команда pfctl -sa)
    ## rdr on tun1 inet proto tcp from 10.0.0.0/8 to 10.[censored]
    ## port = 7777 -> 192.168.0.15 port 7777
    ## rdr on tun1 inet proto udp from 10.0.0.0/8 to 10.[censored]
    ## port = 7777 -> 192.168.0.15 port 7777
    ## И....
    ## По просьбам трудящихся добавляю нат средствами PF 
    nat on $ext_if_cheap from $trusted_lan to any -> ($ext_if_cheap) 
    ## делаем нат НА внешнем интерфейсе (интерфейс с инетом) от 
    ## доверенной сети (192.168.0.0/24) ко всем.
    ## Параметр после знака -> позволяет подписывать у 
    ## отправляемых в инет пакетов любой адрес отправителя,
    ## но здесь нам нет смысла его менять, поэтому ставим
    ## адрес внешнего интерфейса. Т.е. ($ext_if_cheap).
    
    # СЕКЦИЯ правила фильтрации 
    antispoof quick for $ext_if_cheap # включает простейший 
    ## антиспуфинг, который превращается в 2 правила :
    ## block drop in quick on ! tun0 inet from tun0 to any
    ## block drop in quick inet from tun0 to any 
    ## Что означает : сбрасывать все входящие пакеты с 
    ## адресом отправителя равным нашему
    ## Самое время рассказать о порядке срабатывания фильтрующих
    ## правил и о ключе quick.
    ## Все правила обрабатываются сверху вниз и приоритет имеет
    ## последнее правило, т.е. если написать сначала
    ## block all ## а потом
    ## pass all
    ## то сработает 
    ## pass all ## как если бы мы кроме него ничего не писали
    ## Ключ quick указывает на то, то нужно применить текущее 
    ## правило и прекратить дальнейшую обработку.
    antispoof quick for $ext_if_expensive ## тоже самое и
    ## для второго интерфейса
    ## Честно говоря, полноценным антиспуфингом это сложно
    ## назвать, от части спуферов, конечно спасает
    ## но для реализации путевого антиспуфинга надо
    ## смотреть RFC 1918 и 3330 и явно запрещать пакеты с
    ## левых сетей типа 127.0.0.0, 240.0.0.0/4, 169.254.0.0/16 и т.д.
    
    
    block all ## запрет всего по-умолчанию
    
    ##--everithing LOCAL
    pass out on $ext_if_cheap from $ext_if_cheap to any keep state
    ## разрешаем весь исходящий трафик с
    ## локальной машины (на ней у меня клиент торент сетей)
    ##--everithing LOCAL
    
    ##--everithing for 192.168.0.0/24 LAN
    pass out on $ext_if_cheap from $trusted_lan to any keep state 
    ## разрешаем весь трафик от нашей домашней сети
    ## здесь хочу сказать, что если бы мы включили фильтрацию для
    ## интерфейса xl0, то пришлось бы писать ДВА правила :
    ## одно на разрешение ВХОДящего трафика по xl0 от сети 192.168.0.0/24 
    ## другое на разрешение ИСХОДящего трафика по ext_if_cheap 
    ## от сети 192.168.0.0/24 
    ##--everithing for 192.168.0.0/24 LAN
    
    ##--direct connections from 192.168.0.0/24 LAN to 10.0.0.0/8 WAN
    pass out on $ext_if_expensive from $trusted_lan to \ 
    $untrusted_lan keep state ## разрешаем трафик от
    ## локалки 192.168.0.0/24 к сети провайдера по быстрому соединению
    ##--direct connections from 192.168.0.0/24 LAN to 10.0.0.0/8 WAN
    
    ##--WAN services
    ## out from 192.168.0.0/24 LAN to all WAN servers VIA fast connection
    pass out on $ext_if_expensive from $trusted_lan to \ 
    $wan_services keep state ## разрешаем трафик от
    ## локалки 192.168.0.0/24 к серверам провайдера по быстрому соединению
    ##--WAN services
    
    ## и теперь разрешаем входящий трафик по быстрому соединению,
    ## которые мы будем пробрасывать на 192.168.0.15:7777
    pass in log on $ext_if_expensive proto { tcp, udp } from $untrusted_lan to \
    $game_server port $game_ports keep state
    ## это локальный трафик, стоит недорого, а для игр очень важна 
    ## скорость и ширина канала, поэтому
    ## трафик пущен именно по быстрому соединению
    ## ВНИМАНИЕ! Долго ломал голову почему ко мне не могут присоединиться
    ## ребята из локальной сети, чтобы 
    ## поиграть в UT. Методом многочисленных проб удалось установить
    ## что в этом правиле требуется указать
    ## разрешение трафика к game_server, а не к ext_if_expensive,
    ## как сначала может показаться. Убил кучу
    ## времени на это, благо товарищ из локалки помог продиагностировать.
    ## Спасибо GrayCat ;-)
    
    pass log inet proto icmp all icmp-type $icmp_types 
    ## разрешаем icmp трафик установленных типов.
    ##### END CONFIG
    

    И пара слов о keep state. Когда программа (например, браузер из доверенной сети) лезет в интернет — разрешение на исходящий от нас трафик мы указываем явно правилом :

    pass out on $ext_if_cheap from $trusted_lan to any keep state
    

    мы набираем в строке обозревателя какой - то сайт и запрос от обозревателя поступает на этот сайт. В нашем файрволле устанавливается состояние, означающее что мы ожидаем данных от этого сайта. Так вот если написать

    pass out on $ext_if_cheap from $trusted_lan to any 
    

    БЕЗ keep state (или указав no state), то запрос на сайт поступит, а ответ наш файрвол зарежет. Вот зачем нужен keep state.
    И еще одна особенность keep state. Начиная с FreeBSD версии 7.0 (аналогичная версия pf входит в поставку OpenBSD 4.1) keep state применяется ко всем правилам по умолчанию. Если вы не хотите чтобы к некоторым (или ко всем) правилам применялось keep state — пишите явно no state.

    Пример из конфига выше.
    pass out on $ext_if_expensive from $trusted_lan to $untrusted_lan
    

    FreeBSD версии 7.0 и выше (или OpenBSD версии 4.1 и выше)
    воспримет правило как :
    pass out on $ext_if_expensive from $trusted_lan to $untrusted_lan keep state
    

    а FreeBSD ниже версии 7.0 (или OpenBSD ниже версии 4.1)
    воспримет это правило как :
    pass out on $ext_if_expensive from $trusted_lan to $untrusted_lan no state
    

    в новых версиях BSD (FreeBSD 7.0 и OpenBSD 4.1) лично я предпочитаю все равно явно писать keep state (хотя это необязательно и принимается по умолчанию), потому что особого труда это не составляет, а обратная совместимость со "старыми" версиями PF в наличии. Например, конфиг из пункта 2 взят с сервера под управлением ОС FreeBSD 7.0, но у меня есть сервер и на 6.3, на котором сейчас IPFW в качестве файрвола, потом когда буду переводить все на PF меньше шансов запутаться на такой мелочи как состояния keep state.

    По поводу логов. PF пишет лог в бинарном формате, поэтому если смотреть его обычным просмотрщиком Вы увидите сплошные крякозябры. Читать его можно с помощью tcpdump, командой
    # tcpdump -n -e -ttt -r /var/log/pf.log
    

    Часть 3. IP spoofing.
    Несколько месяцев назад у меня была задача организовать ip spoofing под FreeBSD;  коротко, ip spoofing — это подмена ip адреса отправителя. Спуфинг надо сказать планировался в мирных целях, имелось 2 канала :

  • 1) быстрый и помегабайтный (оплата за входящий трафик);
  • 2) медленный и безлимитный (абонемент на 1 месяц);

    хотелось получить один гибридный ассиметричный канал с большой скоростью на отдачу и при этом платить только за безлимит. Погуглив чутка я выяснил что это можно реализовать с помощью ip spoofing'a сделав следующее :
  • 1) сделать дефолтовым маршрутом интерфейс с быстрым инетом;
  • 2) отправлять с быстрого канала пакеты с исходным адресом безлимита (тогда пакеты пройдут именно тот путь что отмечен красными стрелками на рисунке);

    Мне подсказали что это умеет pf. Вот эта строчка в конфиге позволяет подменить адрес отправителя :

    nat on $ext_if_expensive from $trusted_lan to any -> $spoofed_addr
    

    где
    ext_if_expensive — внешний быстрый интерфейс;
    trusted_lan — доверенная сеть, это моя внутренняя сеть, что находится за шлюзом
    spoofed_addr — какой адрес отправителя писать. В моем случае, это адрес безлимитного интерфейса.

    Настроив маршрутизацию, применив правило и запустив tcpdump на быстром интерфейсе я убедился что пакеты отправляются с подмененным адресом. Правда на цисках провайдера, как оказалось, была включена опция rp_filter, запрещающая спуфинг, поэтому из моей задумки ничего не вышло. Но, говорят, есть еще провайдеры где эта схема работает.

    В следующей статье рассмотрим более сложный конфиг с очередями ALTQ, серверами в DMZ, требующими доступ снаружи, и ограниченным списком сервисов, к которым могут обращаться пользователи нашей сети. Ну и если получится, завернем трафик на squid.

    Список литературы :

  • [1] The book of pf (лежит на фтп, называется the.book.of.pf.pdf)
  • [2] OpenBSD PF FAQ
  • [3] Vingrad forum, network technologies.


  • Источник: http://www.lissyara.su/?id=1671
    Категория: IPFW | Добавил: oleg (23.05.2008) | Автор: Grishun_U_S
    Просмотров: 2360 | Рейтинг: 0.0/0 |
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Форма входа

    Beastie

    Друзья сайта

    Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    links

    Copyright MyCorp © 2024