Пятница, 2024-11-08, 3:02 PM
 
Начало Форум Регистрация Вход
Вы вошли как Гость
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Модератор форума: denix  
Управление трафиком на роутере небольшой сети под Linux
denixДата: Четверг, 2006-06-29, 1:49 AM | Сообщение # 1
Admin
Группа: Администраторы
Сообщений: 531
Репутация: 0
Статус: Offline
Подключился я однажды к adsl и обнаружил, что хотя у него неплохие
характеристики 8/1 mbit in/out, но бывают ситуации, когда разные потоки
трафика начинают мешать работе, играм... Даже пинг до гейта поднимался с
8ms до 200-300ms. Усугубляло ситуацию, что я был не единственным пользователем
этого подключения. Т.е. я вдруг могу (хотя и нежелательно) притормозить выкачивание
чего-то, когда хочется поиграть в quake, но что делать с другими пользователями?
Зарезать их на время игры - это конечно сильно smile но нежелательно. Неудобно даже
свои процессы постоянно прибивать/запускать. Ну и просто портится КПД канала. Ради
нескольких процентов трафика и минимальных лагов убивать все остальное... Поэтому
начал копать то, что наваяли в линуксе для разделения траффика по приоритетам и
ограничения полосы. Применил это для роутера, который подключен в интернет через
adsl модем и раздает его пользователям через какой-то сетевой интерфейс (у меня
их несколько и они объединены в виртуальный интерфейс bridge). Хотя это можно
применять и для других ситуаций с некоторыми изменениями.

И результат этого представляю вам на растерзание smile

Для ограничения трафика я решил использовать только входящие в стандартное
ядро (2.4, 2.6) модули. Это QoS, netfilter и стандартны пакеты для работы с
ядром, входящие в большиство дистрибутивов iproute2, iptables. Для большинства
случаев этого достаточно.

Эксперименты показали, что эффективно управлять потоками пакетов можно только
при неполной загрузке канала в обоих направлениях. Т.е. нужно ограничить скорость
канала. Это очень важно! Достаточно забить одно направление на 100% и качество
связи упадет. Решать что важнее: ограничить пропускную способность канала на 10-30%
или маяться с лагами в момент, когда он полностью забит - личное дело каждого.
Я описываю метод с ограничением скорости канала.

Теперь совсем немного теории. Мы не можем управлять входящим трафиком, который
поступает adsl модему на вход. И это факт. Но большинство ip потоков зависят
от исходящего трафика и от дропания или задержки пакетов. Именно ip, а не
только tcpip. Так пишут во всех руководствах. Но я не буду управлять входящим
трафиком через задержку исходящего, как обычно советуют. Не потому что это
невозможно, а потому что это сложно и требуется долгая настройка, а потом и
постоянная подстройка.

Например: тянем что-то по ftp. Входящий трафик 8mbit, а исходящий всего 200kbit,
что в разы меньше пропускной способности исходящего канала. Т.е. для ограничения
входящего ftp трафика надо сделать исходящий меньше 200kbit. Но это только
примерная величина и её нужно подгонять. А ситуация может меняться...

Есть еще один важный момент: adsl модем - устройство с разной пропускной способностью
для исходящих и входящих пакетов. Поэтому нужно ограничивать исходящий с роутера
или сети трафик даже в том случае, если он не является подтверждением для входящих
потоков. Например, поставили у себя какой-то ftp/www/игровой сервер, а так же в сети
могут жить любители пирингового обмена. И своим небольшим (в 10 раз меньше входящего)
трафиком они могут сильно испортить качество канала. Значит нужно делить исходящий
трафик на исходящий с хоста или сети и подтверждение входящих пакетов.

Будем решать эту проблему в лоб, т.е. ограничивать исходящий трафик для исходящих
потоков отдельно и входящий для входящих тоже отдельно smile Для примера берем мою сеть.
ppp0 - интерфейс для выхода в интернет
br0 - интерфейс локальной сети

На ppp0 будем контролировать только исходящий трафик и все ограничения делать
исходя из скорости передачи adsl модема наружу. Политику ограничений строить так,
чтобы не забить исходящий канал и только. Кроме некоторых особых ситуаций.

