## Управление трафиком и шейпинг трафика

### Tom Eastep

### Arne Bernin

Copyright © 2001-2007 Thomas M. Eastep

Copyright © 2005 Arne Bernin & Thomas M. Eastep

Copyright © 2007 Russian Translation: Grigory Mokhin

Этот документ разрешается копировать, распространять и/или изменять при выполнении условий лицензии GNU Free Documentation License версии 1.2 или более поздней, опубликованной Free Software Foundation; без неизменяемых разделов, без текста на верхней обложке, без текста на нижней обложке. Копия лицензии приведена по ссылке “GNU Free Documentation License”.

2020/09/24

### Important

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

### Warning

Иначе говоря, чтение только документации Shorewall не будет достаточным для понимания раскрываемых здесь тем.

Как минимум, потребуется обратиться к следующим дополнительным источникам:

- LARTC HOWTO: http://www.lartc.org

- Руководство по HTB: http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm

- Некоторые документы с сайта http://www.netfilter.org/documentation/index.html#documentation-howto. Рекомендуем ознакомиться с очень хорошим руководством Оскара Андреассона.

- Вывод команды man iptables

## Введение

Начиная с версии 2.5.5 в Shorewall реализована встроенная поддержка управления трафиком и шейпинга трафика. В более ранних версиях эти возможности были ограниченными. Можно было использовать собственный сценарий tcstart (это можно и сейчас), но, за исключением файла tcrules, в файлах конфигурации Shorewall не была предусмотрена возможность определения классов и дисциплин очередей.

До сих пор поддержка управления трафиком является неполной, например, не поддерживаются все опции (и особенно различные алгоритмы очередей) из ядра Linux, но для большинства случаев она будет достаточной. Если у вас уже есть сценарий для управления трафиком, который вы собираетесь использовать и в будущем, то соответствующие инструкции приведены по ссылке ниже в этом документе. Для того чтобы это заработало, требуется включить поддержку управления трафиком в ядре и в Shorewall, как описано далее.

## Управление трафиком и шейпинг трафика в Linux

В этом разделе кратко описано, как работает управление трафиком в Linux. Даже если этого должно быть достаточно для настройки управления трафиком в файлах конфигурации Shorewall, мы очень рекомендуем внимательно прочитать руководство Linux Advanced Routing and Shaping HOWTO. Во время написания этого документа текущей версией была 1.0.0.

Начиная с версии 2.2, в Linux реализованы полные возможности управления трафиком. Предусмотрены различные алгоритмы, которые применяются для приоритизации очередей пакетов, выходящих с интерфейса. Стандартный алгоритм называется pfifo, и, как следует из самого названия, это очередь типа первым пришел - первым ушел. Фактически при этом никакого управления трафиком не происходит, и если какое-то соединение забивает весь канал, то этот алгоритм не сможет этого предотвратить.

Для управления трафиком в Shorewall используются два алгоритма, HTB (иерархический набор маркеров) и SFQ (очередь с равноправным стохастическим упорядочением). SFQ использует простую схему: отслеживаются все соединения (tcp или udp), и трафик распределяется между ними. Обычно это работает хорошо. HTB позволяет определить набор классов, между которыми распределяется трафик. Для каждого класса можно указать минимальную и максимальную полосу пропускания, а сами классы упорядочить в иерархическую структуру, чтобы классы с меньшим приоритетом получали доступ к каналу только в том случае, если запросы более важных классы удовлетворены. Встроенные функции управления трафиком в Shorewall позволяют определить такие классы и указать для них полосу пропускания. Внутри самих классов используется SFQ, чтобы их различные внутренние потоки данных обрабатывались как равноправные.

Управлять можно только исходящим трафиком. Причина этого состоит в том, что входящие пакеты уже пришли на сетевую плату, и нужно решить, что с ними делать. Их можно только сбросить, но особого смысла в этом не будет, поскольку пакет уже пришёл, пройдя через узкое место - входящий канал. Следующим узким местом может быть интерфейс, с которого уходит этот пакет, и именно на нём может образовываться очередь. Поэтому определение очередей для входящих пакетов не будет особенно полезным, эти пакеты просто нужно передать как можно быстрее на исходящий интерфейс.

