Еще один пост про управление трафиком с помощью tc в Linux

Во многих дистрибутивах, ориентированных на роутеры (openwrt, dd-wrt, ipcop & etc) есть встроенная поддержка . Однако, такой «из коробки» не гибок и адаптирован под интернет-тарифы «цивилизованных» стран, с постоянной скоростью доступа. В нашей же социалистической реальности скорость ночью может быть в 2 раза больше чем днем и терять этот бонус жалко.

В этой записи я попробую привести пример рабочего решения для управления приоритетами трафика в с помощью и .

В первую очередь определимся с переменными:

 LAN_IFACE="eth0" WAN_IFACE="eth1" GLOB_RATE="1000mbit" LAN_RATE="100mbit" H=`/bin/date +%H` if [ $H -gt 2 ] && [ $H -lt 8 ]; then WAN_RATE="11060kbit" WAN_BW="1024kbit" else WAN_RATE="2765kbit" WAN_BW="512kbit" fi LAN_NET="192.168.0.0/24" LOCAL_NETS="10.0.0.0/8 172.16.0.0/16" 

В данной секции показан пример увеличения скорости доступа в интернет с 2-х ночи до 8-ми утра. Переменные:
LAN_IFACE — сетевой интерфейс смотрящий в локальную сеть
WAN_IFACE — сетевой интерфейс смотрящий в интернет
LAN_RATE — скорость локальной сети
H — текущий час суток
WAN_RATE — скорость подключения к сети интернет (для того чтобы QoS работал, -10% от реальной скорости)
WAN_BW — минимальная гарантированная скорость для того или иного класса трафика.
LAN_NET — локальная сеть.
LOCAL_NETS — диапазоны адресов провайдера, ограничение скорости на которые не распространяется.

Создаем основные планировщики пакетов и классы для входящего трафика:

 # Root qdsc tc qdisc del dev $LAN_IFACE root 2> /dev/null > /dev/null tc qdisc add dev $LAN_IFACE root handle 1:0 htb default 106 tc class add dev $LAN_IFACE parent 1:0 classid 1:1 htb rate $GLOB_RATE \ burst 20k # Speed for lan traffic tc class add dev $LAN_IFACE parent 1:1 classid 1:2 htb rate $LAN_RATE \ burst 10k prio 6 tc qdisc add dev $LAN_IFACE parent 1:2 handle 2: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 6 protocol ip handle 2 fw \ classid 1:2 # Speed for inet traffic tc class add dev $LAN_IFACE parent 1:1 classid 1:10 htb rate $WAN_RATE \ burst 6k prio 3 

Настал черед для исходящего трафика:

 # Root qdsc tc qdisc del dev $WAN_IFACE root 2> /dev/null > /dev/null tc qdisc add dev $WAN_IFACE root handle 1:0 htb default 106 tc class add dev $WAN_IFACE parent 1:0 classid 1:1 htb rate $GLOB_RATE \ burst 20k # Speed for lan traffic tc class add dev $WAN_IFACE parent 1:1 classid 1:2 htb rate $LAN_RATE \ burst 10k prio 6 tc qdisc add dev $WAN_IFACE parent 1:2 handle 2: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 6 protocol ip handle 2 fw \ classid 1:2 # Speed for inet traffic tc class add dev $WAN_IFACE parent 1:1 classid 1:10 htb rate $WAN_RATE \ burst 6k prio 3 

Теперь создаем 6 классов трафика разного приоритета:

 ### Prio 1 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:101 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 1 tc qdisc add dev $LAN_IFACE parent 1:101 handle 101: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 1 protocol ip handle 101 fw \ classid 1:101 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:101 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 1 tc qdisc add dev $WAN_IFACE parent 1:101 handle 101: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 1 protocol ip handle 101 fw \ classid 1:101 ### Prio 2 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:102 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 2 tc qdisc add dev $LAN_IFACE parent 1:102 handle 102: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 2 protocol ip handle 102 fw \ classid 1:102 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:102 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 2 tc qdisc add dev $WAN_IFACE parent 1:102 handle 102: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 2 protocol ip handle 102 fw \ classid 1:102 ### Prio 3 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:103 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 3 tc qdisc add dev $LAN_IFACE parent 1:103 handle 103: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 3 protocol ip handle 103 fw \ classid 1:103 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:103 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 3 tc qdisc add dev $WAN_IFACE parent 1:103 handle 103: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 3 protocol ip handle 103 fw \ classid 1:103 ### Prio 4 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:104 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 4 tc qdisc add dev $LAN_IFACE parent 1:104 handle 104: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 4 protocol ip handle 104 fw \ classid 1:104 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:104 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 4 tc qdisc add dev $WAN_IFACE parent 1:104 handle 104: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 1 protocol ip handle 104 fw \ classid 1:104 ### Prio 5 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:105 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 5 tc qdisc add dev $LAN_IFACE parent 1:105 handle 105: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 5 protocol ip handle 105 fw \ classid 1:105 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:105 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 5 tc qdisc add dev $WAN_IFACE parent 1:105 handle 105: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 5 protocol ip handle 105 fw \ classid 1:105 ### Prio 6 # Incoming tc class add dev $LAN_IFACE parent 1:10 classid 1:106 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 6 tc qdisc add dev $LAN_IFACE parent 1:106 handle 106: sfq perturb 10 tc filter add dev $LAN_IFACE parent 1:0 prio 6 protocol ip handle 106 fw \ classid 1:106 # Outgoing tc class add dev $WAN_IFACE parent 1:10 classid 1:106 htb rate $WAN_BW \ ceil $WAN_RATE burst 2k prio 6 tc qdisc add dev $WAN_IFACE parent 1:106 handle 106: sfq perturb 10 tc filter add dev $WAN_IFACE parent 1:0 prio 6 protocol ip handle 106 fw \ classid 1:106 