На br0 будем контролировать тоже только исходящий трафик (стандартная
реализация QoS в линуксе не позволяет делать это для исходящего). Но т.к. это
маршрутизатор, то это будет и контроль входящего на ppp0 траффика smile

В обоих направлениях траффик делится на несколько каналов с разным уровнем
приоритета. Каждая канал имеет свою минимальную гарантированную полосу
пропускания и максимальную, доступную в случае, когда канал не занят более
приоритетным траффиком.

Если вы используете стандартное ядро из дистрибутива, то скорее всего все
нужное уже есть в модулях к нему и можете не читать следующий параграф.

Настройка ядра

Для тех, кто собирает ядра сам, я дам общие советы. Вряд ли они нуждаются в
разжевывании до мелочей smile Я буду давать названия для ядра 2.6. Для 2.4
используются аналогичные, но с другими путями. Сам я пользуюсь для конфигурации
командой make menuconfig и поэтому все будет описываться именно для этого
варианта конфигурации, но для случая make xconfig разницы никакой.

В первую очередь нужно разрешить

Device Drivers -> Networking support -> Networking options -> QoS and/or fair queueing

дальше делаем модулями или вставляем в ядро следующие модули:

HTB packet scheduler
SFQ queue
Packet classifier API
Firewall based classifier (NEW)
U32 classifier

Остальное на ваше усмотрение. Это минимальный набор для ограничения трафика.

От слов к делу. Вот пример скрипта поблочно, с комментариями после каждого блока.

запускается как
adsl_qos {start|stop|status} ppp_интерфейс адрес_интерфейса

#!/bin/sh

DEV_OUT=$2
IP=$3
QLEN_OUT=10
RATE_OUT=650
MTU_OUT=1400

DEV_IN=br0
RATE_IN=6000
QLEN_IN=1000

RATE_LOCAL=100mbit
IP_LOCAL=10.0.0.1

ICMP="match ip protocol 1 0xff"
TCP="match ip protocol 6 0xff"
UDP="match ip protocol 17 0xff"
DPORT="match ip dport"
SPORT="match ip sport"
SRC="match ip src"
DST="match ip dst"
U32="protocol ip u32"

Сделано это для запуска из ip-up/ip-down скрипта ppp.
xxx_OUT - относится к adsl интерфейсу, исходящему потоку.
xxx_IN - относится к интерфейсу локальной сети, но входящему на adsl модем
потоку smile

Ставлю ограничение 650kbit для исходящего потока и 6000kbit для входящего.

status(){

echo "[qdisc out]"
tc -s -d qdisc show dev $DEV_OUT
echo
echo "[class out]"
tc -s -d class show dev $DEV_OUT
echo
echo "[filter out]"
tc -s filter show dev $DEV_OUT
echo

echo "-----------------------------------------------------------------"
echo "[qdisc in]"
tc -s -d qdisc show dev $DEV_IN
echo
echo "[class in]"
tc -s -d class show dev $DEV_IN
echo
echo "[filter in]"
tc -s filter show dev $DEV_IN
exit
}

Без комментариев

stop(){

tc qdisc del dev $DEV_OUT root 2> /dev/null > /dev/null
tc qdisc del dev $DEV_IN root 2> /dev/null > /dev/null
}

Сбрасываю все в начальное состояние