Есть одно исключение. Если ограничить входящий трафик значением чуть меньшим, чем фактическая пропускная способность канала, то будет исключено образование очередей на другом конце соединения. Это бывает полезно, если управление потоком на другом конце канала невозможно, а сам он подключен к сети по более быстрому каналу, например, если вы подключены к провайдеру по кабельному модему или модему DSL, а маршрутизатор провайдера подключен к быстрому магистральному каналу. Поэтому, если отбрасывать слишком быстро приходящие пакеты, то основной протокол сможет это обнаружить и снизить скорость соединения. В TCP такой механизм встроен, в UDP не встроен, но протокол, работающий поверх UDP, может иметь такой механизм.

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

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

Управление исходящим трафиком достигается посредством распределения потока пакетов по классам. Класс связан ровно с одним сетевым интерфейсом и имеет ряд атрибутов:

1. PRIORITY - используется для указания приоритетов классов, к которым относятся отправляемые пакеты. Приоритет - это число, при этом 1 задаёт наивысший приоритет, 2 - следующий по важности и т.д.

2. RATE - скорость, то есть минимальная гарантированная пропускная способность, которая должна обеспечиваться для класса, когда возрастает нагрузка на канал. Классы с более высоким приоритетом (меньшие значения PRIORITY) обслуживаются даже в том случае, если заданы другие классы с гарантированной пропускной способностью, но низшим приоритетом (большие значения PRIORITY).

3. CEIL - ограничение, максимальная полоса пропускания, которая отводится для класса, когда канал свободен.

4. MARK - метка. В Netfilter предусмотрены способы маркировки пакетов. Метки пакетов - это числа. В Shorewall они могут принимать значение от 1 до 255. Метки пакетов присваиваются различным типам пакетов согласно правилам, заданным в файле `/etc/shorewall/tcrules`.

Для каждого интерфейса необходимо задать один класс, который будет классом по умолчанию. К этому классу будут относиться непомеченные данные, то есть пакеты, для которых не задана метка в файле `/etc/shorewall/tcrules`.

Netfilter также поддерживает метки соединений. Метки соединений можно присвоить соединениям в правилах `/etc/shorewall/tcrules`, можно скопировать метку пакета в метку соединения (SAVE), или скопировать метку соединения в метку пакета (RESTORE).

## Конфигурация ядра Linux

Для работы требуется ядро не ниже 2.4.18. На рисунке показаны опции ядра, которые необходимо включить. Для встроенной поддержки необходимы опции HTB scheduler, Ingress scheduler, PRIO pseudoscheduler и SFQ queue. Прочие планировщики или алгоритмы очередей необязательны.

Также требуются классификаторы u32 и fw из главного меню Networking Options (не показаны).

На следующем рисунке показано, как я настроил QoS у себя в ядре 2.6.13:

Конфигурация ядра изменилась в 2.6.16 -- вот мои рекомендации.

## Включение поддержки TC в Shorewall

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

Для включения встроенных функций управления трафиком в Shorewall выполните следующее:

- Задайте TC_ENABLED равным "Internal" в /etc/shorewall/shorewall.conf. Если TC_ENABLED=Yes, то Shorewall будет искать внешний файл tcstart (см. далее).

- Если задать параметр CLEAR_TC в /etc/shorewall/shorewall.conf равным Yes, то при запуске, перезапуске и остановке Shorewall будет сбрасываться текущая конфигурация управления трафиком. Обычно именно это и требуется при работе с встроенными функциями, а также с собственным сценарием tcstart.

- Следующие действия зависят от того, применяются ли встроенные функции или собственный сценарий. Подробнее это объясняется в следующих разделах.

## Работа с встроенными функциями управления трафиком и шейпинга

Встроенные в Shorewall функции управления трафиком - это тонкая оболочка для очереди входящих пакетов (ingress qdisc), HTB и SFQ. Эта оболочка позволяет выполнить следующие задачи:

