Потребовалось мне как то ограничить пользователей по скорости выхода в интернет. В моем распоряжении был роутер на linux машине. Первое что пришло на ум — это прокси-сервер, но он не полностью удовлетворял потребностям, так как ограничивал только web-трафик и пользователи программками типа DC забивали весь канал. Стал искать дальше, какими средствами linux можно ограничить трафик. Нашел утилиту tc входящую в состав пакета iproute2. На сервере весь трафик пользователей натится(nat), eth0 — интерфейс который смотрит в интернет, eth1 — интерфейс локальной сети. Все ограничение трафика сделано на интерфейсе локальной сети.
Начнем:
1) # Удаляем настройки корневого класса
/sbin/tc qdisc del dev eth1 root
/sbin/tc qdisc del dev eth1 ingress
2) # Создаем корневой класс со скоростью общего входящего канала в 1000 mbit
/sbin/tc qdisc add dev eth1 root handle 1:0 cbq avpkt 1000 bandwidth 1000mbit
Здесь:
dev eth1 - это устройство, к которому мы подключаем дисциплину обработки очереди
root - указывает что это корневая дисциплина
handle 1:0 - задается дескриптор в форме старший номер:младший номер (допускается использовать «1:» - при этом подразумевается что младший номер равен 0)
cbq - указываем тип дисциплины обработки очереди
avpkt - определяет усредненный размер пакета. Для ethernet-интерфейсов можно считать его равным 1000 байт при MTU равном 1500 байтам.
Bandwidth - физическая пропускная способность нашего устройства
3) # Создаем корневой класс для исходящего канала
/sbin/tc qdisc add dev eth1 handle ffff: ingress
4) # Создаем класс с шириной канала 15200kbit
/sbin/tc bounded class add dev eth1 parent 1: classid 1:1 cbq rate 15200kbit allot 1500 prio 5 bounded isolated
Здесь:
classid — для classid младший номер должен быть уникальным!!! (то есть число после двоеточия)
rate — этот параметр задает ограничение полосы пропускания
prio — присваивает классам приоритеты — чем меньше значение, тем выше приоритет
bounded — обозначает что классу запрещается занимать свободную полосу пропускания других классов, настроенных с параметром sharing
isolated — обозначает что другие классы на смогут занять полосу этого класса, даже если она будет свободна
5) # Классифицируем трафик с помощью фильтров и направляем его в нужные классы
/sbin/tc filter add dev eth1 parent 1: protocol ip prio 16 u32 match ip dst 192.168.0.10 flowid 1:1
Здесь:
u32 — это классификатор, позволяющий классифицировать пакеты на основании их атрибутов
flowid - задает дескриптор класса, куда направляются пакеты соответствующие заданному фильтру
6) # Для более равномерного распределения пропускной способности между соединениями, присоединим к классу дисциплину обработки очереди SFQ
/sbin/tc qdisc add dev eth1 parent 1:1 sfq perturb 10
sfq — дисциплина для более равномерного распределения пропускной способности между соединениями
perturb — этот параметр задает интервал в секундах, через который происходит изменение функции
7) # Этой командой мы будем контролировать резкое увеличение трафика
/sbin/tc filter add dev eth1 parent ffff: protocol ip prio 50 u32 match ip src 192.168.0.10/32 police rate 15200Kbit burst 15564800 drop flowid 1:1
burst — контролирует реакцию на резкое увеличение трафика
C 4-го по 7-ой пункт выполняем для каждого ip-адреса
Посмотреть что получилось можно с помощью команды /sbin/tc -s qdisc ls dev eth1
Вот скрипт для двух IP-адресов с разной скоростью интернета:
#!/bin/bash
/sbin/tc qdisc del dev eth1 root
/sbin/tc qdisc del dev eth1 ingress
/sbin/tc qdisc add dev eth1 root handle 1: cbq avpkt 1000 bandwidth 1000mbit
/sbin/tc qdisc add dev eth1 handle ffff: ingress
/sbin/tc class add dev eth1 parent 1: classid 1:1 cbq rate 15200kbit allot 1500 prio 5 bounded isolated
/sbin/tc filter add dev eth1 parent 1: protocol ip prio 16 u32 match ip dst 192.168.0.10 flowid 1:1
/sbin/tc qdisc add dev eth1 parent 1:1 sfq perturb 10
/sbin/tc filter add dev eth1 parent ffff: protocol ip prio 50 u32 match ip src 192.168.0.10/32 police rate 15200Kbit burst 15564800 drop flowid 1:1
/sbin/tc class add dev eth1 parent 1: classid 1:2 cbq rate 400kbit allot 1500 prio 5 bounded isolated
/sbin/tc filter add dev eth1 parent 1: protocol ip prio 16 u32 match ip dst 192.168.0.101 flowid 1:2
/sbin/tc qdisc add dev eth1 parent 1:2 sfq perturb 10
/sbin/tc filter add dev eth1 parent ffff: protocol ip prio 50 u32 match ip src 192.168.0.101/32 police rate 400Kbit burst 409600 drop flowid 1:2