Итак, мы имеем 6 классов трафика, от 1 (максимальный приоритет) до 6 (минимальный приоритет). По-умолчанию весь трафик имеет 6-ой, минимальный приоритет.

С помощью iptables разложим трафик по классам, для этого создадим специальную цепочку — qos_tc:

 # Delete Chains iptables -t mangle -D POSTROUTING -o $LAN_IFACE -j qos_tc iptables -t mangle -D PREROUTING -i $LAN_IFACE -j qos_tc iptables -t mangle -F qos_tc iptables -t mangle -X qos_tc iptables -t mangle -F iptables -t mangle -X # Create Chain iptables -t mangle -N qos_tc iptables -t mangle -I POSTROUTING -o $LAN_IFACE -d $LAN_NET -j qos_tc iptables -t mangle -I PREROUTING -i $LAN_IFACE -s $LAN_NET -j qos_tc # ICMP iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -p icmp -j MARK \ --set-mark 101 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -p icmp -j MARK \ --set-mark 101 # ACK & Other small packets iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -p tcp -m length \ --length :64 -j MARK --set-mark 101 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -p tcp -m length \ --length :64 -j MARK --set-mark 101 # DNS iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -p tcp --dport 53 \ -j MARK --set-mark 101 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -p tcp --sport 53 \ -j MARK --set-mark 101 iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -p udp --dport 53 \ -j MARK --set-mark 101 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -p udp --sport 53 \ -j MARK --set-mark 101 # Web-client iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -m multiport -p tcp \ --dports 80,443 -j MARK --set-mark 104 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -m multiport -p tcp \ --sports 80,443 -j MARK --set-mark 104 # IM-client && SSH-Client iptables -t mangle -A qos_tc -s $LAN_NET ! -d $LAN_NET -m multiport -p tcp \ --dports 22,5190,5222,5223 -j MARK --set-mark 103 iptables -t mangle -A qos_tc -d $LAN_NET ! -s $LAN_NET -m multiport -p tcp \ --sports 22,5190,5222,5223 -j MARK --set-mark 103 # LAN-to-LAN iptables -t mangle -A qos_tc -s $LAN_NET -d $LAN_NET -j MARK --set-mark 1 iptables -t mangle -A qos_tc -d $LAN_NET -s $LAN_NET -j MARK --set-mark 1 # Poviders nets for net in $LOCAL_NETS; do iptables -t mangle -A qos_tc -s $net -d $LAN_NET -j MARK --set-mark 2 iptables -t mangle -A qos_tc -d $net -s $LAN_NET -j MARK --set-mark 2 done 

С таким шейпированием трафика можно безболезненно пользоваться IM, SSH и серфить в интернете имея при этом десятки активных торрентов. Полоса пропускания будет автоматически выделяться под более приоритетные классы трафика по мере необходимости.

В некоторых Embedded-дистрибутивах (например openwrt) для работоспособности скрипта может потребоваться вручную загрузить соответствующие модули ядра:

 insmod ip_queue 2> /dev/null > /dev/null insmod sch_htb 2> /dev/null > /dev/null insmod sch_sfq 2> /dev/null > /dev/null insmod cls_u32 2> /dev/null > /dev/null insmod sch_ingress 2> /dev/null > /dev/null insmod cls_fw 2> /dev/null > /dev/null insmod ipt_TOS 2> /dev/null > /dev/null insmod sch_prio 2> /dev/null > /dev/null 

Скачать скрипт целиком: qos_tc.sh