- Определить классы HTB в файлах конфигурации Shorewall.

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

- Распределить пакеты по классам HTB согласно значениям TOS.

- Отнести исходящие пакеты TCP ACK к классу HTB.

- Распределить пакеты по классам HTB согласно значениям меток пакетов.

### Warning

Встроенные в Shorewall функции управления трафиком ограничены десятью (10) устройствами.

Больше никаких задач встроенные функции управления трафиком не выполняют. Поэтому, чтобы их использовать, необходимо понимать, как работает HTB и управление трафиком в Linux, и как работают метки пакетов Netfilter. За дополнительной информацией обратитесь к ссылкам, приведенным в начале этого документа.

Для задания пропускной способности (как устройств, так и классов) используйте kbit или kbps (для килоБАЙТ в секунду) БЕЗ пробела между числом и единицей измерения (то есть 100kbit НО НЕ 100 kbit). Можно также использовать mbit, mbps или число (означающее байты), но поддерживаются только целые числа (0.5 использовать нельзя).

Для того чтобы правильно настроить устройства, необходимо выяснить фактическую пропускную способность канала в обоих направлениях. Это особенно важно для соединений DSL или любых других, для которых пропускная способность канала не гарантирована. Не верьте числам, которые называет провайдер, но сами измерьте реальную скорость канала. В этом могут помочь различные утилиты в сети, попробуйте поискать "dsl speed test" в google (для Германии можно использовать arcor speed check). Найдите тест поближе к себе.

### /etc/shorewall/tcdevices

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

Далее описаны столбцы файла:

- INTERFACE - Имя интерфейса. Интерфейс может быть указан не более одного раза. Использовать псевдоним интерфейса (например, eth0:0) здесь нельзя, см. FAQ #18. Также нельзя использовать символы подстановки, например, если есть несколько интерфейсов ppp, то все их необходимо здесь перечислить. В версиях Shorewall до 3.0.8 и 3.2.0 Beta 8, устройство, имя которого указано в столбце, должно было существовать в момент запуска, перезапуска или обновления Shorewall. Начиная с версии 3.0.8 и 3.2.0 Beta 8 Shorewall может определить, существует ли устройство, и настроит его только в том случае, если оно существует. Если оно не существует, то будет показано следующее предупреждение:

  WARNING: Device <устройство> not found -- traffic-shaping configuration skipped

- IN-BANDWIDTH - Пропускная способность входящего канала для этого интерфейса. Обратите внимание, что шейпинг входящего трафика невозможен, так как пакеты уже пришли. В этом столбце можно задать максимальную скорость, разрешенную для этого интерфейса, при превышении которой пакеты будут отбрасываться. Это полезно главным образом для соединений DSL или кабельных, чтобы избежать очередей в устройствах провайдера. Если не следует отбрасывать никакие пакеты, то укажите значение, превышающее фактическую максимальную скорость канала (в Shorewall начиная с версии 3.2.6 можно также указать 0).

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

- OUT-BANDWIDTH - Пропускная способность исходящего канала для этого интерфейса. Это максимальная скорость, с которой может работать исходящее соединение. В терминах классов tc эта скорость называется полной (full). Превышающий эту скорость исходящий трафик будет отбрасываться.

Example 1.

Предположим, что вы работаете с PPP по Ethernet (DSL), а интерфейс - это ppp0. Устройство имеет исходящую скорость 500 кбит и входящую - 6000 кбит

    #INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
    ppp0           6000kbit         500kbit

### /etc/shorewall/tcclasses

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

- INTERFACE - Имя интерфейса. Должно совпадать с именем интерфейса в файле `/etc/shorewall/tcdevices`.

- MARK - метка. Должна быть целым числом от 1 до 255. Эти метки задаются в файле tcrules. Они помечают пакеты, которые тем самым будут отнесены к определенным здесь классам очередей. Одни и те же метки могут использоваться для разных интерфейсов.

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

- CEIL - ограничение, максимальная полоса пропускания, которая отводится для данного класса, когда канал свободен. Это полезно, если есть трафик, для которого будет выделяться полная скорость канала, если более важные службы (такие как ssh) не используются. Значение "full" означает, что максимальная пропускная способность для класса определяется значением, заданным для интерфейса.