start_out(){

ip link set dev $DEV_OUT qlen $QLEN_OUT mtu $MTU_OUT

tc qdisc add dev $DEV_OUT root handle 1: htb default 17
tc class add dev $DEV_OUT parent 1: classid 1:1 htb rate ${RATE_OUT}kbit

tc class add dev $DEV_OUT parent 1:1 classid 1:10 htb rate $[$RATE_OUT/8]kbit ceil $[$RATE_OUT/3]kbit prio 0
tc class add dev $DEV_OUT parent 1:1 classid 1:11 htb rate 20kbit prio 1
tc class add dev $DEV_OUT parent 1:1 classid 1:12 htb rate $[$RATE_OUT/8]kbit ceil $[$RATE_OUT/3]kbit prio 2
tc class add dev $DEV_OUT parent 1:1 classid 1:13 htb rate $[$RATE_OUT/8]kbit ceil $[$RATE_OUT/3]kbit prio 3
tc class add dev $DEV_OUT parent 1:1 classid 1:14 htb rate $[$RATE_OUT/8]kbit ceil $[$RATE_OUT/3]kbit prio 4
tc class add dev $DEV_OUT parent 1:1 classid 1:15 htb rate $[$RATE_OUT/8]kbit ceil ${RATE_OUT}kbit prio 5
tc class add dev $DEV_OUT parent 1:1 classid 1:17 htb rate $[$RATE_OUT/8]kbit ceil ${RATE_OUT}kbit prio 7

Разделил исходящий трафик на 8 полос с разным приоритетом и разной пропускной способностью
каждой полосы. Одну полосу (classid 1:16) пока ничем не занял - резерв.

rate - гарантированная полоса пропускания.

ceil - максимальная, если очереди с более высоким приоритетом незагружены

prio - приоритет полосы. 0 - максимальный

остальную абракадабру вычитывайте в документации

Еще один момент. Трафик, не попадающий в полосы 1:10 - 1:16, по умолчанию идет в 1:17

 
denixДата: Четверг, 2006-06-29, 1:50 AM | Сообщение # 2
Admin
Группа: Администраторы
Сообщений: 531
Репутация: 0
Статус: Offline
Ниже будут заданы фильтры, которые направляют пакеты в нужные полосы (классы).

Прошу обратить внимание на prio. Чем меньше, тем выше. Это не имеет отношения
к приоритету полос. Это приоритет для выборки пакета фильтром. Иначе может
получиться, что сначала отработает

tc filter add dev $DEV_OUT parent 1:0 $U32 $UDP classid 1:13

а

tc filter add dev $DEV_OUT parent 1:0 $U32 $DPORT 53 0xffff classid 1:12

будет сосать лапу smile

Я сделал несколько простых макросов, чтобы задание правил не было таким громоздким.

0xffff после порта - маска. Например, 22 0xfffe позволяет ловить и 23 порт
Все условия, которые задаются в одной команде, работают как AND.

tc filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $DPORT 53 0xffff classid 1:12

Важный момент. Тут не отслеживается тип пакета. Формат udp и tcp пакета
одинаковый в самом начале и поэтому можно проверять условие на dest port сразу
для этих двух протоколов.

tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $SPORT 22 0xfffe classid 1:10
tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $SPORT 222 0xfffe classid 1:10
tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $SPORT 2200 0xfffe classid 1:10
tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $DPORT 22 0xfffe classid 1:10
tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $DPORT 222 0xfffe classid 1:10
tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $TCP $DPORT 2200 0xfffe classid 1:10

Самым приоритетным для меня считаются исходящие соединения на внешние ssh/telnet сервера.
К тому же я использую нестандартные порты типа 222, 2200 Так же хочу, чтобы эти
же сервисы, которые подняты на роутере, были доступны снаружи без тормозов.
Выше стоит максимальное ограничение скорости в 1/3. Нечего забивать
канал всякими scp и sftp !

tc filter add dev $DEV_OUT parent 1:0 prio 1 $U32 $ICMP classid 1:11

Пусть пингается с максимальным качеством, но не более 30-50 пакетов в секунду (20kbit/8/60).
Нечего флудить!

tc filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $SPORT 53 0xffff classid 1:12
tc filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $DPORT 53 0xffff classid 1:12

Пропускаю тут запросы к днс серверам наружу. Так же у меня есть днс сервер на хосте
и он должен отвечать на запросы. С таким приоритетом маркировать пакеты для своих любимых
сетевых игр, именно поэтому максимальная скорость разрешена в 1/3
например:

tc filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $UDP $DPORT 27505 0xffff classid 1:12
tc filter add dev $DEV_OUT parent 1:0 prio 2 $U32 $TCP $DPORT 4000 0xffff classid 1:12

tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $UDP classid 1:13

Все прочие udp пакеты. Возможно, некоторые пиринговые сети будут жить в этой полосе.
Но в основном для игрушек, которые не попали в более приоритетную полосу.

tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $DPORT 3389 0xffff classid 1:14
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $SPORT 3389 0xffff classid 1:14

Хочу использовать rdp на внешних серверах без сильных тормозов, но и не хочу
мешать игрушкам. Так же есть некий компьютер в локальной сети, на который можно
зайти по rdp снаружи. Где-то в другом скрипте сделан dnat.

tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $DPORT 80 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $DPORT 443 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $DPORT 3128 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $DPORT 8080 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $SPORT 25 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $SPORT 80 0xffff classid 1:15
tc filter add dev $DEV_OUT parent 1:0 prio 3 $U32 $TCP $SPORT 443 0xffff classid 1:15

Веб серфинг пусть получит приоритет повыше. Сюда же добавлять icq, irc, smtp, pop3 ...
Тут же ограничиваю свои веб и почтовые сервисы. Приоритет выше, чем у пакетов
по умолчанию.

tc qdisc add dev $DEV_OUT parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:11 handle 11: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:12 handle 12: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:13 handle 13: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:14 handle 14: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:15 handle 15: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:17 handle 17: sfq perturb 10

echo "Outbound shaping added to $DEV_OUT. Rate: ${RATE_OUT}Kbit/sec."
}

