<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<article>
  <!--$Id$-->

  <articleinfo>
    <title>Управление трафиком и шейпинг трафика</title>

    <authorgroup>
      <author>
        <firstname>Tom</firstname>

        <surname>Eastep</surname>
      </author>

      <author>
        <firstname>Arne</firstname>

        <surname>Bernin</surname>
      </author>
    </authorgroup>

    <pubdate><?dbtimestamp format="Y/m/d"?></pubdate>

    <copyright>
      <year>2001-2007</year>

      <holder>Thomas M. Eastep</holder>
    </copyright>

    <copyright>
      <year>2005</year>

      <holder>Arne Bernin &amp; Thomas M. Eastep</holder>
    </copyright>

    <copyright>
      <year>2007</year>

      <holder>Russian Translation: Grigory Mokhin</holder>
    </copyright>

    <legalnotice>
      <para>Этот документ разрешается копировать, распространять и/или
      изменять при выполнении условий лицензии GNU Free Documentation License
      версии 1.2 или более поздней, опубликованной Free Software Foundation;
      без неизменяемых разделов, без текста на верхней обложке, без текста на
      нижней обложке. Копия лицензии приведена по ссылке <quote><ulink
      url="GnuCopyright.htm">GNU Free Documentation
      License</ulink></quote>.</para>
    </legalnotice>
  </articleinfo>

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

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

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

    <itemizedlist>
      <listitem>
        <para>LARTC HOWTO: <ulink
        url="http://www.lartc.org">http://www.lartc.org</ulink></para>
      </listitem>

      <listitem>
        <para>Руководство по HTB: <ulink
        url="http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm">http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm</ulink></para>
      </listitem>

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

      <listitem>
        <para>Вывод команды <command>man iptables</command></para>
      </listitem>
    </itemizedlist>
  </warning>

  <section id="Intro">
    <title>Введение</title>

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

    <para>До сих пор поддержка управления трафиком является неполной,
    например, не поддерживаются все опции (и особенно различные алгоритмы
    очередей) из ядра Linux, но для большинства случаев она будет достаточной.
    Если у вас уже есть сценарий для управления трафиком, который вы
    собираетесь использовать и в будущем, то соответствующие инструкции
    приведены по ссылке <link linkend="owntcstart"> ниже в этом
    документе</link>. Для того чтобы это заработало, требуется включить
    поддержку управления трафиком в ядре и в Shorewall, как описано
    далее.</para>
  </section>

  <section id="LinuxTC">
    <title>Управление трафиком и шейпинг трафика в Linux</title>

    <para>В этом разделе кратко описано, как работает управление трафиком в
    Linux. Даже если этого должно быть достаточно для настройки управления
    трафиком в файлах конфигурации Shorewall, мы очень рекомендуем внимательно
    прочитать руководство <ulink url="http://lartc.org/howto/">Linux Advanced
    Routing and Shaping HOWTO</ulink>. Во время написания этого документа
    текущей версией была 1.0.0.</para>

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

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

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

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

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

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

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

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

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

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

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

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

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

  <section id="Kernel">
    <title>Конфигурация ядра Linux</title>

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

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

    <para>На следующем рисунке показано, как я настроил QoS у себя в ядре
    2.6.13:<graphic align="center" fileref="images/QoS.png" /></para>

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

    <graphic align="center" fileref="images/traffic_shaping2.6.png" />
  </section>

  <section id="Shorewall">
    <title>Включение поддержки TC в Shorewall</title>

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

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

    <itemizedlist>
      <listitem>
        <para>Задайте <emphasis role="bold">TC_ENABLED</emphasis> равным
        "Internal" в /etc/shorewall/shorewall.conf. Если TC_ENABLED=Yes, то
        Shorewall будет искать внешний файл tcstart (см. <link
        linkend="tcstart">далее</link>).</para>
      </listitem>

      <listitem>
        <para>Если задать параметр <emphasis role="bold">CLEAR_TC</emphasis> в
        /etc/shorewall/shorewall.conf равным Yes, то при запуске, перезапуске
        и остановке Shorewall будет сбрасываться текущая конфигурация
        управления трафиком. Обычно именно это и требуется при работе с
        встроенными функциями, а также с собственным сценарием tcstart.</para>
      </listitem>

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

  <section id="Builtin">
    <title>Работа с встроенными функциями управления трафиком и
    шейпинга</title>

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

    <itemizedlist>
      <listitem>
        <para>Определить классы HTB в файлах конфигурации Shorewall.</para>
      </listitem>

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

      <listitem>
        <para>Распределить пакеты по классам HTB согласно значениям
        TOS.</para>
      </listitem>

      <listitem>
        <para>Отнести исходящие пакеты TCP ACK к классу HTB.</para>
      </listitem>

      <listitem>
        <para>Распределить пакеты по классам HTB согласно значениям меток
        пакетов.</para>
      </listitem>
    </itemizedlist>

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

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

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

    <para>Для того чтобы правильно настроить устройства, необходимо выяснить
    фактическую пропускную способность канала в обоих направлениях. Это
    особенно важно для соединений DSL или любых других, для которых пропускная
    способность канала не гарантирована. Не верьте числам, которые называет
    провайдер, но сами измерьте реальную скорость канала. В этом могут помочь
    различные утилиты в сети, попробуйте поискать "dsl speed test" в google
    (для Германии можно использовать <ulink
    url="http://www.speedcheck.arcor.de/cgi-bin/speedcheck.cgi">arcor speed
    check</ulink>). Найдите тест поближе к себе.</para>

    <section id="tcdevices">
      <title>/etc/shorewall/tcdevices</title>

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

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

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

          <para><emphasis role="bold">WARNING: Device &lt;устройство&gt; not
          found -- traffic-shaping configuration skipped</emphasis></para>
        </listitem>

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

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

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

      <example id="Example0">
        <title></title>

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

        <programlisting>#INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