- PRIORITY - позволяет указать приоритет для класса. Пакеты из класса с более высоким приоритетом (то есть меньшим значением) будут обрабатываться раньше, чем пакеты с низшим приоритетом. Здесь можно просто указать значение метки, если метки присваиваются согласно приоритетам.

- OPTIONS - Список параметров через запятую. Возможны следующие параметры:

  - default - класс по умолчанию для интерфейса, к которому будет отнесен весь трафик, не отнесенный к другим классам.

    ### Note

    Необходимо указать default ровно для одного класса для интерфейса.

  - tos-<имя-tos> - позволяет указать фильтр для заданного <имени-tos>, что в свою очередь позволяет определить значение бит Type Of Service в пакете ip, вследствие чего пакет будет отнесен к этому классу. Учтите, что этот фильтр переопределяет все заданные метки, поэтому, если задать фильтр tos для класса, то все пакеты, имеющие эту метку, войдут в этот класс независимо от того, какая у них уже есть метка. Возможные значения этого параметра: tos-minimize-delay (16) tos-maximize-throughput (8) tos-maximize-reliability (4) tos-minimize-cost (2) tos-normal-service (0)

    ### Note

    Каждая из этих опций применима только для одного класса интерфейса.

  - tcp-ack - эта опция создает фильтр tc и класс, в который помещаются все пакеты tcp ack на этом интерфейсе, размер которых не превышает 64 байта. Это позволяет ускорить загрузку. Ограничение размера пакетов ack 64 байтами служит для того, чтобы исключить из этого класса все приложения (например, p2p), которые помечают каждый пакет как пакет ack. Этому фильтру должны соответствовать только пакеты БЕЗ дополнительной нагрузки, отсюда и ограничение размера. Пакеты большего размера будут отнесены в другие классы.

    ### Note

    Эта опция применима только для одного класса интерфейса.

### /etc/shorewall/tcrules

Классификатор fwmark является удобным средством для классификации пакетов при управлении трафиком. В файле “/etc/shorewall/tcrules” эти метки представлены в виде таблицы. Глубже познакомиться с маркировкой пакетов в Netfilter/Shorewall позволяет этот документ.

Обычно метка пакета ставится в цепочке PREROUTING перед тем, как осуществляется замена адресов. При этом невозможно помечать входящие пакеты согласно их целевому адресу, если применяется SNAT или Masquerading. Тем не менее, можно осуществлять маркировку пакетов в цепочке FORWARD, если задать опцию MARK_IN_FORWARD_CHAIN в файле shorewall.conf.

Далее описаны столбцы файла:

- MARK или CLASSIFY - MARK задает значение метки, которая присваивается пакету в случае совпадения с правилом. Она должна быть целым числом от 1 до 255. Вслед за этим значением может идти “:” и одно из значений: “F”, “P” или "T", которые обозначают соответственно маркировку в цепочках FORWARD, PREROUTING или POSTROUTING. Если эти дополнительные спецификаторы опущены, то цепочка, в которой осуществляется маркировка пакетов, определяется следующим образом:

  - Если SOURCE - это $FW[:<адрес>], то правило вставляется в цепочку OUTPUT.

  - В противном случае цепочка определяется по значению опции MARK_IN_FORWARD_CHAIN из файла shorewall.conf.

  ### Note

  Спецификатор "T" был добавлен в Shorewall версии 3.3.6 и недоступен в более ранних версиях.

  Обычно метка присваивается пакету. Если вслед за меткой указать ":" и "C", то метка будет применяться к соединению. "C" можно сочетать с "F", "P" или "T", чтобы указать, что соединение следует пометить в определенной цепочке (например, "CF", "CP", "CT").

  Предусмотрены также следующие специальные значения:

  1. RESTORE[/маска] -- восстановить метку пакета из метки соединения, используя маску, если она указана. Ядро и iptables должны поддерживать CONNMARK.

     Как и ранее, можно использовать дополнительные спецификаторы :P, :F или :T.

  2. SAVE[/маска] -- сохранить метку пакета в метке соединения, используя маску, если она указана. Ядро и iptables должны поддерживать CONNMARK.

     Как и ранее, можно использовать дополнительные спецификаторы :P, :F или :T.

  3. CONTINUE - прекратить обработку дальнейших правил маркировки в таблице.

     Как и ранее, можно использовать дополнительные спецификаторы :P, :F или :T.

  4. COMMENT (Начиная с Shorewall версии 3.3.3) -- остальной текст в строке будет добавлен как комментарий в правила Netfilter, генерируемые по следующим записям. Комментарий будет выделен символам "/* ... */" в выводе команды shorewall show mangle

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

  При работе с CLASSIFY ядро и iptables должны поддерживать CLASSIFY. В этом случае в столбце будет содержаться классификатор (classid) в виде <основной>:<дополнительный>, где <основной> и <дополнительный> должны быть целыми числами. Он соответствует указанию 'class' в следующих модулях управления трафиком:

  atm
  cbq
  dsmark
  pfifo_fast
  htb
  prio

  В версиях Shorewall до 3.2.3 правила классификации всегда помещались в цепочку POSTROUTING. Начиная с Shorewall версии 3.2.3 классификация осуществляется в цепочке POSTROUTING, кроме тех случаев, когда SOURCE содержит $FW[:<адрес>], для которых классификация осуществляется в цепочке OUTPUT. При работе со встроенными функциями управления трафиком класс <основной> - это номер устройства (первая запись в файле `/etc/shorewall/tcdevices` - это устройство 1, вторая - устройство 2 и т.д.), а класс <дополнительный> - это значение MARK класса, перед которой стоит число "1" (для MARK со значением 1 <дополнительный> класс - это 11, для MARK со значением 22 - <дополнительный> класс 122, и т.д.).

- SOURCE - источник пакета. Это может быть разделенный запятыми список имен интерфейсов, IP-адресов, MAC-адресов и/или подсетей для пакетов, маршрутизируемых по общему пути. Элементы списка могут также включать имя интерфейса, к которому прибавлено ":" и адрес (например, eth1:192.168.1.0/24). Так, все пакеты для соединений, маскируемых через eth0 с других интерфейсов, можно описать одним правилом с несколькими критериями SOURCE. Однако соединение, пакеты которого приходят на eth0 по другому пути, например, из самой системы файрвола, требуют отдельного правила.

  Поэтому создавайте отдельное правило с $FW для пакетов, исходящих из системы файрвола. В таком правиле столбец MARK не может содержать ":P" или ":F", поскольку маркировка пакетов, исходящих из системы файрвола, всегда осуществляется в цепочке OUTPUT.

  MAC-адреса необходимо предварять символом "~" и использовать "-" как разделитель.

  Пример: ~00-A0-C9-15-39-78

- DEST - назначение пакета. Список IP-адресов и/или подсетей, разделенный запятыми. Если ядро и iptables поддерживают iprange, то можно также указывать диапазоны IP-адресов. Элементы списка могут также включать имя интерфейса, к которому прибавлено ":" и адрес (например, eth1:192.168.1.0/24). Если в столбце MARK указан спецификатор в виде <основной>:<дополнительный>, то столбец может также содержать имя интерфейса.

- PROTO - протокол. Должен быть указан как "tcp", "udp", "icmp", "ipp2p", "ipp2p:udp", "ipp2p:all", число или "all". Для "ipp2p" требуется поддержка ipp2p в ядре и iptables.

- PORT(S) - целевые порты. Список имен портов (из /etc/services), номеров портов или диапазонов портов, разделенный запятыми. Если протокол - это "icmp", то столбец считается целевым типом icmp.

  Если протокол - это ipp2p, то столбец интерпретируется как опция ipp2p без начального "--" (например, "bit" для bit-torrent). Если PORT не указан, предполагается "ipp2p".

  Этот поле игнорируется, если PROTOCOL = all, но должно быть указано, если задано любое из последующих полей. В этом случае рекомендуется указывать в этом поле "-"

