Ограничение скорости интерфейса linux

Новичкам про управление шириной канала в Linux

Некоторое время назад меня попросили настроить в удаленном филиале простейшую балансировку трафика. Работают они, бедолаги, через ADSL, и отправка электронных писем большого объема (сканы документов) забивает им весь обратный канал, что приводит к проблемам в работе с офисными онлайн-программами через VPN.
В качестве шлюза у них используется Linux (Fedora). До этого я пару раз видел, как подобная балансировка настраивается через ipfw на FreeBSD, а так как знаю механизм iptables достаточно хорошо, не ожидал особых проблем. Но поискав в Интернете, я был неприятно удивлен тем, что iptables мне тут совсем не помощник. И знания о порядке прохождения пакетов через его таблицы и правила мне почти не пригодятся. Нужно изучать tc из пакета iproute2.

Неожиданно для себя, я потратил два дня, для того чтобы более-менее разобраться в балансировке трафика средствами iproute2. Сначала попалась не самая лучшая для новичка статья про HTB(здесь). Различные примеры из Интернет тоже порой вводили в ступор, так как в них часто не было описания конкретных опций или смысла их применения. Поэтому я и попытался собрать полученные мною знания в одну статью, а главное описать все на доступном для новичков уровне.

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

Бесклассовые дисциплины

Итак, в Linux для управления трафиком каждому сетевому интерфейсу назначается дисциплина (qdisc). Именно из дисциплин и строится вся система управления трафиком. Но пугаться не стоит, на самом деле, дисциплина — это просто алгоритм обработки очереди сетевых пакетов.
Дисциплин на одном интерфейсе может быть задействовано несколько, а непосредственно к интерфейсу крепится так называемая корневая дисциплина (root qdisc). При этом каждый интерфейс имеет свою собственную корневую дисциплину.

prio_fast

По-умолчанию после загрузки системы, root qdisc задает алгоритм обработки пакетов типа pfifo_fast.

qdisc pfifo_fast 0: dev eth0 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

pfifo_fast — это обычный алгоритм “First Input — First Output”, но с некоторой приоритизацией трафика. Дисциплина такого типа содержит внутри себя три очереди FIFO с разным приоритетом обработки пакетов. Пакеты раскладываются по ним на основе флага ToS (Type of Service) в каждом IP-пакете. Пакет попавший в FIFO0 имеет наивысший приоритет к обработке, в FIFO2 — наименьший. Сам ToS требует отдельного разговора, поэтому предлагаю ограничиться тем фактом, что операционная система сама знает какой ToS назначить отправленному IP-пакету. Например, в пакетах telnet и ping ToS будет иметь разные значения.

0: — дескриптор корневой дисциплины.
Дескрипторы должны иметь вид старший_номер: младший_номер, но у дисциплин младший номер всегда должен быть 0, и поэтому его можно опускать.

Параметр priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1, как раз задает побитовое соответствие поля ТоS каждой внутренней очереди (band). Например, при ToS=4, пакет обрабатывается в очереди 1, при ToS=7 в очереди 0.

В ряде источников указано, что параметры дисциплины pfifo_fast нельзя изменить, поверим.

Теперь рассмотрим как можно ограничить скорость общего исходящего трафика. Для этого назначим корневой дисциплиной интерфейса дисциплину типа TBF (Token Bucket Filter).

# tc qdisc add dev eth0 root tbf rate 180kbit latency 20ms buffer 1540

rate 180kbit — устанавливает порог скорости передачи на интерфейсе.

latency 20ms — задает максимальное время нахождения пакета данных в ожидании токена.

buffer 1540 — задаем размер буфера токенов в байтах. В примерах пишут, что для ограничения в 10Мbit/s достаточно буфера на 10Kbytes. Главное не сделать его слишком малого размера, больше можно. Примерная формула расчета: rate_in_Bytes/100.

Дисциплина ТBF для своей работы использует механизм токенов. Токены генерируются системой с постоянной скоростью и помещаются в буфер(bucket). За каждый токен, вышедший из буфера с интерфейса уходит IP-пакет.
Если скорости передачи пакетов и генерации токенов совпадает, процесс передачи данных идет без задержки.
Если скорость передачи пакетов меньше чем скорость токенов, последние начинают накапливаться в буфере и затем могут использоваться для кратковременной передачи данных на скорости выше пороговой.
Если скорость передачи пакетов выше — токенов начинает не хватать. Пакеты данных ожидают новых токенов некоторое время, а затем начинают отбрасываться.

