Если вы работает с pf и во время загрузки правил получаете такое сообщение:

No ALTQ support in kernel
 ALTQ related functions disabled

значит поддержка altq не включена. Включить можно только через пересборку ядра. Для этого добавляем такие опции в конфигурационный файл ядра:

 

options ALTQ

включает подсистему  ALTQ

options ALTQ_CBQ

включает Class Based Queuing (CBQ). CBQ позволяет распределять пропускную способность соединений по классам или очередям для выставления приоритетов трафика на основе правил фильтрации.

options ALTQ_RED

включает Random Early Detection (  RED  ).  RED  используется для предотвращения перегрузки сети.  RED  вычисляет длину очереди и сравнивает ее с минимальной и максимальной границей очереди. Если очередь превышает максимум, все новые пакеты отбрасываются. В соответствии со своим названием,  RED  отбрасывает пакеты из различные соединений в произвольном порядке.

options ALTQ_RIO 

включает Random Early Detection In and Out.

options ALTQ_HFSC

включает Hierarchical Fair Service Curve Packet Scheduler. (Дополнительная информация http://www-2.cs.cmu.edu/~hzhang/HFSC/main.html)

options ALTQ_PRIQ

включает Priority Queuing (  PRIQ  ).  PRIQ  всегда пропускает трафик из более высокой очереди первым.

options ALTQ_NOPCC

включает поддержку  SMP  для  ALTQ  . Эта опция необходима для  SMP  систем.

options ALTQ_CDNR
options ALTQ_DEBUG

Тестовый стенд: FreeBSD 8.2 i386

Условия — ограничить download (1000 Кбит/с) upload (2000 Кбит/с) с возможность заимствовать свободный трафик из ширины 5000 Кбит/с

ВНИМАНИЕ !!!

Ограничить можно только исходящий (upload) трафик, так как входящий (download) — уже пришёл и ограничить его нельзя. Но есть хитрый способ (не всегда даёт желаемый результат, но лучше, чем ничего): входящий на внутренний интерфейс (download) будет исходящим для внешнего. Именно так и будут составляться правила.

Иными словами сначала составляете правила распределения трафика, а потом навешиваете на правила файервола, но только с ключевым словом out. Иначе шейпер работать не будет.

Правила шейпера:

altq on $ext_if cbq bandwidth 5000Kb queue { IN_ext, OUT_ext }
        queue IN_ext bandwidth 1000Kb cbq(default borrow)
        queue OUT_ext bandwidth 2000Kb
altq on $int_if cbq bandwidth 5000Kb queue { IN_int, OUT_int }
        queue IN_int bandwidth 1000Kb cbq(default borrow)
        queue OUT_int bandwidth 2000Kb

Навешиваем шейпер:

pass out on ext_if from any to $int_if:network queue IN_ext no state
 pass out on int_if from $int_if:network to any queue OUT_int no state

Напомню, что в pf’e важен порядок правил:

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

Поэтому правила, начинающиеся с altq/queue будут идти выше правил трансляции, а правила pass — вместе с правилами фильтрации.

А теперь, что бы посмотреть состояние очередей, выполним :

# pfctl -sq
 queue root_em0 on em0 bandwidth 5Mb priority 0 cbq( wrr root ) {IN_ext, OUT_ext}
 queue IN_ext on em0 bandwidth 1Mb cbq( borrow default )
 queue OUT_ext on em0 bandwidth 2Mb
 queue root_em1 on em1 bandwidth 5Mb priority 0 cbq( wrr root ) {IN_int, OUT_int}
 queue IN_int on em1 bandwidth 1Mb cbq( borrow default )
 queue OUT_int on em1 bandwidth 2Mb

Примечание.

Будьте внимательны при использовании borrow+cbq, так как оно не всегда работает, так как вам этого хочется. Яркий пример — не заимствование пропускной способности от родителей. Если кратко — то использовать вместо cbq -> hfsc

Сама проблема  http://lists.freebsd.org/pipermail/freebsd-pf/2009-March/005058.html
Решение проблемы  http://lists.freebsd.org/pipermail/freebsd-pf/2009-March/005061.html

Примечание 2.

В пакетном фильтре (начиная с OpenBSD 5.5) pf реализована новая система управления очередями сетевых пакетов, которая пришла на смену системе приоритизации трафика и управления пропускной способности ALTQ. Поддержка ALTQ пока сохранена, но будет удалена в следующем выпуске. Изменено действие правила блокировки по умолчанию, в pf.conf теперь используется «block return«. Простейший пример нового синтаксиса расстановки приоритетов для разного вида трафика:

 queue std on em0 bandwidth 100M
 queue ssh parent std bandwidth 10M
 queue mail parent std bandwidth 10M, min 5M, max 25M
 queue http parent std bandwidth 80M default

Необходимо было настроит динамический шейпер для локальной сети. Выбор стал между ipfw+dummynet и pf+altq. В результате шейпер решили настроить на dummynet, а правила NAT и фильтрации на PF, так как PF+ALTQ не дает возможности создания очереди на виртуальных интерфейсах (bridge, ng*, tun* ).
Визуальную статистику по пользователям, будем смотреть с помощью mrtg. Вышло даже неплохо.
Установленная ОС:

[root@pdcserv ~]# uname -rv
FreeBSD 8.1-RELEASE #0

Первым делом пересоберем ядро с поддержкой дамминета и PF:

#PF
device pf
device pflog
device pfsync
options ALTQ
options ALTQ_CBQ
options ALTQ_RED
options ALTQ_RIO
options ALTQ_HFSC
options ALTQ_PRIQ
options ALTQ_NOPCC#IPFW
options IPFIREWALL
options DUMMYNET
options HZ=1000

Далее необходимо немного тюнинговать ядро:

[root@pdcserv /etc]# cat /etc/sysctl.conf
net.inet.ip.forwarding=1 #включаем форвардинг пакетов
net.inet.ip.fastforwarding=1 #эта опция действительно ускоряет форвардинг
net.inet.tcp.blackhole=2 #ядро убивает tcp пакеты, приходящие в систему на непрослушиваемые порты
net.inet.udp.blackhole=0 #как и выше, только не убивает ибо traceroute пакеты не покажут этот хоп
net.inet.icmp.drop_redirect=1 #не обращаем внимания на icmp redirect
net.inet.icmp.log_redirect=0 #и не логируем их
net.inet.ip.redirect=0 #не реагируем на icmp redirect
net.inet.ip.sourceroute=0 #отключение маршрутизации от источника
net.inet.ip.accept_sourceroute=0 #старый и бесполезный механизм
net.inet.icmp.bmcastecho=0 #защита от SMURF атак
net.inet.icmp.maskrepl=0 #не отдавать по icmp паску своей подсети
net.link.ether.inet.max_age=30 #переспрашиваем каждые 30 секунд mac адреса в своём arp пространстве
net.inet.tcp.drop_synfin=1 #небольшая защита
net.inet.tcp.syncookies=1 #от доса
kern.ipc.somaxconn=32768 #увеличиваем размер очереди для сокетов
kern.maxfiles=204800 #увеличиваем число открытых файловых дескрипторов
kern.maxfilesperproc=200000 #кол-во ф.д. на каждоый процесс  
kern.ipc.nmbclusters=524288 #увеличиваем число сетевых буферов
kern.ipc.maxsockbuf=2097152 #
kern.random.sys.harvest.ethernet=0 #не использовать трафик и прерывания    
kern.random.sys.harvest.interrupt=0 #как источник энтропии для random'a  
net.inet.ip.dummynet.io_fast=1 #заставляет dummynet работать побыстрее  
net.inet.ip.dummynet.hash_size=65535 #  
net.inet.ip.dummynet.pipe_slot_limit=2048 #
kern.ipc.shmmax=67108864 #макс. размер сегмента памяти
net.inet.ip.intr_queue_maxlen=8192 #размер очереди ip-пакетов
#net.inet.ip.fw.one_pass=0 # 0=пакеты, прошедшие пайпы не вылетают из фаервола, а дальше идут по нему
net.inet.ip.fw.verbose=1
net.inet.ip.fw.verbose_limit=5
net.inet.ip.dummynet.hash_size=1024
net.inet.ip.fw.dyn_buckets=1024

Перейдем к настройке IPFW (dummynet);

[root@pdcserv /etc]#cat /etc/ipfw.conf
#!/bin/sh

cmd="ipfw -q"
lan=rl0 # LAN
wan=ae0 # WAN
drate=2Mbit/s # download
urate=2Mbit/s # upload
n=10 #Количество пользователей (1:253)

$cmd flush # Очищаем правила
$cmd pipe flush # Очищаем пайпы
$cmd table all flush # Очищаем все таблицы

# download (wan->lan)
$cmd pipe 100 config bw $drate queue 100 noerror
$cmd queue 111 config pipe 100 weight 50 queue 100 mask dst-ip 0xffffffff noerror

# upload (lan->wan)
$cmd pipe 200 config bw $urate  queue 100 noerror
$cmd queue 211 config pipe 200 weight 50 queue 100 mask src-ip 0xffffffff noerror

#Создаем очереди по таблицам
$cmd add queue tablearg ip from table(10) to any out recv $lan xmit $wan
$cmd add queue tablearg ip from any to table(11) out recv $wan xmit $lan

#Генерация правил подсчета трафика по пользователях
i=2
k=`expr $i + $n`
while [ "$i" -lt "$k" ]
do
$cmd add count all from any to 10.10.10.$i/32
$cmd add count all from 10.10.10.$i/32 to any
i=`expr $i + 1`
done

# IPFIREWALL_DEFAULT_TO_ACCEPT
$cmd add allow all from any to any

### Заполняем таблицы: ip номер_пайпы ###
# user_1
#$cmd table 10 add 10.10.10.2/32 211
#$cmd table 11 add 10.10.10.2/32 111

# user_2
#$cmd table 10 add 10.10.10.3/32 211
#$cmd table 11 add 10.10.10.3/32 111

# user_3
#$cmd table 10 add 10.10.10.4/32 211
#$cmd table 11 add 10.10.10.4/32 111
#user_all
$cmd table 10 add 10.10.10.0/24 211
$cmd table 11 add 10.10.10.0/24 111

На PF настраиваем только NAT:

[root@pdcserv /etc]#cat /etc/pf.conf
####МАКРОСЫ####
# WAN ISP
ext_if="ae0"

# LAN
int_if="rl0"

LAN="10.10.10.0/24"
#### NAT ####
# Разрешаем ходить в интернет через NAT
nat on $ext_if inet from $LAN to !$LAN -> ($ext_if)

Для автозапуска добавим строчки в /etc/rc.conf:

[root@pdcserv /etc]#cat >>  /etc/rc.conf
#pf  
pf_enable="YES"
pf_rules="/etc/pf.conf"
pf_flags=""
pflog_logfile="/var/log/pf.log"
pflog_flags=""#ipfw
firewall_enable="YES"
firewall_script="/etc/ipfw.conf"

Для визуальной статистики отдельно по каждому пользователю, необходимо добавить в конфиг MRTG блоки такого содержания:

#Общий блок
HtmlDir: /usr/local/www/mrtg
ImageDir: /usr/local/www/mrtg/img
LogDir: /usr/local/www/mrtg
Language: russian
Options[^]: growright, unknaszero, nobanner, transparent, noinfo, nopercent, integer
Background[_]: #B0C4DE
XSize[_]: 400
YSize[_]: 100# ipfw user_2
Target[user_2]: `ipfw show 300 | awk '{ print $3 }' && ipfw show 400 | awk '{ print $3 }'`
Title[user_2]: user_2
Pagetop[user_2]: <H1>user 192.168.100.2</H1>
Options[user_2]: bits
MaxBytes[user_2]:1250000

Вывод сгенерированных правил для 2-х пользователей:

[root@pdcserv ~]# ipfw show 
00100   0     0 queue tablearg ip from table(10) to any out recv rl0 xmit ae0
00200   0     0 queue tablearg ip from any to table(11) out recv ae0 xmit rl0
00300   0     0 count ip from any to 10.10.10.2
00400   0     0 count ip from 10.10.10.2 to any
00500   0     0 count ip from any to 10.10.10.3
00600   0     0 count ip from 10.10.10.3 to any
00700 129 48429 allow ip from any to any
65535   0     0 deny ip from any to any
[root@pdcserv ~]#

Просмотр текущих динамических очередей:

[root@pdcserv ~]# ipfw queue show
q00211 100 sl. 0 flows (1024 buckets) sched 200 weight 50 lmax 0 pri 0 droptail
mask:  0x00 0xffffffff/0x0000 -> 0x00000000/0x0000
BKT Prot ___Source IP/port____ ____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp
q00111 100 sl. 0 flows (1024 buckets) sched 100 weight 50 lmax 0 pri 0 droptail
mask:  0x00 0x00000000/0x0000 -> 0xffffffff/0x0000
BKT Prot ___Source IP/port____ ____Dest. IP/port____ Tot_pkt/bytes Pkt/Byte Drp
[root@pdcserv ~]#

Вот дошли руки и до корпоративного сервера — [urlspan]Exim[/urlspan]. Посмотрев статистику с помощью встроенного парсера логов(eximstats), решил что  блокировка спамеров  будет  проводиться  по IP.
Напишем скрипт, который будет запускать eximstats с необходимы опциями, парсить html-лог и складывать в файл «/etc/pf-mail-spammers» нежелательные IP, которые в качестве таблицы будут подгружаться в PF:

[root@router /]#cat eximstats.sh
/usr/local/sbin/eximstats -nt -nr -include_original_destination -chartdir/usr/local/www/eximstats/ -html=/usr/local/www/eximstats/ eximstats.html /var/log/exim/main
sleep 5
/usr/local/bin/php /eximstats.php
sleep 5
pfctl -f/etc/pf.sh

Парсер:

[root@router /]# cat eximstats.php 
<?php
$content=file_get_contents ('http://<ваш домен>/eximstats/#Rejected');
$pos = strpos ($content,'<h2>Top 50 rejected ips by message count</h2>');
$content = substr ($content, $pos);
$pos = strpos ($content, '<hr>');
$content = substr ($content, 0, $pos);
preg_match_all ('/d*.d*.d*.d*/', $content, $output);
foreach ($output as $index => $val)
{
foreach ($val as $val2)
{
if ((substr ($val2, 0, 3)!='127') and (substr ($val2, 0, 7)!='192.168'))
{
$mass[]=$val2;
}
}
}
$str = implode («n», $mass);
$file = fopen («/etc/pf-mail-spammers»,"w+");
fputs ( $file, $str);
fclose ($file);
echo ('ok')
?>

Добавим таблицу и блокирующее правило в /etc/pf.conf:

#Спамеры живут тут.
table <mailspam> persist file "/etc/pf-mail-spammers"
block in log quick from <mailspam>

Для просмотра лога eximstats, создадим каталог для местонахождения лога и добавим директорию в Apache:

[root@router /# mkdir /usr/local/www/eximstats
<Directory /usr/local/www/eximstats>
DirectoryIndex eximstats.html
AllowOverride None
Order deny,allow
Allow from <IP>
</Directory>

и вежливо перезапустим его:

[root@router /usr/local/etc/rc.d]# apachectl graceful
/usr/local/sbin/apachectl graceful: httpd gracefully restarted
[root@router /usr/local/etc/rc.d]# 

Теперь можно смотреть статистику по Exim в браузере:

http://<ваш домен>/eximstats/

Добавим в крон для выполнения по расписанию:

[root@router /etc]# cat /etc/crontab | grep eximstats
#eximstats
58 23*** root /eximstats.sh

В связи с сменой реквизитов предприятия, необходимо было перейти на новый домен,так как на старом крутился мыльник (exim) на 100чел. нужно было настроить безболезненный переход на новый домен.
Для решения нашей задачи, необходимо добавить в конфиг exim следующий маршрут:

domain_to_domain_redirect:
driver = redirect
allow_fail
allow_defer
domains = domain1
data = ${quote:$local_part}@domain2

теперь вся входящая почта для domain1, будет перенаправляться на domain2.

Tmpfs — предназначена для ускорения работы ОС FreeBSD (монтирования FS, но размещается в ОЗУ вместо HDD), она портированна с NetBSD и впервые входит в состав FreeBSD 7.0.
В основном в UNIX, tmpfs используют для работы с /tmp, так как после перезагрузки все файлы удаляются. Tmpfs динамически использует свободную память.

Первым делом пересоберем ядро с поддержкой tmpfs:

options TMPFS

Если этого делать не охота, включаем модулем ядра:

# echo 'tmpfs_load="YES"'>> /boot/loader.conf

Для монтирования ФС с помощью tmpfs, доступны следующие опции:

     gid — root group id.
uid — root user id.
mode — разрешения в восьмеричном формате.
inodes — максимальное количество дескрипторов.
size — максимального размера (в байтах) для файловой системы.

Заменяем в /etc/fstab, swap на tmpfs:

#/dev/ad6s1e            /tmp            ufs     rw              2       2
 tmpfs                   /tmp            tmpfs   rw,mode=1777    0       0

где в опциях указываем «mode=1777», что означает назначить права «chmod 1777 /tmp» после перезагрузки, иначе MySQL не поднимится. Так же можно указать в опциях размер памяти, который будет выделен под раздел: size=536870912 в байтах:

tmpfs                   /tmp            tmpfs   rw,mode=1777,size=536870912    0       0

После перезагрузки видим, что все удачно примонтировалось:

# df -h
 Filesystem     Size    Used   Avail Capacity  Mounted on
 ...
 tmpfs          1.1G     40K    1.1G     0%    /tmp
 ...

MRTG (Multi Router Traffic Grapher) — это свободное програмное обеспечение,  для визуального мониторинга по SNMP-протоколу. Но в данном примере я буду его использовать для визуализации текущей загрузки интернет канала провайдера.
Continue Reading