ALTQ обеспечивает правила обслуживания QoS и другие связанные с ним компоненты, необходимые для реализации совместного использования ресурсов и качества обслуживания.Чаще всего он настраивается на основе BSD маршрутизаторов. ALTQ включен в базу FreeBSD , NetBSD , и интегрирован в пакетный фильтр из OpenBSD .С ALTQ, пакеты могут быть выстроены в очереди для управления полосой пропускания. Планировщик определяет какие пакеты пропустить с задержкой, а какие отправить немедленно.
Приступим к подготовке. Сначала соберем ядро с поддержкой ALTQ, идём в директорию /usr/src/sys/i386/conf Копируем файлик GENERIC в какой-нибудь другой. Например у меня это MYGENERIC. Редактируем его: меняем сроку ident на ident MYGENERIC. # дописываем следующие девайсы: device pf device pflog device pfsync # и следующие опции: 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
Собираем ядро
cd /usr/src make buildkernel KERNCONF="MYGENERIC" make installkernel KERNCONF="MYGENERIC"
#Для работы NAT`а необходимо включить форвардинг в ядре. echo gateway_enable="YES" >> /etc/rc.conf #Для включения форвардинга без перезагрузки можно выполнить sysctl net.inet.ip.forwarding=1
#добавим в rc.conf строки pf_enable="YES" #включаем фаервол pf_rules="/etc/pf.conf" #конфиг фаил pflog_enable="YES" # включаем логирование pflog_logfile="/var/log/pf.log" #фаил куда будет писаться лог
#Лог PF пишет в бинарном виде. И читать его надо tcpdump`ом. #Примерно вот так tcpdump -n -e -ttt -r /var/log/pf.log #можно так же запускать с флагами pf_program="/sbin/pfctl" pf_flags="" pflog_program="/sbin/pflogd" pflog_flags=""
Также PF можно управлять через утилиту pfctl.
Например, включить pf можно так pfctl -e, а выключить pfctl -d.
При включении через pfctl правила автоматически не загружаются.
Для того, чтобы их загрузить надо выполнить команду pfctl -f /etc/pf.conf (вместо имени файла указать своё).
Эта команда ещё пригодится много раз. Если в конфиг файле что-то изменили, то чтобы эти изменения вступили в силу надо их применить pfctl -f /etc/pf.conf.
Прочие команды писать не буду — их можно посмотреть в документации.
Теперь приступим собственно к составлению конфига.
Отмечу очень важное отличие pf от прочих файрволов (ipfw, iptables): в тех файрволах действует первое правило в списке под которое попадает пакет.
И остальными правилами уже не обрабатывается. В pf же наоборот. Действует последнее правило. Но можно отменить дальнейшее рассмотрение правил если для правила применить параметр quick. Так что pf очень гибок в этом.
Конфиг:
############################## MACROSS ############################## ext_if="tun0" #внешний интерфейс int_if="rl0" #внутренний lan="192.168.0.0/24" #локальная сеть icmp_types="{echoreq, unreach}" # allow icmp set block-policy return #drop пакет молча отбрасывается; #return для отброшенных пакетов TCP отсылается пакет TCP RST, # для прочих ICMP Unreachable. set skip on lo0 #пропускаем все на петле set loginterface $ext_if #указываем интерфейс для логирования ############################## TABLES ############################## #Таблицы. Удобная штука. Если адресов много, их можно запихать в таблицу. #Есть ещё списки, но они работают медленнее. table <lan> {192.168.0.0/24} table <boss> {192.168.0.100, 192.168.0.101} table <home> {192.168.0.111, 192.168.0.112, 192.168.0.113} ############################## SCRUB ############################## scrub in all #Нормализация всех входящих пакетов. Желательно. ############################## ALTQ ############################## #altq on interface scheduler bandwidth bw qlimit qlim tbrsize size queue { queue_list } #interface собсно интерфейс #scheduler планировщик очереди. Нас интересует cbq (есть ещё priq, но он не годится для наших целей) #bw ширина очереди, и чаще всего ширина канала. #qlim максимальное число пакетов в очереди. Необязательный параметр. По умолчанию — 50 #size размер token bucket regulator в битах. Если не определен, то устанавливается на основе ширины #полосы пропускания. (понятия не имею что и зачем) #queue_list — список дочерних очередей. altq on $int_if cbq bandwidth 100Mb queue { inet_in, default_in } #queue name [on interface] bandwidth bw [priority pri] [qlimit qlim] scheduler ( sched_options ) { queue_list } #interface интерфейс. Так как у нас пакеты в очередь должны пихаться независимо от того на каком они #интерфейсе, то параметр надо опустить. #bw ширина очереди. Можно указывать в %, можно в бит/с. #scheduler уже сказано. #pri приоритет. Для cbq приоритет изменяется от 0 до 7, для priq диапазон от 0 до 15. Приоритет 0 #считается самым низким. Если этот параметр не определён, ему назначается 1. #sched_option опции планироващика. Нас интересует опция borrow. Позволяет занимать в случае #необходимости и наличиния возможности ширину канала у родительской очереди и у очередей, также #являющихся для данной родительской дочерними. (ппц замутил). Данная опция работает только #с планировщиком cbq. Также желательна опция red. Позволяет не допускать полного забивания канала. #То есть начинает потихоньку дропать пакеты, задолго до полной забитости очереди. #Чем более забита очередь, тем больше дропает. #queue_list список дочерних очередей. То есть для основной они уже будут внуками”. Возможно #использовать только с планировщиком cbq. queue inet_in bandwidth 4Mb { qboss_in, qhome_in } queue qboss_in bandwidth 3Mb priority 5 cbq(red,borrow) queue qhome_in bandwidth 512Kb priority 1 cbq(red,borrow) queue default_in bandwidth 90% cbq(red default) #очереди для исходящего трафика altq on $ext_if cbq bandwidth 100Mb queue { inet_out, default_out } queue inet_out bandwidth 4Mb { qboss_out, qhome_out } queue qboss_out bandwidth 3Mb priority 5 cbq(red,borrow) queue qhome_out bandwidth 512Kb priority 1 cbq(red,borrow) queue default_out bandwidth 90% cbq(red default) ############################## NAT ############################## nat on $ext_if from $lan to !$lan -> ($ext_if) #($ext_if) подставляет ip этого интерфейса ############################# RDR ############################## #WEB пример проброса портов rdr on $ext_if proto tcp from any to ($ext_if) port 80 -> 192.168.0.1 port 80 ############################## Filters ############################# antispoof log quick for $ext_if #Не плохо так же защититься от спуфинга: antispoof log quick for $int_if #ну и распихиваем правила по очередям. pass in on $int_if from <boss> to !$lan queue qboss_out no state pass out on $int_if from !$lan to <boss> queue qboss_in no state pass in on $int_if from <home> to !$lan queue qhome_out no state pass out on $int_if from !$lan to <home> queue qhome_in no state pass log inet proto icmp all icmp-type $icmp_types
Работу шейпинга можно посмотреть командой pfctl -vvsq
Материал:
http://tuupic.org.ru/dinamicheskij-shejping-na-freebsd/
http://house.hcn-strela.ru/BSDCert/BSDA-course/apcs02.html
http://www.openbsd.org/faq/pf/ru/
http://www.lissyara.su/articles/openbsd/pf/office_config/