- CLIENT PORT(S) - необязательные порты, применяемые клиентом. Если они не указаны, то допускается любой целевой порт. Задается как список, разделенный запятыми, имен портов, номеров портов или диапазонов портов.

- USER/GROUP (Начиная с Shorewall версии 1.4.10) - Необязательный параметр имени пользователя или группы. Он может указываться, только если SOURCE - это сама система файрвола. Если значение поля задано, то правило применяется только в том случае, если программа, создавшая пакет, работает от имени указанного пользователя и/или группы. Возможные значения:

  [!][<имя пользователя или номер>]:[<имя группы или номер>][+<имя программы>]

  Двоеточие указывать необязательно, если задано только имя пользователя.

  Примеры:

      joe     # программа должна выполняться пользователем joe
      :kids   # программа выполняется участниками группы 'kids'
      !:kids  # программа выполняется участниками группы 'kids'
      +upnpd  # программа upnpd (эта функция была удалена из Netfilter в версии ядра 2.6.14).

- TEST - задает тест для проверки существующей метки пакета или соединения. Правило будет совпадать только в том случае, если тест возвращает true. Тесты имеют следующий формат: [!]<значение>[/<маска>][:C]

  Здесь:

  ! Обратное соответствие (не равно)
  <значение> Значение метки соединения или пакета.
  <маска> Маска, применяемая к метке перед сравнением
  :C обозначает метку соединения. Если она не указана, то сравнивается метка пакета.

- LENGTH - длина пакета (необязательный параметр, начиная с Shorewall версии 3.2.0). Если указано это значение, то сравнивается длина пакета с указанным значением или диапазоном значений. Диапазон задается в виде <мин>:<макс>, где можно опустить или <мин>, или <макс>, но не оба эти параметра. Если опущен <мин>, то он считается равным 0, если опущен <макс>, то совпадающим будет любой пакет, длина которого не меньше <мин>.

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

  Примеры: 1024, 64:1500, :100

- TOS - тип обслуживания (необязательный параметр, начиная с Shorewall версии 3.2.0 Beta 6). Стандартное имя или число.

  > Minimize-Delay (16)
  > Maximize-Throughput (8)
  > Maximize-Reliability (4)
  > Minimize-Cost (2)
  > Normal-Service (0)

Example 2.

Все пакеты, приходящие на eth1, должны иметь метку 1. Все пакеты, приходящие на eth2 и eth3, должны иметь метку 2. Все пакеты, созданные в системе файрвола, должны иметь метку 3.

    #MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)
    1       eth1      0.0.0.0/0      all
    2       eth2      0.0.0.0/0      all
    2       eth3      0.0.0.0/0      all
    3       $FW       0.0.0.0/0     all

Example 3.

Все пакеты GRE (протокол 47), не созданные в системе файрвола и имеющие целевой адрес 155.186.235.151, должны иметь метку 12.

    #MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)
    12      0.0.0.0/0 155.182.235.151 47

Example 4.

Все пакеты SSH, приходящие с 192.168.1.0/24 и предназначенные для 155.186.235.151, должны иметь метку 22.

    #MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)
    22      192.168.1.0/24 155.182.235.151 tcp        22

Example 5.

Все пакеты SSH, проходящие через первое устройство в файле /etc/shorewall/tcdevices, должны быть отнесены в класс с меткой 10.

    #MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)         CLIENT
    #                                                                 PORT(S)
    1:110   0.0.0.0/0      0.0.0.0/0       tcp        22
    1:110   0.0.0.0/0      0.0.0.0/0       tcp        -               22

Example 6.

Все пакеты echo ICMP должны иметь метку 1. Весь трафик протоколов p2p должен иметь метку 4.