К каждому классу добавляются алгоритмы обработки очереди
можно вместо sfq выбрать другой тип очереди, например esfq
esfq не входит в стандартное ядро и поэтому нужно устанавливать этот
модуль отдельно (http://fatooh.org/esfq-2.6/)

Процедура для ограничения исходящего трафика закончена.

start_in(){

ip link set dev $DEV_IN qlen $QLEN_IN

tc qdisc add dev $DEV_IN root handle 1: htb default 17

tc class add dev $DEV_IN parent 1: classid 1:1 htb rate ${RATE_IN}kbit
tc class add dev $DEV_IN parent 1:1 classid 1:10 htb rate $[$RATE_IN/8]kbit prio 0
tc class add dev $DEV_IN parent 1:1 classid 1:11 htb rate $[$RATE_IN/8]kbit prio 1
tc class add dev $DEV_IN parent 1:1 classid 1:12 htb rate $[$RATE_IN/8]kbit ceil $[$RATE_IN/3]kbit prio 2
tc class add dev $DEV_IN parent 1:1 classid 1:13 htb rate $[$RATE_IN/8]kbit ceil $[$RATE_IN/3]kbit prio 3
tc class add dev $DEV_IN parent 1:1 classid 1:14 htb rate $[$RATE_IN/8]kbit ceil $[$RATE_IN/3]kbit prio 4
tc class add dev $DEV_IN parent 1:1 classid 1:15 htb rate $[$RATE_IN/8]kbit ceil ${RATE_IN}kbit prio 5
tc class add dev $DEV_IN parent 1:1 classid 1:17 htb rate $[$RATE_IN/8]kbit ceil ${RATE_IN}kbit prio 7

Примерно тоже самое, только этот интерфейс работает с локальной сетью.

tc class add dev $DEV_IN parent 1: classid 1:2 htb rate $RATE_LOCAL prio 7


Через этот класс пропускается не транзитный с adsl модема траффик, а исходящий
с роутера, поэтому используется другой, более высокий rate

tc filter add dev $DEV_IN parent 1:0 prio 1 $U32 $SRC $IP_LOCAL classid 1:2

а это фильтр для него

tc filter add dev $DEV_IN parent 1:0 prio 2 $U32 $TCP $SPORT 22 0xfffe classid 1:10
tc filter add dev $DEV_IN parent 1:0 prio 2 $U32 $TCP $SPORT 222 0xffff classid 1:10
tc filter add dev $DEV_IN parent 1:0 prio 2 $U32 $TCP $SPORT 2200 0xffff classid 1:10
tc filter add dev $DEV_IN parent 1:0 prio 2 $U32 $ICMP classid 1:11
tc filter add dev $DEV_IN parent 1:0 prio 2 $U32 $SPORT 53 0xffff classid 1:12
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $UDP classid 1:13
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $SPORT 3389 0xffff classid 1:14
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $DST 10.0.0.100 $DPORT 3389 0xffff classid 1:14
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $SPORT 80 0xffff classid 1:15
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $SPORT 443 0xffff classid 1:15
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $SPORT 3128 0xffff classid 1:15
tc filter add dev $DEV_IN parent 1:0 prio 3 $U32 $TCP $SPORT 8080 0xffff classid 1:15

Тут используются обычно src port вместо dst port, потому что это входящий трафик.
Хотя никто не мешает вам сделать другие политики и наслаждаться бардаком smile

tc qdisc add dev $DEV_IN parent 1:2 handle 2: pfifo

Использую самую простую и легкую для процессора очередь pfifo для исходящего
с роутера трафика (не транзитный!)

tc qdisc add dev $DEV_OUT parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:11 handle 11: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:12 handle 12: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:13 handle 13: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:14 handle 14: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:15 handle 15: sfq perturb 10
tc qdisc add dev $DEV_OUT parent 1:17 handle 17: sfq perturb 10

echo "Outbound shaping added to $DEV_OUT. Rate: ${RATE_OUT}Kbit/sec."
}

Процедура для ограничения входящего трафика закончена.

case "$1" in
start)
stop
start_in
start_out
;;