Описанные две дисциплины относятся к так называемым бесклассовым (classless) дисциплинам. Они имеют ряд функциональных ограничений: подключаются только к интерфейсу (либо краевому классу), плюс для них нельзя применять фильтры пакетов. И соответственно мою задачу по балансировке почтового трафика с их помощью решить не удастся.
Кстати, полный набор бесклассовых дисциплин несколько шире: pfifo, bfifo, sqf (обеспечивает одинаковую скорость пакетов поступивших из разных потоков), esqf и т.д.

Классовые дисциплины

Если дисциплины можно представить как отрезки водопроводных труб, то классы — это соединители (фитинги). Это может быть простой фитинг-переходник, а может хитрый фитинг-разветвитель с десятком отводов.

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

Класс, не имеющий дочерних классов, называется краевым (leaf class). Здесь пакеты данных, пробежав по нашему “водопроводу” покидают систему управления трафиком и отправляются сетевым интерфейсом. По-умолчанию, любой краевой класс имеет присоединенную дисциплину типа fifo, и именно она определяет порядок передачи пакетов для этого класса. Но вся прелесть в том, что мы можем поменять эту дисциплину на любую другую.
В случае добавления дочернего класса данная дисциплина удаляется.

Вернемся к задаче по балансировке почтового трафика и рассмотрим классовую дисциплину prio.
Она очень похожа на уже описанную pfifo_fast. Но данная дисциплина особенная тем, что при ее назначении автоматически создается три класса (количество можно менять параметром bands).

Заменим корневую дисциплину интерфейса на prio.

# tc qdisc add dev eth0 root handle 1: prio

handle 1: — задаем дескриптор данной root qdisc. В классовых дисциплинах его затем указывают при подключении классов.

qdisc prio 1: dev eth0 bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

# tc -d -s class show dev eth0

class prio 1:1 parent 1:
Sent 734914 bytes 7875 pkt (dropped 0, overlimits 0 requeues 0)
backlog 0b 0p requeues 0
class prio 1:2 parent 1:
Sent 1555058583 bytes 8280199 pkt (dropped 124919, overlimits 26443 requeues 0)
backlog 0b 0p requeues 0
class prio 1:3 parent 1:
Sent 57934378 bytes 802213 pkt (dropped 70976, overlimits 284608 requeues 0)
backlog 0b 0p requeues 0

Видим три класса с идентификаторами 1:1, 1:2 и 1:3, подключенные к родительской диcциплине 1: типа prio (классы обязаны иметь общий старший_номер идентификатора со своим родителем).
Т.е на “трубу” root qdisc, которая разделяет потоки данных также как это делает pfifo_fast мы насадили тройник. Руководствуясь ToS, в класс 1:1 попадает высокоприоритетный трафик, в класс 1:2 обычный трафик, в класс 1:3 совсем уж «мусор».

Допустим обратный канал ADSL выдает скорость 90Кбайт/c. Разделим его на 20Kбайт/c под почту и 70Kбайт/c на все остальное.

Трафик из класса 1:1 специально ограничивать не будем. Его пакеты всегда смогут занять хоть всю ширину канала из-за высокого приоритета ToS, но объем трафика в этом классе у нас будет ничтожно мал по сравнению с остальными двумя классами. Поэтому отдельную полосу под него не резервируем.

Читайте также:  Двусторонняя печать mac os word

Стандартный трафик, как правило, попадает в класс 1:2. Подключаем ко второму выводу класса-тройника трубу-дисциплину на 70Kбайт/c:

# tc qdisc add dev eth0 parent 1:2 handle 10: tfb rate 70kbps buffer 1500 latency 50ms

На третий вывод тройника подключим трубу-дисциплину на 20Kбайт/c:

# tc qdisc add dev eth0 parent 1:3 handle 20: tfb rate 20kbps buffer 1500 latency 50ms

Все три этих класса краевые.

И теперь осталось только направить почтовый трафик не в класс 1:2, как происходило раньше, а в класс 1:3. Это делается с помощью фильтров классовых дисциплин.

# tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 25 0xffff flowid 1:3

parent 1: — фильтр может крепиться только к дисциплине и вызывается из нее же. На основе срабатывания фильтра дисциплина решает в каком классе продолжится обработка пакета.

protocol ip — определяем тип сетевого протокола

prio 1 — параметр долго вводил меня в замешательство, так как он применяется в классах и фильтрах, плюс это название дисциплины. Здесь prio задает приоритет срабатывания фильтров, первыми задействуются фильтры с меньшим prio.

u32 — так называемый классификатор трафика, который может выполнять отбор пакетов по любому его признаку: по ip-адресу отправителя/получателя, по порту источника/приeмника, по типу протокола. Эти условия, собственно, и указаны далее.

match ip dport 25 0xffff — задает срабатывание фильтра при отправке пакетов на порт 25. 0xffff — это битовая маска для номера порта.

flowid 1:3 — указываем в какой класс передаются пакеты при срабатывании данного фильтра.

Сделано грубо, но задачу выполнит.

Смотрим статистику прохождения пакетов:

# tc -s -d qdisq show dev eth0
# tc -s -d class show dev eth0
# tc -s -d filter show dev eth0

Быстро удалить все классы, фильтры и вернуть root qdisc интерфейса в первоначальное состояние можно командой:

# tc qdisc del dev eth0 root

С другой стороны, у нас и так слишком тонкий обратный канал, чтобы резервировать 20Kбайт/c только под отправку электронной почты. Поэтому здесь лучше использовать классовую дисциплину HTB (Hierarchical Token Bucket). Она позволяет производить заимствование полосы пропускания дочерним классами у родительского.

# tc qdics add dev eth0 root handle 1: htb default 20

default 20 — задаем класс по-умолчанию. В нем будут обрабатываться пакеты, не попавшие в другие классы дисциплины htb. Если его не указать, то будет назначен “default 0” и весь неклассифицированный (непопавший под фильтры) трафик будет отправляться со скоростью интерфейса.

# tc class add dev eth0 parent 1: classid 1:1 htb rate 90kbps ceil 90kbps

прикрепляем к root qdisc класс с идентификатором 1:1. Тем самым ограничиваем скорость на интерфейсе до 90Кбайт/c.

classid 1:1 — идентификатор класса.

rate 90kbps — устанавливаем нижний порог пропускной способности для класса.

ceil 90kbps — устанавливаем верхний порог пропускной способности для класса.

# tc class add dev eth0 parent 1:1 classid 1:10 htb rate 20kbps ceil 70kbps

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

rate 20kbps — устанавливаем гарантированный нижний порог пропускной способности для класса.

ceil 70kbps — устанавливаем верхний порог пропускной способности для класса. В случае если у родительского класса будет свободна полоса пропускания (наличие “лишних” токенов), class 1:10 сможет временно поднять скорость передачи данных, вплоть до указанного предела в 70Кбайт/c.

# tc class add dev eth0 parent 1:1 classid 1:20 htb rate 70kbps ceil 90kbps

Создаем класс по умолчанию. В него будет попадать весь остальной трафик. Точно также, параметрами rate и ceil, задаем расширение пропускной способности в случае отсутствия уже почтового трафика.

# tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 25 0xffff flowid 1:10

фильтр на базе u32, направляющий пакеты исходящие на 25й порт в класс 1:10.

Кстати, в документации указано, что по факту в HTB шейпинг трафика происходит только в краевых классах, в нашем случае 1:10 и 1:20. Указание параметров ограничения полосы пропускания в остальных классах HTB нужно лишь для функционирования системы заимствования между классами.

При добавлении класса также возможно указать параметр prio. Он задает приоритет класса (0 — макс.приоритет). Классы с меньшим приоритетом не обрабатываются пока есть данные в более приоритетных классах.

Источник

Ограничиваем входящий и исходящий трафик в Linux

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

Какие есть способы ограничения трафика?

Для того, чтобы ответить на этот вопрос нужно определиться для чего этот трафик ограничивать вообще.
Взяв за основу мою сеть из, примерно, 50 рабочих мест, которые выходят в интернет через шлюз, под управлением ОС Ubuntu и некоторые из пользователей пользуются локальными ресурсами на этом сервере по протоколу SMB.
Моя цель ограничить пользователям скорость передачи данных в Интернет со справедливым разделением полосы пропускания между ними.