Это чуть более сложный случай. Поскольку модуль ipp2p не в состоянии распознать все пакеты в соединении как пакеты P2P, то все соединение помечается как P2P, если совпадение найдено хотя бы для одного пакета. Предполагается, что метка пакета/соединения 0 означает неклассифицированные пакеты.

    #MARK    SOURCE         DESTINATION     PROTOCOL   PORT(S)       CLIENT   USER/     TEST
    #                                                                PORT(S)  GROUP
    1        0.0.0.0/0      0.0.0.0/0       icmp       echo-request
    1        0.0.0.0/0      0.0.0.0/0       icmp       echo-reply

    RESTORE  0.0.0.0/0      0.0.0.0/0       all        -             -        -         0
    CONTINUE 0.0.0.0/0      0.0.0.0/0       all        -             -        -         !0
    4        0.0.0.0/0      0.0.0.0/0       ipp2p:all
    SAVE     0.0.0.0/0      0.0.0.0/0       all        -             -        -         !0

Последние четыре правила означают следующее:

> "Если пакет не был классифицирован (метка пакета 0), то скопировать метку соединения в метку пакета. Если метка пакета уже задана, то никаких действий более не требуется. Если пакет относится к типу P2P, то задать метку пакета 4. Если метка пакета задана, то сохранить ее в качестве метки соединения."

### Устройства ppp

Если подключение к провайдеру выполняется через ppp/pppoe/pppoa, и вы используете управление трафиком, то необходимо перезапустить управление трафиком shorewall. Причина этого состоит в том, что если соединение ppp перезапускается (обычно это происходит как минимум раз в день), то все фильтры и qdisc “tc”, связанные с этим интерфейсом, будут удалены.

Самым простым решением будет перезапуск shorewall при повторном установлении соединения. Для этого добавьте в сценарий “/etc/ppp/ip-up.d” следующую строку.

    #! /bin/sh

    /sbin/shorewall refresh

### Рабочие примеры

#### Конфигурация для замены Wondershaper

Встроенные функции управления трафиком позволяют полностью заменить сценарий wondershaper. Примеры файлов конфигурации приведены по адресу "http://www1.shorewall.net/pub/shorewall/Samples/tc4shorewall/. Обратите внимание, что эти примеры необходимо настроить, чтобы они работали в вашей среде. В них предполагается, что интерфейс соединения с провайдером - это ppp0 (для DSL), и для другого типа соединения его необходимо изменить. Также требуется изменить параметры в файле tcdevices.wondershaper, чтобы они отвечали фактической скорости канала. Ниже приведены соответствующие строки из файлов конфигурации. В итоге получается точная замена того, что должен делать wondershaper. Но вы можете и вносить улучшения...

##### Файл tcdevices

    #INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
    ppp0            5000kbit        500kbit

##### Файл tcclasses

    #INTERFACE      MARK    RATE            CEIL            PRIORITY    OPTIONS
    ppp0            1       full            full            1       tcp-ack,tos-minimize-delay
    ppp0            2       9*full/10       9*full/10       2       default
    ppp0            3       8*full/10       8*full/10       2

##### Файл tcrules

    #MARK           SOURCE          DEST            PROTO   PORT(S)      CLIENT   USER
    #                                                              PORT(S)
    1:F             0.0.0.0/0       0.0.0.0/0       icmp    echo-request
    1:F             0.0.0.0/0       0.0.0.0/0       icmp    echo-reply
    # метка для трафика с низким приоритетом:
    # mldonkey
    3               0.0.0.0/0        0.0.0.0/0      udp     -         4666

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

##### Присвоение низкого приоритета хостам

Допустим, что в сценарии wondershaper были следующие параметры (только в качестве примера):

    # Низкий приоритет для исходящего трафика - можно оставить пустым,
    # чтобы применять сетевые маски для низкого приоритета
    NOPRIOHOSTSRC="192.168.1.128/25 192.168.3.28"

    # Низкий приоритет - маска для назначения
    NOPRIOHOSTDST=60.0.0.0/24

    # Низкий приоритет - порты источника
    NOPRIOPORTSRC="6662 6663"

    # Низкий приоритет - порты назначения
    NOPRIOPORTDST="6662 6663"

