Доброго дня!
Занялся вопросом шейпинга трафика на роутере. Суть такова: 2 интернет-канала и 1 локалка. Первый канал основной, второй - резервный, при падении одного автоматом переключается на другой, с этим проблем нет.
Нужно ограничить входящий и исходящий трафик на обоих интерфейсах интернет-каналов. Иначе говоря, чтобы сам роутер не качал и не отдавал используя весь канал. Также нужно динамическое распределение полосы пользователям за NATом, иначе говоря, трафика который форвардится.
Много читал, много думал, много пробовал. В итоге дошел вот до чего:
[console]
#!/bin/sh
###################
#
# Traffic shaping
#
###################
#
# Settings
#
# TC utility location
TC="/sbin/tc"
# Local network
LOCAL_IF="vlan10"
LOCAL_RATE="100mbit"
# Provider 1
P1_IF="vlan11"
P1_RATE="4096kbit"
# Provider 2
P2_IF="vlan12"
P2_RATE="2048kbit"
# Rates
INET_RATE="1024kbit"
CEIL_RATE="1280kbit"
P2P_RATE="128kbit"
[/console]
Переменные, все думаю понятно. 2 провайдера, один каналом 2 мбит, другой 4 мбит, локалка 100 мбит. Общая скорость интернета 1 мбит с возможностью разгона до 1280 кбит, скорость для торрентов, качалок и прочих неизвестных портов 128 кбит.
Про дисциплины очередей почитал, понял что такое. В скрипте удаляем если они уже имеются и заново добавляем:
[console]
#
# Delete existing disciplines
#
$TC qdisc del dev $LOCAL_IF root
$TC qdisc del dev $P1_IF root
$TC qdisc del dev $P2_IF root
#
# Add queueing disciplines
#
$TC qdisc add dev $LOCAL_IF root handle 1: htb
$TC qdisc add dev $P1_IF root handle 1: htb
$TC qdisc add dev $P2_IF root handle 1: htb
[/console]
Я предпочел дисциплицы HTB (Hierarchical Token Bucket) основываюсь на документации и отзывах.
Я вроде даже более менее сообразил и в плане создания классов трафика:
[console]
#
# Add classes
#
# Local net
$TC class add dev $LOCAL_IF parent 1: classid 1:1 htb rate $LOCAL_RATE
$TC class add dev $LOCAL_IF parent 1:1 classid 1:10 htb rate $INET_RATE ceil $CEIL_RATE prio 1
$TC class add dev $LOCAL_IF parent 1:1 classid 1:20 htb rate $P2P_RATE ceil $P2P_RATE prio 2
# Provider 1
$TC class add dev $P1_IF parent 1: classid 1:1 htb rate $P1_RATE
$TC class add dev $P1_IF parent 1:1 classid 1:10 htb rate $INET_RATE ceil $CEIL_RATE prio 1
$TC class add dev $P1_IF parent 1:1 classid 1:20 htb rate $P2P_RATE ceil $P2P_RATE prio 2
# Provider 2
$TC class add dev $P2_IF parent 1: classid 1:1 htb rate $P2_RATE
$TC class add dev $P2_IF parent 1:1 classid 1:10 htb rate $INET_RATE ceil $CEIL_RATE prio 1
$TC class add dev $P2_IF parent 1:1 classid 1:20 htb rate $P2P_RATE ceil $P2P_RATE prio 2
[/console]
И понял что для динамического распределения каналов мне необходимы дисциплины SFQ для классов.
[console]
#
# Add additional disciplines
#
# Local net
$TC qdisc add dev $LOCAL_IF parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $LOCAL_IF parent 1:20 handle 20: sfq perturb 10
# Provider 1
$TC qdisc add dev $P1_IF parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $P1_IF parent 1:20 handle 20: sfq perturb 10
# Provider 2
$TC qdisc add dev $P2_IF parent 1:10 handle 10: sfq perturb 10
$TC qdisc add dev $P2_IF parent 1:20 handle 20: sfq perturb 10
[/console]
Где-то еще вычитал что для более менее равномерного распределения полосы сгодятся оные команды.
[console]
#
# Add filters
#
# Local net
$TC filter add dev $LOCAL_IF parent 10: protocol ip handle 10 flow hash keys dst divisor 256
$TC filter add dev $LOCAL_IF parent 20: protocol ip handle 20 flow hash keys dst divisor 256
# Provider 1
$TC filter add dev $P1_IF parent 10: protocol ip handle 10 flow hash keys dst divisor 256
$TC filter add dev $P2_IF parent 20: protocol ip handle 20 flow hash keys dst divisor 256
# Provider 2
$TC filter add dev $P2_IF parent 10: protocol ip handle 10 flow hash keys dst divisor 256
$TC filter add dev $P2_IF parent 20: protocol ip handle 20 flow hash keys dst divisor 256
[/console]
Судя по всему определяет как очереди SFQ обрабатывать запросы.
И все, понеслись запарки в плане установки фильтров трафика, маркираторов и пр.
Сейчас использую iptables с вот таким вот конфигом:
[console]
#
# FORWARD Chain
#
# Other
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P1_IFACE -j CLASSIFY --set-class 1:20
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P2_IFACE -j CLASSIFY --set-class 1:20
$IPT -t mangle -A FORWARD -i $P1_IFACE -o $LOCAL_IFACE -j CLASSIFY --set-class 1:20
$IPT -t mangle -A FORWARD -i $P2_IFACE -o $LOCAL_IFACE -j CLASSIFY --set-class 1:20
# ICMP
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P1_IFACE -p icmp -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P2_IFACE -p icmp -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P1_IFACE -o $LOCAL_IFACE -p icmp -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P2_IFACE -o $LOCAL_IFACE -p icmp -j CLASSIFY --set-class 1:10
# TCP
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P1_IFACE -p tcp -m multiport --dport 20,21,22,25,53,80,110,143,443,995,3389,4899,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P2_IFACE -p tcp -m multiport --dport 20,21,22,25,53,80,110,143,443,995,3389,4899,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P1_IFACE -o $LOCAL_IFACE -p tcp -m multiport --sport 20,21,22,25,53,80,110,143,443,995,3389,4899,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P2_IFACE -o $LOCAL_IFACE -p tcp -m multiport --sport 20,21,22,25,53,80,110,143,443,995,3389,4899,5190,5222 -j CLASSIFY --set-class 1:10
# UDP
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P1_IFACE -p udp -m multiport --dport 53,123,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $LOCAL_IFACE -o $P2_IFACE -p udp -m multiport --dport 53,123,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P2_IFACE -o $LOCAL_IFACE -p udp -m multiport --sport 53,123,5190,5222 -j CLASSIFY --set-class 1:10
$IPT -t mangle -A FORWARD -i $P2_IFACE -o $LOCAL_IFACE -p udp -m multiport --sport 53,123,5190,5222 -j CLASSIFY --set-class 1:10
[/console]
Но по-моему это как-то коряво, стопудово можно эту конструкцию сделать куда компактней и удобней. Плюс это только маркировка трафика для форвардинга. Как мне ограничить трафик на внешних интерфейсах для самого роутера?
Господа, был бы очень признателен если бы кто-нибудь подробно объяснил формирование фильтров для трафика средствами tc, iptables и пр.
Я уже просто замучился.
Нужна помочь в реализации динамического шейпинга
Можно установить IMQ и efsq (процесс описан здесь http://www.volmed.org.ru/wiki/index.php/Наложение_патчей_IMQ,_ESFQ_и_Layer7 ).
Использование виртуальных интерфейсов даст возможность резать трафик в одной точке по каждому направлению вне зависимости от интерфейсов физических и логических. Например можно пропустить входящий трафик для внутренних сетей через IMQ0:
iptables -t mangle -A POSTROUTING -d 172.20.0.0/16 -j IMQ --todev 0
iptables -t mangle -A POSTROUTING -d 192.168.0.0/16 -j IMQ --todev 0
iptables -t mangle -A POSTROUTING -d 172.21.0.0/16 -j IMQ --todev 0
что даст возможность перераспределять неиспользуемую полосу между разными внутренними сетями. Также можно по разному настроить несколько интерфейсов IMQ1, IMQ2 .. для реализации, например, режима день/ночь.
В сторону кождого провайдера - тоже по IMQ.
EFSQ позволит раз и навсегда забыть про гемор с маркировкой пакетов по портам.
Вот пример:
tc qdisc del dev imq0 root
tc qdisc add dev imq0 root handle 1:0 htb default 11
tc class add dev imq0 parent 1:0 classid 1:1 htb rate 8mbit ceil 8mbit burst 32k
tc class add dev imq0 parent 1:1 classid 1:10 htb rate 6mbit ceil 8mbit burst 32k
tc class add dev imq0 parent 1:1 classid 1:11 htb rate 2mbit ceil 6mbit burst 128k
tc qdisc add dev imq0 parent 1:10 handle 40: esfq perturb 10 hash dst
tc qdisc add dev imq0 parent 1:11 handle 50: esfq perturb 10 hash dst
В последних двух строках hash dst - задается "справедливое" распределение трафика по ip адресам юзеров.
Для исходящего трафика аналогично используется hash src.
Дальше закидываем фильтром трафик пользователей в 10 класс и всё.
Да, еще каждому отдельно можно отрезать скорость в пределах разумного:
tc filter add dev imq0 parent 1:0 prio 1 protocol all u32 match ip dst 192.168.18.0/26 flowid 1:10 police rate 3mbit burst 512k drop
Параметром burst можно определьсть количество трафика, скачиваемого без ограничения скорости, что положительно скажется на веб-серфинге. При болшом числе юзеров фильры можно огранизовать в хэш.
И да, можно еще огранизовать борьбу с uTP протоколом http://forum.nag.ru/forum/index.php?showtopic=55025&st=140