Исходя из моих задач, для ограничения полосы пропускания можно использовать следующие методы:
1. Ограничение с помощью прокси-сервера Squid.
Данный метод позволяет довольно гибко контролировать весь www,ftp трафик пользователей с возможностью гибкого ограничения скорости пропускания.
2. Использование traffic control из iproute2.
Очень гибкий и оптимальный метод ограничения трафика, но не предоставляющий контроля над WWW трафиком, как в предыдущем методе.
3. Конечно возможно ограничить скорость путём использования модуля –m limit для iptables – но считаю это неприемлемым.

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

Как уже упоминал, я использую сервер: OS Ubuntu 10.04, ядро 2.6.32-30. В сервере 3 интерфейса: eth0 – внутренняя сеть, eth1 — провайдер 1, eth2 – провайдер 2.

Задача: ограничить скорость входящего и исходящего трафика пользователей с приоритезацией трафика по классам, исходя из некоторых условий. Локальный трафик не ограничивать.

Представим ситуацию, когда пользователь установил соединение с youtube.com и смотрит какой-нибудь ролик в HD-качестве. Основная часть трафика направляется от сервера, в данном случае youtube.com к пользователю. Учитывая, что весь трафик проходит через наш шлюз, мы можем повлиять на скорость передачи этого трафика путем установки шейпера трафика на интерфейсе внутренней сети.
Похожая ситуация происходит, когда пользователь загружает фотоотчет о проведенном отпуске, состоящий из 300 фотографий в разрешении 5000х3500 пикселей на какой-нибудь сервис хранения фотографий в интернете.

Естественно, что при отсутствии системы ограничения трафика этот пользователь займёт весь канал и остальным пользователям не будет предоставлена нормальная скорость работы с Интернет. Но мы не может ограничить скорость отправки данных пользователем на внешнем интерфейсе сервера, т.к. для доступа пользователей в Интернет используется NAT, а, учитывая, что шейпинг трафика выполняется после преобразования адресов, то на внешнем интерфейсе сервера уже не будет пакетов с внутренними адресами сети.

Читайте также:  Time management для windows

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

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

Исходя из вышеизложенного, я ограничивал входящий к пользователю трафик на интерфейсе внутренней сети — eth0, а исходящий от пользователя трафик – на виртуальном интерфейсе ifb0.

Для того чтобы во время занятия пользователем всей полосы пропускания, ограниченной ему на шлюзе, для скачивания какого-нибудь большого объема данных и при этом мог нормально пользоваться ssh и чтобы у него работал ping – я использовал приоритезацию трафика.

Я расставил следующие приоритеты трафика:

  1. icmp
  2. udp,ssh
  3. tcp sport 80
  4. остальной неклассифицированный трафик

Чем ниже параметр – тем выше приоритет трафика.

Дисциплины, классы, фильтры

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

Для инициализации интерфейса ifb0 нужно сначала загрузить модуль управления интерфейсом:
/sbin/modprobe ifb
После успешной загрузки модуля нужно включить интерфейс:
/sbin/ip link set dev ifb0 up
Затем, после того, как интерфейс будет поднят, нужно организовать переадресацию всего исходящего трафика от пользователей на этот интерфейс:
/sbin/tc qdisc add dev eth0 ingress
/sbin/tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev ifb0
Теперь можно смело начинать строить классы и фильтры для входящего к пользователям трафика на интерфейсе eth0, а исходящего – на интерфейсе ifb0.

Для ограничения трафика используется следующий принцип:

  1. На интерфейсе создается, так называемый корневой обработчик очереди
  2. К этой дисциплине прикрепляется класс, который одержит информацию о максимальной пропускной способности данных, которые в этот класс попадут
  3. Добавляется фильтр, который, с помощью определенных параметров, относит каждый пакет к тому или иному классу

Классы могут быть вложенными. То есть, если класс 1: описывает максимальную пропускную способность в 1Мбит, то класс 1:1, который является его подклассом, не может превысить ограничения по скорости его родителя.

Ограничиваем входящий к пользователям трафик

Все манипуляции с трафиком будем проводить на интерфейсе eth0.

Для начала создадим корневой обработчик очереди на интерфейсе:
/sbin/tc qdisc add dev eth0 root handle 1: htb default 900

