|
Ограничение пропускной способности инета у
пользователей
Автор:
lissyara.
Наступил такой интересный момент - порнуха у пользователей
зарезана, приличная часть сайтов развлекательного назначения тоже
заразана, баннеры режутся, короче, зарезано очень и очень много. А
вот потребление траффика больше не снижается :( Народ припугнутый
"драконовскими" методами, типа по 200 мегабайт инета на каждого
протянул недолго - месяца полтора - потом просекли, что если
попросить то включают анлим :( (и, ввиду, дырявости моей памяти,
забывают выключить...) Короче, было принято решение ограничить
скорость работы с инетом. Мера проверенная ещё на старой работе, и
действенная (но там было вообще жестоко - 2kB/s). Можно было
ограничить скорость работы по протоколу HTTP средствами SQUID, но
были отдельные грамотные товарищщи, которые тянули всякий хлам по
ftp - поэтому нужно было зарезать все протоколы, для этого подходил
DUMMYNET.
Сказано - сделано. Для начала правим конфиг ядра, туда надо
добавить поддержку
DUMMYNET, файрволла.
IPFIREWALL #enable ipfirewall (required for dummynet)
IPFIREWALL_VERBOSE #enable firewall output
IPFIREWALL_VERBOSE_LIMIT #limit firewall output
DUMMYNET #enable dummynet operation
NMBCLUSTERS #set the amount of network packet buffers
HZ #set the timer granularity
options IPFIREWALL
options DUMMYNET
options HZ=1000 # strongly recommended
|
После чего пересобираем ядро. Если у Вас до
этого ядро было без файрволла - то будте готовы к тому, что после
перезагрузки он заработает, и в нём будет только одно правило:
Если файрволл есть, то в него надо добавить
следующие строки (в самом верху):
# Сбрасываем ранее установленные правила:
${FwCMD} -f flush
# сбрасываем все pipe
${FwCMD} -f pipe flush
# сбрасываем очереди
${FwCMD} -f queue flush
# DUMMYNET
# учтите - чтобы пакеты не выпадали на трубе из файрволла (типа,
# как на разрешающем правиле) надо поставить переменную sysctl
# net.inet.ip.fw.one_pass в 0 (по дефолту - 1) и внести это в
# файл /etc/sysctl.conf - иначе при перезагрузке потеряется
${FwCMD} add pipe 1 ip from ${IpOut} to ${NetIn}/${NetMask}
${FwCMD} pipe 1 config bw 100Mbit/s
${FwCMD} add pipe 2 ip from ${IpIn} to ${NetIn}/${NetMask}
${FwCMD} pipe 2 config bw 100Mbit/s
# `спецтруба` для мелкиз пакетов типа ack - ибо если они теряются
# то повторные пакеты будут большего размера
${FwCMD} add pipe 3 ip from any to any tcpflags ack iplen 0-128
${FwCMD} pipe 3 config bw 100Mbit/s
# Пропускаем следующие трубы - чтобы мелкие пакеты не лимитировались
# пропускать надо до первого нормального (после труб) правила.
# я ему присвоил жёсткий номер - файрволл раздаёт номера с последнего правила
# (если номер жёстко не задан) с интервалом определяемым переменной sysctl
# net.inet.ip.fw.autoinc_step - по дефолту - 100
${FwCMD} add skipto 39999 ip from any to any tcpflags ack iplen 0-128
# запускаем счётчик
i=4
# цикл по $i
while [ $i != 252 ]
do
# добавляем трубу для IP адреса
${FwCMD} add pipe $i ip from not ${NetIn}/${NetMask} to 192.168.20.${i}
# проверяем - часом не мой ли это IP
if [ $i -eq 13 -o $i -eq 22 ]
then
# мой инет :)))
${FwCMD} pipe $i config bw 100Mbit/s
else
# не мой IP - режем скорость
${FwCMD} pipe $i config bw 64000 bit/s
fi
# увеличиваем $i на единичку
i=$(($i+1))
done
# проверяем временные правила (перед этим правилом возврщаются мелкие
# пакеты в файрволл) :
${FwCMD} add 40000 check-state
# разрешаем всё по интерфейсу lo0 (петля)
${FwCMD} add allow ip from any to any via lo0
|
Где переменные:
${FwCMD} - /sbin/ipfw - собственно IPFW
${NetIn} - 192.168.20.0 - внутренняя сеть
${NetMask} - 24 - маска сети
${IpOut} - 222.222.222.222 - внешний IP
сервака
Вкратце о том, что всё это делает: первые две pipe для того, чтобы не
ограничивалась скорость работы с самим серваком - на нём лежит почта,
кое какие файлы, и естественно от того, что почта принимается со
скоростью 64k никто в восторге не будет, тем более, что внутри офиса
довольно большой документооборот идёт именно по почте. Затем запускаем
цикл по всем IP-шникам (я сделал не одно правило, а целую кучу (больше
200!), чтобы была большая гибкость в использовании - есть люди которым
не надо ничего ограничивать, те же IT-шники, начальство...) В цикле (он
специально сделан не с начала диапазона и не до конца - у меня вверху и
внизу висят серваки - их ограничивать не надо вообще) добавляются
именованые каналы и в зависимости от IP выставляется скорость - в
примере приведено для 2-х адресов - 192.168.20.13 и 192.168.20.22 -
можно сделать не такое жёсткое деление, используя не
else, а elif.
Выглядеть это будет так:
if [ $i -eq 13 -o $i -eq 22 ]
then
${FwCMD} pipe $i config bw 100000000 bit/s
elif [ $i -eq 18 -o $i -eq 38 ]
${FwCMD} pipe $i config bw 128000 bit/s
elif [ $i -eq 55 -o $i -eq 159 -o $i -eq 188 ]
${FwCMD} pipe $i config bw 256000 bit/s
else
${FwCMD} pipe $i config bw 64000 bit/s
fi
|
В этом случае имеем всем скорость 64k, для
адресов
192.168.20.13 и 192.168.20.22 - 100 мегабит,
192.168.20.18 и 192.168.20.38 - 128k,
192.168.20.55, 192.168.20.159 и 192.168.20.188 - 256k.
После чего перезапускаем файрволл следующей командой:
(при условии, что конфиг файрволла у Вас в
файле /etc/rc.firewall). Для просмотра
существующих pipe пользуемся командой
Только не забудьте & в конце - иначе
может так получиться, что старые правила сбросятся, а новые не успеют
примениться (в момент запуска этой команды соединение по ssh почти
всегда обрывается.)
|