stop)
stop
echo "Shaping removed on $DEV_OUT/$DEV_IN."
;;

status)
status
;;

*)
echo "Usage: $0 {start|stop|status} ppp_interface ip"
esac

Теперь добавляем в /etc/ppp/ip-up

что-то типа:

if [ $4 = "1.2.3.4" ]; then
/etc/iproute2/rt_add $5 # это у меня создаются дополнительные таблицы и маршруты роутинга
# для локальной сети и для самого роутера для своих, особых целей
/etc/ppp/adsl_qos start $1 $4
fi

в /etc/ppp/ip-down:

if [ $4 = "1.2.3.4" ]; then
/etc/iproute2/rt_del $5
/etc/ppp/adsl_qos stop $1 $4
fi

Проверку можно и не делать, но у меня еще есть и dialup сервер smile и/или
туннель на pppd

Все. Если циферки RATE_IN/RATE_OUT подобраны правильно, то максимальная пропускная
способность канала пострадает не сильно, но зато высокоприоритетные потоки
не будут лагать даже при сильной загрузке в обоих направлениях одновременно.
Скорость входящих потоков реально зажимается без прямого воздействия на
исходящие и дропы пакетов минимальны. Скорее всего это происходит из-за
притормаживания пакета в очереди. Разумеется, от флуда это не спасет, но эти
случаи лечат обычно административными методами.

Если критично, что ограничиваются пакеты на интерфейсе локальной сети,
то нужно ставить IMQ модуль и переносить обработку с $DEV_IN на интерфейс imq#

Часть информации и заготовка для скрипта взято отсюда:
http://gazette.linux.ru.net/rus....to.html

Другие полезные ссылки по QoS:
http://www.lartc.org
http://gazette.linux.ru.net/rus/articles/taleLinuxTC.html
http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm

tcp, udp пинг. Самое то для проверки работы QoS:
http://wiki.hping.org/

imq модуль для создания виртуального интерфейса. Появляется возможность обрабатывать
входящий трафик на ppp устройстве, а не на интерфейсе локальной сети:
http://www.linuximq.net/

esfq алгоритм обработки очереди. Полезен, когда нужно распределить канал
примерно поровну между пользователями, вне зависимости от того, сколько каждый
из них использует потоков. Давить наглых регетчиков-многопоточников!!! smile
http://fatooh.org/esfq-2.6/

Разные полезные модули. В том числе для борьбы с p2p:
http://kem.p.lodz.pl/~peter/qnet/

Мониторинг сетевой активности:
http://iptraf.seul.org/

 
  • Страница 1 из 1
  • 1
Поиск:


Бесплатный хостинг uCoz