ppp0           6000kbit         500kbit</programlisting>
      </example>
    </section>

    <section id="tcclasses">
      <title>/etc/shorewall/tcclasses</title>

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

      <itemizedlist>
        <listitem>
          <para>INTERFACE - Имя интерфейса. Должно совпадать с именем
          интерфейса в файле
          <filename>/etc/shorewall/tcdevices</filename>.</para>
        </listitem>

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

        <listitem>
          <para>RATE - скорость, то есть минимальная гарантированная
          пропускная способность, которая должна обеспечиваться для класса,
          когда возрастает нагрузка на канал. Классы с более высоким
          приоритетом обслуживаются даже в том случае, если заданы другие
          классы с гарантированной пропускной способностью, но низшим
          приоритетом. <emphasis role="bold">Если сумма значений RATE для всех
          классов, присвоенных интерфейсу, превышает OUT-BANDWIDTH для
          интерфейса, то предел OUT-BANDWIDTH не будет
          соблюдаться.</emphasis></para>
        </listitem>

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

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

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

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

              <note>
                <para>Необходимо указать default ровно для <emphasis
                role="bold">одного</emphasis> класса для интерфейса.</para>
              </note>
            </listitem>

            <listitem>
              <para>tos-&lt;имя-tos&gt; - позволяет указать фильтр для
              заданного &lt;имени-tos&gt;, что в свою очередь позволяет
              определить значение бит 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)</para>

              <note>
                <para>Каждая из этих опций применима только для <emphasis
                role="bold">одного</emphasis> класса интерфейса.</para>
              </note>
            </listitem>

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

              <note>
                <para>Эта опция применима только для одного <emphasis
                role="bold">класса</emphasis> интерфейса.</para>
              </note>
            </listitem>
          </itemizedlist>
        </listitem>
      </itemizedlist>
    </section>

    <section id="tcrules">
      <title>/etc/shorewall/tcrules</title>

      <para>Классификатор fwmark является удобным средством для классификации
      пакетов при управлении трафиком. В файле
      <quote>/etc/shorewall/tcrules</quote> эти метки представлены в виде
      таблицы. Глубже познакомиться с маркировкой пакетов в
      Netfilter/Shorewall позволяет <ulink url="PacketMarking.html">этот
      документ</ulink>.</para>

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

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

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

          <itemizedlist>
            <listitem>
              <para>Если SOURCE - это
              $FW[:&lt;<emphasis>адрес</emphasis>&gt;], то правило вставляется
              в цепочку OUTPUT.</para>
            </listitem>

            <listitem>
              <para>В противном случае цепочка определяется по значению опции
              MARK_IN_FORWARD_CHAIN из файла shorewall.conf.</para>
            </listitem>
          </itemizedlist>

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

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

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

          <orderedlist numeration="loweralpha">
            <listitem>
              <para><emphasis
              role="bold">RESTORE</emphasis>[/<emphasis>маска</emphasis>] --
              восстановить метку пакета из метки соединения, используя маску,
              если она указана. Ядро и iptables должны поддерживать
              CONNMARK.</para>

              <para>Как и ранее, можно использовать дополнительные
              спецификаторы <emphasis role="bold">:P</emphasis>, <emphasis
              role="bold">:F</emphasis> или <emphasis
              role="bold">:T</emphasis>.</para>
            </listitem>

            <listitem>
              <para><emphasis
              role="bold">SAVE</emphasis>[/<emphasis>маска</emphasis>] --
              сохранить метку пакета в метке соединения, используя маску, если
              она указана. Ядро и iptables должны поддерживать
              CONNMARK.</para>

              <para>Как и ранее, можно использовать дополнительные
              спецификаторы <emphasis role="bold">:P</emphasis>, <emphasis
              role="bold">:F</emphasis> или <emphasis
              role="bold">:T</emphasis>.</para>
            </listitem>

            <listitem>
              <para><emphasis role="bold">CONTINUE</emphasis> - прекратить
              обработку дальнейших правил маркировки в таблице.</para>

              <para>Как и ранее, можно использовать дополнительные
              спецификаторы <emphasis role="bold">:P</emphasis>, <emphasis
              role="bold">:F</emphasis> или <emphasis
              role="bold">:T</emphasis>.</para>
            </listitem>

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

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

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

          <simplelist>
            <member>atm</member>

            <member>cbq</member>

            <member>dsmark</member>

            <member>pfifo_fast</member>

            <member>htb</member>

            <member>prio</member>
          </simplelist>

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

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

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

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

          <para>Пример: ~00-A0-C9-15-39-78</para>
        </listitem>

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

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

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

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

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

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

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

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

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

          <para>Примеры:</para>

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

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

          <para>Здесь:</para>

          <simplelist>
            <member>! Обратное соответствие (не равно)</member>

            <member>&lt;значение&gt; Значение метки соединения или
            пакета.</member>

            <member>&lt;маска&gt; Маска, применяемая к метке перед
            сравнением</member>

            <member>:C обозначает метку соединения. Если она не указана, то
            сравнивается метка пакета.</member>
          </simplelist>
        </listitem>

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

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

          <para>Примеры: 1024, 64:1500, :100</para>
        </listitem>

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

          <blockquote>
            <simplelist>
              <member>Minimize-Delay (16)</member>

              <member>Maximize-Throughput (8)</member>

              <member>Maximize-Reliability (4)</member>

              <member>Minimize-Cost (2)</member>

              <member>Normal-Service (0)</member>
            </simplelist>
          </blockquote>
        </listitem>
      </itemizedlist>

      <example id="Example1">
        <title></title>

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

        <programlisting>#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</programlisting>
      </example>

      <example id="Example2">
        <title></title>

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

        <programlisting>#MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)