Эти параметры будут отражены следующим образом в файле tcrules:

    3               192.168.1.128/25 0.0.0.0/0      all
    3               192.168.3.28     0.0.0.0/0      all
    3               0.0.0.0/0        60.0.0.0/24    all
    3               0.0.0.0/0        0.0.0.0/0      udp     6662,6663
    3               0.0.0.0/0        0.0.0.0/0      udp     -         6662,6663
    3               0.0.0.0/0        0.0.0.0/0      tcp     6662,6663
    3               0.0.0.0/0        0.0.0.0/0      tcp     -         6662,6663

#### Простая конфигурация

Ниже приведен простой пример для общего подключения к Интернет с разных компьютеров. Фактически здесь настроен шейпинг для двух хостов с IP-адресами 192.168.2.23 и 192.168.2.42

##### Файл tcdevices

    #INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
    ppp0            6000kbit        700kbit

Канал имеет входящие 6 мбит и исходящие 700 кбит.

##### Файл tcclasses

    #INTERFACE      MARK    RATE            CEIL        PRIORITY    OPTIONS
    ppp0            1       5*full/10       full            1       tcp-ack,tos-minimize-delay
    ppp0            2       3*full/10       9*full/10       2       default
    ppp0            3       2*full/10       8*full/10       2

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

##### Файл tcrules

    #MARK           SOURCE          DEST            PROTO   PORT(S)      CLIENT   USER
    #                                                                    PORT(S)
    1:F             0.0.0.0/0       0.0.0.0/0       icmp    echo-request
    1:F             0.0.0.0/0       0.0.0.0/0       icmp    echo-reply
    2:F             192.168.2.23    0.0.0.0/0       all
    3:F             192.168.2.42    0.0.0.0/0       all

Пакеты ping icmp и ответы помечаются отдельно, как относящиеся к интерактивному классу. Для них метка ставится для обоих хостов.

## Замечания для пользователей Xen

Если управление трафиком включено в dom0, но исходящий трафик при этом шейпится неправильно, то причиной этого может быть "выгрузка контрольных сумм" (checksum offloading) в ваших domU. Просмотрите вывод команды "shorewall show tc". Ниже приведен пример:

    class htb 1:130 parent 1:1 leaf 130: prio 3 quantum 1500 rate 76000bit ceil 230000bit burst 1537b/8 mpu 0b overhead 0b cburst 1614b/8 mpu 0b overhead 0b level 0
     Sent 559018700 bytes 75324 pkt (dropped 0, overlimits 0 requeues 0)
     rate 299288bit 3pps backlog 0b 0p requeues 0
     lended: 53963 borrowed: 21361 giants: 90174
     tokens: -26688 ctokens: -14783

В приведенном примере легко обнаружить две проблемы:

1. Скорость (299288) заметно превышает установленный предел (230000).

2. Сообщается о большом числе огромных пакетов (90174).

Эта неполадка устраняется выключением "checksum offloading" в domU с помощью программы ethtool. За инструкциями обратитесь к статье по Xen.

## Применение собственных сценариев tc

### Замена встроенного файла tcstart

Если вы предпочитаете сами создать файл запуска tc, просто поместите его в /etc/shorewall/tcstart.

В сценарии tcstart вместо вызова программы “tc” используйте функцию run_tc из Shorewall, чтобы при ошибке tc остановить файрвол.

1. Задайте TC_ENABLED=Yes и CLEAR_TC=Yes

2. Укажите сценарий /etc/shorewall/tcstart с правилами управления трафиком.

3. Укажите также необязательный сценарий /etc/shorewall/tcclear для остановки управления трафиком. Обычно это не требуется.

4. Если сценарий tcstart применяет классификатор “fwmark”, то можно помечать пакеты, используя записи из /etc/shorewall/tcrules.

### Управление трафиком, внешнее по отношению к Shorewall

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

1. Задайте TC_ENABLED=No и CLEAR_TC=No

2. Если сценарий применяет классификатор “fwmark”, то можно помечать пакеты, используя записи из /etc/shorewall/tcrules.

## Инструменты тестирования

Как минимум один пользователь Shorewall посчитал полезными следующие инструменты: http://e2epi.internet2.edu/network-performance-toolkit.html