Мы — долго запрягаем, быстро ездим, и сильно тормозим.
www.lissyara.su —> статьи —> FreeBSD —> настройка —> DUMMYNET

Ограничение пропускной способности инета у пользователей

Автор: 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

После чего пересобираем ядро. Если у Вас до этого ядро было без файрволла - то будте готовы к тому, что после перезагрузки он заработает, и в нём будет только одно правило:
deny all from any to any

Если файрволл есть, то в него надо добавить следующие строки (в самом верху):
# Сбрасываем ранее установленные правила:
${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.
После чего перезапускаем файрволл следующей командой:
sh /etc/rc.firewall &

(при условии, что конфиг файрволла у Вас в файле /etc/rc.firewall). Для просмотра существующих pipe пользуемся командой
ipfw pipe show

Только не забудьте & в конце - иначе может так получиться, что старые правила сбросятся, а новые не успеют примениться (в момент запуска этой команды соединение по ssh почти всегда обрывается.)



размещено: 2005-11-29,
последнее обновление: 2006-05-18,
автор: lissyara


PomidorOFF, 2006-07-26 в 16:38:06

src/share/examples/ipfw/change_rules.sh
стандартный скрипт перезапуска фаервола, ssh не рвется если правила написаны верно, и не разрывается соединение. ;)

paha, 2006-09-21 в 13:10:16

а так не проще?
/etc/rc.d/ipfw forcerestart . ни разу SSh не рвалось.

ztaz, 2006-10-20 в 3:53:48

А не проще ничего не выводить при обновлении правил?
FwCMD="/sbin/ipfw -q"
Тогда ничего и не будет разрывать...

sticker, 2006-11-25 в 18:46:55

Про обрывание соединений при изменении настроек ipfw тоже пережмвал, пока не узнал об
/usr/ports/sysutils/screen/
Даже не представляю теперь как жиз без этого раньше :)

Trias, 2007-02-10 в 13:07:30

еще достаточно удобно делать ограничения используя возможности IPFW2, а точнее ipfw table

в 5.х и 6.х уже по дефолту а 4.х надо пересобирать ядро.

тоесть например

ipfw add 2 pipe 1 ip from any to table\(1\) in
pipe 1 config bw 300Kbit/s mask dst-ip 0xffffffff

ipfw add 2 pipe 2 ip from table\(1\) to any
pipe 2 config bw 300Kbit/s mask src-ip 0xffffffff

если пользователь заносится в таблицу 1 то он будет иметь ограничение по 300/300 на каждого. уберем ( mask dst-ip 0xffffffff ) в pipe и будет на всех в таблице =)

Andrey74, 2007-04-15 в 21:01:05

А после elif не нужен then?

Zaq, 2007-05-14 в 14:45:30

ну и не плохо добовлять in/out для правил, дабы избежать превращения 128 в 64, может это конечно только при наличии natd но всёже более чёткое правило будет
pipe 1 ip from 10.0.0.109 to any in
pipe 1 ip from any to 10.0.0.109 out

pipe 1 config bw 128kbit/s mask src-ip 0xffffffff
pipe 2 config bw 128kbit/s mask dst-ip 0xffffffff
правда, зачем плодить пайпы ))

zOrg, 2007-06-01 в 15:34:04

Попробовал, действительно теребует после elif  then!!!  Фря  6.2

ma4o, 2007-09-12 в 14:34:40

Вот что искал нигде не мог внятного ответа найти про "sh /etc/rc.firewall &", точнее про амперсанд в конце. А то по удаленке перегружаешь правила и все колом встает пока в локаль не залезешь. Да и сама статья полезная.

ADvise, 2008-04-29 в 6:25:58

Господа, я так понимаю, это все мы проделываем ручками.

скажем, вот хочу так, дошел юзер до предела, скажем 200 мб выкачал, и все, хочу ему или инет отрезать или скорость такой сделать, что ему все желание отбивает пользоваться инетом. но скажем я на месте бываю раз в три месяца.

скажем, по юзеру можно узнать, сколько он накачал, но как правила на лету править... или подставлять в командной строке адрес и в крон?

Из статьи лишь понятно, что мы просто жестко определяем скорость конкретным пользователям. и все.

может сделать следующее:
1. смотрим число - 1 число, разрешаем максимальную допустимую скорость всем.
2. не 1 число, смотрим статистику юзера, >200 мб накачал, вызываем файрвол с параметром (адрес юзера), урезаем скорость.
3. и можно ему об этом еще письмом сообщить, что мол лимит достигнут имейте совесть, тра-ля-ля.

Алексей, 2008-09-02 в 9:52:57

А если юзвери ходят в инет через прозрачный проксик... а остальной трафик через NAT. Ограничить таким образом ширину канала для них возможно?

Croaker, 2008-09-08 в 15:46:14

В первом конфиге есть строка
${FwCMD} add pipe 2 ip from ${IpIn} to
а сама переменная IpIn не опеределена

vesper, 2009-03-14 в 1:17:01

А для DUMMYNET В FreeBSD 7.1 ничего не будет? О:-) там много нового появилось.. а инфы мало

dr_alf, 2009-05-21 в 10:20:30

${FwCMD} pipe $i config bw 64000 bit/s
у меня с пробелом неработало) я особенный или в разных версиях фри, разные требования? ))))

denis-k, 2010-01-23 в 3:56:09

Народ, статья все еще актуальна? Например, для 8-ки.

Морфин, 2010-03-25 в 7:34:14

А можно же сделать
rdr on $int_if proto tcp from \\\"192.168.20.0/24\\\" to any port www -> 127.0.0.1 port 3128
и аналогично для FTP и скомпилить SQUID под поддержку pf

Товарищщи!, 2010-04-01 в 21:58:29

 Товарищщи!  Это поля для ввода комментариев к статье, а не для вопросов. Сюда пишите найденные баги, или какие-то фичи :)
Для вопросов есть форум!

beerdy, 2011-09-22 в 17:12:53

День добрый.
Есть ВОТ это:
${FwCMD} add pipe 2 ip from ${IpIn} to ${NetIn}/${NetMask}
${FwCMD} pipe 2 config bw 100Mbit/s
Для чего? Что за IpIn?

Мфынф, 2013-10-22 в 17:12:15

АФТАР ЕБЛАН СОСИ ХУЙ!!!!!!!!!!!11111111111



 

  Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
  Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

© lissyara 2006-10-24 08:47 MSK

Время генерации страницы 0.1734 секунд
Из них PHP: 46%; SQL: 54%; Число SQL-запросов: 77 шт.
Исходный размер: 36939; Сжатая: 9612