Тем самым мы привязали корневой обработчик очереди к интерфейсу eth0, присвоили ему номер 1: и указали на использование планировщика HTB с отправкой всего неклассифицированного трафика в класс с номером 900.

Затем создадим дочерний класс 1:1 с шириной канала, равной скорости интерфейса:
/sbin/tc class add dev eth0 parent 1: classid 1:1 htb rate 100Mbit burst 15k
Все последующие классы будут подклассами только что созданного нами класса. Это дает нам более точную приоритезацию и обработку скорости потока данных.

Создадим класс для локального трафика, адресом назначения или исходным адресом которого будет являться внутренний адрес сервера. Это нужно для удобства пользования ресурсами сервера, такими как SSH, SMB, FTP, WWW и так далее. Скорость, описанная классом – 50Mbit, но в случае, если скорость потока родительского класса не меньше 100Mbit, то разрешаем использовать 80Mbit, в качестве максимальной скорости передачи данных.
/sbin/tc class add dev eth0 parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

Далее создаем класс, скорость которого будет равно ширине полосы пропускания, которую нам предоставляет провайдер. В моем случае – это 15Mbit.
/sbin/tc class add dev eth0 parent 1:1 classid 1:100 htb rate 15Mbit burst 15k

Даже если провайдер предоставляет большую скорость, к примеру 18Mbit, я рекомендую снижать эту скорость для шейпера на 1-2 Mbit для более «мягкого» ограничения трафика.
Далее создадим класс, в который будут отправляться все пакеты данных, которые не попадут ни в один из созданных ранее классов.
/sbin/tc class add dev eth0 parent 1:1 classid 1:900 htb rate 56Kbit ceil 128Kbit

Для каждого пользователя я создавал отдельный подкласс, с выделенной полосой пропускания, а затем создавал подклассы этого класса для приоритезации трафика:
/sbin/tc class add dev eth0 parent 1:100 classid 1:101 htb rate 4Mbit ceil 6Mbit

Данной командой мы указали на создание класса с номером 1:101, который является подклассом класса с номером 1:100 и указали пропускную способность класса в 4Mbit, а в случае свободной полосу пропускания у родительского класса, разрешить максимальное прохождение данных по классу на скорости 6Mbit.

Далее создаем подклассы для приоритезации трафика:
# PRIO 1 -> icmp traffic — самый низкий приоритет
/sbin/tc class add dev eth0 parent 1:101 classid 1:102 htb rate 33kbit ceil 6Mbit prio 1
# PRIO 2 -> udp, ssh
/sbin/tc class add dev eth0 parent 1:101 classid 1:103 htb rate 33kbit ceil 6Mbit prio 2
# PRIO 3 -> tcp sport 80 – WWW трафик из мира
/sbin/tc class add dev eth0 parent 1:101 classid 1:104 htb rate 33kbit ceil 6Mbit prio 3
# PRIO 4 -> unclassified traffic – трафик, который не попал под условия, указанные в предыдущих классах
/sbin/tc class add dev eth0 parent 1:101 classid 1:105 htb rate 33kbit ceil 6Mbit prio 4

После создания классов пришло время создания фильтров, которые будут классифицировать трафик по определенным критериям.

Есть несколько способов классифицировать трафик.
Самые удобные из них – это u32 классификаторы, позволяющие классифицировать пакеты исходя из адреса назначения или отправителя, используемого протокола, номера порта и так далее, и классификаторы на основе меток iptables. Для использования последних необходимо сначала маркировать пакеты при помощи iptables в цепочке PREROUTING, на основе каких-либо условий, а затем при помощи tc направлять пакеты с соответствующей меткой в нужные классы.

Я предпочел использовать u32 классификатор.

Присваиваем icmp-трафику самый низкий приоритет и отправляем его в класс 1:102
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 192.168.10.78 \
match ip protocol 1 0xff flowid 1:102

UDP и SSH трафик отправляем в класс 1:103
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 192.168.10.78 \
match ip protocol 17 0xff flowid 1:103
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 192.168.10.78 \
match ip protocol 6 0xff match ip sport 22 0xffff flowid 1:103

WWW-трафик, пришедший с tcp-порта 80 отправляем в класс 1:104
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dst 192.168.10.78 \
match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:104

