Динамический шейпер траффика (dummynet + PF + mrtg)
Необходимо было настроит динамический шейпер для локальной сети. Выбор стал между 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 ~]#