12      0.0.0.0/0 155.182.235.151 47</programlisting>
      </example>

      <example id="Example3">
        <title></title>

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

        <programlisting>#MARK   SOURCE         DESTINATION     PROTOCOL   PORT(S)
22      192.168.1.0/24 155.182.235.151 tcp        22</programlisting>
      </example>

      <example id="Example4">
        <title></title>

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

        <programlisting>#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</programlisting>
      </example>

      <example id="Example5">
        <title></title>

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

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

        <programlisting>#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</programlisting>

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

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

    <section id="ppp">
      <title>Устройства ppp</title>

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

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

      <programlisting>#! /bin/sh

/sbin/shorewall refresh</programlisting>
    </section>

    <section id="Real">
      <title>Рабочие примеры</title>

      <section id="Wondershaper">
        <title>Конфигурация для замены Wondershaper</title>

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

        <section id="realtcd">
          <title>Файл tcdevices</title>

          <programlisting>#INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
ppp0            5000kbit        500kbit</programlisting>
        </section>

        <section id="realtcc">
          <title>Файл tcclasses</title>

          <programlisting>#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</programlisting>
        </section>

        <section id="realtcr">
          <title>Файл tcrules</title>

          <programlisting>#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</programlisting>

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

        <section id="lowpro">
          <title>Присвоение низкого приоритета хостам</title>

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

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

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

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

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

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

          <programlisting>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</programlisting>
        </section>
      </section>

      <section id="simiple">
        <title>Простая конфигурация</title>

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

        <section id="simpletcd">
          <title>Файл tcdevices</title>

          <programlisting>#INTERFACE    IN-BANDWITH      OUT-BANDWIDTH