Трафик, не соответствующий ни одному из условий отправляем в класс 1:105
/sbin/tc filter add dev eth0 protocol ip parent 1:0 prio 4 u32 match ip dst 192.168.10.78 flowid 1:105

Приоритезация работает по такому принципу, что каждому классу выделяется по минимальной полосе пропускания с возможностью заимствования у родительского класса максимальной полосы пропускания, в зависимости от приоритета трафика, поэтому, если класс будет забит WWW-трафиком с tcp-порта 80, при прохождении icmp пакета с более низким приоритетом, чем у WWW-трафика, он будет пропущен вне очереди, учитывая его приоритет.

Читайте также:  Что работает быстрее линукс или виндовс

Ограничиваем исходящий трафик

Для ограничения исходящего от пользователей трафика выполняются такие же действия как и для входящего, только в ход идет виртуальный интерфейс ifb0. Также нужно изменить назначение следования трафика: вместо dst 192.168.10.78 – нужно указать src 192.168.10.78 соответственно.

Автоматизация и принцип работы скриптов

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

Файл представляет из себя поля, разделенный знаком табуляции либо пробелом со следующими значениями:
CLIENT – Имя пользователя. Нужно для удобства предоставления данных
IP – адрес пользователя в сети
DOWN – скорость потока данных к пользователю
CEIL – максимальная скорость входящего трафика к пользователю при доступности данной полосы у родительского класса
UP — скорость потока данных от пользователя
CEIL – то же, что и у CEIL для входящего трафика к пользователю
PROVIDER – какой из провайдеров используется для обслуживания запросов пользователя (при наличии нескольких)
ID – номер класса для пользователя. Подробнее о номерах классов ниже.
Также я использую несколько bash-скриптов.

root@steel:/etc/rc.d/shape# cat ./rc.shape

#!/bin/bash
. /etc/init.d/functions
/sbin/modprobe ifb
/sbin/ip link set dev ifb0 up

TC=»/sbin/tc»
DEV_P1_DOWN=»eth0″
DEV_P1_UP=»ifb0″

stop() <
$TC qdisc del dev $DEV_P1_DOWN root
$TC qdisc del dev $DEV_P1_UP root
$TC qdisc del dev $DEV_P1_DOWN ingress
>
start() <
# Удаляем все обработчики на интерфейсе
$TC qdisc del dev $DEV_P1_DOWN root
$TC qdisc del dev $DEV_P1_UP root
$TC qdisc del dev $DEV_P1_DOWN ingress

## Перенаправляем весь исходящий от пользователей трафик на виртуальный интерфейс ifb0
$TC qdisc add dev $DEV_P1_DOWN ingress
$TC filter add dev $DEV_P1_DOWN parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $DEV_P1_UP

# Подгружаем скрипты с описанием классов входящего и исходящего трафика

# Весь трафик, который следует на шлюз или от него ограничиваем в 50Мбит с максимумом в 80Мбит.
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 1 u32 match ip dst 10.0.0.1 flowid 1:10
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 1 u32 match ip src 10.0.0.1 flowid 1:10

# Подгружаем скрипт с описанием фильтров
. /etc/rc.d/shape/rc.shape.filters
>

Далее код, который подгружается:

root@steel:/etc/rc.d/shape# cat ./rc.shape.down.classes

#!/bin/bash
## DOWNLOAD CLASSES
##########################################################
# Создаем корневой обработчик очереди
$TC qdisc add dev $DEV_P1_DOWN root handle 1: htb default 900

# Описание классов для входящего к пользователям трафика
$TC class add dev $DEV_P1_DOWN parent 1: classid 1:1 htb rate 100Mbit burst 15k

# Локльный трафик (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

# Трафик от провайдера (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:100 htb rate 15Mbit burst 15k

# Неклассифицированный трафик будет отправлен в этот класс (SERVER -> CLIENTS)
$TC class add dev $DEV_P1_DOWN parent 1:1 classid 1:900 htb rate 128Kbit ceil 128Kbit

root@steel:/etc/rc.d/shape# cat ./rc.shape.up.classes
#!/bin/bash

## UPLOAD CLASSES
#############################################################
# Создаем корневой обработчик очереди
$TC qdisc add dev ifb0 root handle 1: htb default 900

