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/