<?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 & 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 <устройство> 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-<имя-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)</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[:<<emphasis>адрес</emphasis>>], то правило вставляется в цепочку 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) в виде <основной>:<дополнительный>, где <основной> и <дополнительный> должны быть целыми числами. Он соответствует указанию '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[:<<emphasis>адрес</emphasis>>], для которых классификация осуществляется в цепочке OUTPUT. При работе со встроенными функциями управления трафиком класс <основной> - это номер устройства (первая запись в файле <filename>/etc/shorewall/tcdevices</filename> - это устройство 1, вторая - устройство 2 и т.д.), а класс <дополнительный> - это значение MARK класса, перед которой стоит число "1" (для MARK со значением 1 <дополнительный> класс - это 11, для MARK со значением 22 - <дополнительный> класс 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 указан спецификатор в виде <основной>:<дополнительный>, то столбец может также содержать имя интерфейса.</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>[!][<имя пользователя или номер>]:[<имя группы или номер>][+<имя программы>]</para> <para>Двоеточие указывать необязательно, если задано только имя пользователя.</para> <para>Примеры:</para> <programlisting>joe # программа должна выполняться пользователем joe :kids # программа выполняется участниками группы 'kids' !:kids # программа выполняется участниками группы 'kids' +upnpd # программа upnpd (эта функция была удалена из Netfilter в версии ядра 2.6.14).</programlisting> </listitem> <listitem> <para>TEST - задает тест для проверки существующей метки пакета или соединения. Правило будет совпадать только в том случае, если тест возвращает true. Тесты имеют следующий формат: [!]<значение>[/<маска>][:C]</para> <para>Здесь:</para> <simplelist> <member>! Обратное соответствие (не равно)</member> <member><значение> Значение метки соединения или пакета.</member> <member><маска> Маска, применяемая к метке перед сравнением</member> <member>:C обозначает метку соединения. Если она не указана, то сравнивается метка пакета.</member> </simplelist> </listitem> <listitem> <para>LENGTH - длина пакета (необязательный параметр, начиная с Shorewall версии 3.2.0). Если указано это значение, то сравнивается длина пакета с указанным значением или диапазоном значений. Диапазон задается в виде <мин>:<макс>, где можно опустить или <мин>, или <макс>, но не оба эти параметра. Если опущен <мин>, то он считается равным 0, если опущен <макс>, то совпадающим будет любой пакет, длина которого не меньше <мин>.</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>