# Описание классов для исходящего от пользователей трафика
$TC class add dev ifb0 parent 1: classid 1:1 htb rate 100Mbit burst 15k
# Локальный трафик (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:10 htb rate 50Mbit ceil 80Mbit burst 15k

# Трафик к провайдеру (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:100 htb rate 5Mbit burst 15k
# Неклассифицированный трафик будет отправлен в этот класс (CLIENTS -> SERVER)
$TC class add dev $DEV_P1_UP parent 1:1 classid 1:900 htb rate 128Kbit ceil 128Kbit

root@steel:/etc/rc.d/shape# cat ./rc.shape.filters
#!/bin/bash
# читаем построчно файл “users”
while read LINE
do
set — $LINE
if [[ $1 =

# создаем отдельный подкласс для пользователя
$TC class add dev $DEV_P1_DOWN parent 1:100 classid 1:$<8>1 htb rate $CLIENT_DOWN_RATE ceil $CLIENT_DOWN_CEIL

# PRIO 1 -> icmp traffic
$TC class add dev $DEV_P1_DOWN parent 1:$<8>1 classid 1:$<8>2 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 1

# PRIO 2 -> udp, ssh
$TC class add dev $DEV_P1_DOWN parent 1:$<8>1 classid 1:$<8>3 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 2

# PRIO 3 -> tcp sport 80
$TC class add dev $DEV_P1_DOWN parent 1:$<8>1 classid 1:$<8>4 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 3

# PRIO 4 -> unclassified traffic
$TC class add dev $DEV_P1_DOWN parent 1:$<8>1 classid 1:$<8>5 htb rate 33kbit ceil $CLIENT_DOWN_CEIL prio 4

# фильтруем icmp-пакеты в ранее созданный нами класс для icmp-трафика с приоритетот 1
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 1 u32 match ip dst $CLIENT_IP \
match ip protocol 1 0xff flowid 1:$<8>2

# фильтрация udp
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 2 u32 match ip dst $CLIENT_IP \
match ip protocol 17 0xff flowid 1:$<8>3
# ssh
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 2 u32 match ip dst $CLIENT_IP \
match ip protocol 6 0xff match ip sport 22 0xffff flowid 1:$<8>3
# WWW, sport 80
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 3 u32 match ip dst $CLIENT_IP \
match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:$<8>4
# самый высокий приоритет – трафику, не попавшему под предыдущие фильтры
$TC filter add dev $DEV_P1_DOWN protocol ip parent 1:0 prio 4 u32 match ip dst $CLIENT_IP flowid 1:$<8>5

### ТАКИЕ ЖЕ ПРАВИЛА И ДЛЯ ИСХОДЯЩЕГО ТРАФИКА

$TC class add dev $DEV_P1_UP parent 1:100 classid 1:$<8>1 htb rate $CLIENT_UP_RATE ceil $CLIENT_UP_CEIL
# PRIO 1 -> icmp traffic
$TC class add dev $DEV_P1_UP parent 1:$<8>1 classid 1:$<8>2 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 1
# PRIO 2 -> udp, ssh
$TC class add dev $DEV_P1_UP parent 1:$<8>1 classid 1:$<8>3 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 2
# PRIO 3 -> unclassified traffic
$TC class add dev $DEV_P1_UP parent 1:$<8>1 classid 1:$<8>4 htb rate 1kbit ceil $CLIENT_UP_CEIL prio 3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 1 u32 match ip src $CLIENT_IP \
match ip protocol 1 0xff flowid 1:$<8>2
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 2 u32 match ip src $CLIENT_IP \
match ip protocol 17 0xff flowid 1:$<8>3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 2 u32 match ip src $CLIENT_IP \
match ip protocol 6 0xff match ip dport 22 0xffff flowid 1:$<8>3
$TC filter add dev $DEV_P1_UP protocol ip parent 1:0 prio 3 u32 match ip src $CLIENT_IP flowid 1:$<8>4

Данные скрипты нужно положить в один каталог, Выполнить:

chmod +x ./rc.shape

Я описал один из методов ограничения трафика. Утилита tc – очень мощная вещь в вопросах об ограничениях трафика. Рекомендую ознакомиться с документом: LARTC-HOWTO для более глубокого изучения данного вопроса.

Источник

Оцените статью