ppp0            6000kbit        700kbit</programlisting>

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

        <section id="simpletcc">
          <title>Файл tcclasses</title>

          <programlisting>#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</programlisting>

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

        <section id="simpletcr">
          <title>Файл tcrules</title>

          <programlisting>#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</programlisting>

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

  <section id="Xen">
    <title>Замечания для пользователей Xen</title>

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

    <programlisting>class htb 1:130 parent 1:1 leaf 130: prio 3 quantum 1500 rate 76000bit <emphasis
        role="bold">ceil 230000bit</emphasis> 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) 
 <emphasis role="bold">rate 299288bit</emphasis> 3pps backlog 0b 0p requeues 0 
 lended: 53963 borrowed: 21361 <emphasis role="bold">giants: 90174</emphasis>
 tokens: -26688 ctokens: -14783</programlisting>

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

    <orderedlist>
      <listitem>
        <para>Скорость (299288) заметно превышает установленный предел
        (230000).</para>
      </listitem>

      <listitem>
        <para>Сообщается о большом числе огромных пакетов (90174).</para>
      </listitem>
    </orderedlist>

    <para>Эта неполадка устраняется выключением "checksum offloading" в domU с
    помощью программы <command>ethtool</command>. За инструкциями обратитесь к
    <ulink url="XenMyWay-Routed.html">статье по Xen</ulink>.</para>
  </section>

  <section id="External">
    <title id="tcstart">Применение собственных сценариев tc</title>

    <section id="owntcstart">
      <title>Замена встроенного файла tcstart</title>

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

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

      <orderedlist>
        <listitem>
          <para>Задайте TC_ENABLED=Yes и CLEAR_TC=Yes</para>
        </listitem>

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

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

        <listitem>
          <para>Если сценарий tcstart применяет классификатор
          <quote>fwmark</quote>, то можно помечать пакеты, используя записи из
          /etc/shorewall/tcrules.</para>
        </listitem>
      </orderedlist>
    </section>

    <section id="Start">
      <title>Управление трафиком, внешнее по отношению к Shorewall</title>

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

      <orderedlist>
        <listitem>
          <para>Задайте TC_ENABLED=No и CLEAR_TC=No</para>
        </listitem>

        <listitem>
          <para>Если сценарий применяет классификатор <quote>fwmark</quote>,
          то можно помечать пакеты, используя записи из
          /etc/shorewall/tcrules.</para>
        </listitem>
      </orderedlist>
    </section>
  </section>

  <section id="Testing">
    <title>Инструменты тестирования</title>

    <para>Как минимум один пользователь Shorewall посчитал полезными следующие
    инструменты: <ulink
    url="http://e2epi.internet2.edu/network-performance-toolkit.html">http://e2epi.internet2.edu/network-performance-toolkit.html</ulink></para>
  </section>
</article>
