Iptables: различия между версиями

Содержимое удалено Содержимое добавлено
орфография, викификатор
Строка 12:
|screenshot = [[File:Iptablesfb.png|300px|iptables]]
}}
'''iptables'''  — утилита [[w:Интерфейс командной строки |командной строки]], является стандартным интерфейсом управления работой [[w:Межсетевой экран |межсетевого экрана]] (брандмауэра) '''{{w |netfilter}}''' для [[w:Ядро Linux |ядер Linux]] версий 2.4, 2.6, 3.x, 4.x . Для использования утилиты iptables требуются привилегии [[w:Root |суперпользователя]] (root).
 
Иногда под словом iptables имеется в виду и сам межсетевой экран netfilter.
Строка 21:
Предшественниками iptables были проекты {{w |ipchains}} (применялась для администрирования фаервола ядра Linux версии 2.2) и [[ipfwadm]] (аналогично для ядер Linux версий 2.0). Последний был основан на {{w |BSD}}-утилите {{w |ipfw}}.
 
iptables сохраняет идеологию, ведущую начало от ipfwadm: функционирование фаервола определяется набором правил, каждое из которых состоит из критерия и действия, применяемого к пакетам, подпадающим под этот критерий. В ipchains появилась концепция ''цепочек''  — независимых списков правил. Были введены отдельные цепочки для фильтрации входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов. В продолжении этой идеи, в iptables появились ''таблицы''  — независимые группы цепочек. Каждая таблица решала свою задачу  — цепочки таблицы filter отвечали за фильтрацию, цепочки таблицы nat  — за преобразование сетевых адресов ({{w |NAT}}), к задачам таблицы mangle относились прочие модификации заголовков пакетов (например, изменение [[w:Time to live |TTL]] или [[w:Тип обслуживания |TOS]]). Кроме того, была слегка изменена логика работы цепочек: в ipchains все входящие пакеты, включая транзитные, проходили цепочку INPUT. В iptables через INPUT проходят только пакеты, адресованные самому хосту.
 
Такое разделение функциональности позволило iptables при обработке отдельных пакетов использовать информацию о соединениях в целом (ранее это было возможно только для NAT). В этом iptables значительно превосходит ipchains, так iptables может отслеживать состояние соединения и перенаправлять, изменять или отфильтровывать пакеты, основываясь не только на данных из их заголовков (источник, получатель) или содержимом пакетов, но и на основании данных о соединении. Такая возможность фаервола называется stateful-фильтрацией, в отличие от реализованной в ipchains примитивной stateless-фильтрации (подробнее о видах фильтрации см. статью о [[w:Межсетевой экран |фаерволах]]). Можно сказать, что iptables анализирует не только передаваемые данные, но и контекст их передачи, в отличие от ipchains, и поэтому может принимать более обоснованные решения о судьбе каждого конкретного пакета. Более подробно о stateful-фильтрации в netfilter/iptables см. [[w:Netfilter#Механизм определения состояний]].
 
В будущем, разработчики netfilter планируют заменить iptables на [[nftables]]  — инструмент нового поколения, пока находящийся в ранней стадии разработки<ref>[http://www.opennet.ru/opennews/art.shtml?num=20843 Разработчики Netfilter представили замену iptables]</ref>.
 
== Архитектура ==
 
=== Основные понятия ===
 
Ключевыми понятиями iptables являются:
* '''Правило'''  — состоит из ''критерия'', ''действия'' и ''счетчика''. Если пакет соответствует критерию, к нему применяется действие, и он учитывается счетчиком. Критерия может и не быть  — тогда неявно предполагается критерий «все пакеты». Указывать действие тоже не обязательно  — в отсутствие действия правило будет работать только как счетчик.
** '''Критерий'''  — логическое выражение, анализирующее свойства пакета и/или соединения и определяющее, подпадает ли данный конкретный пакет под действие текущего правила.
** '''Действие'''  — описание действия, которое нужно проделать с пакетом и/или соединением в том случае, если они подпадают под критерий этого правила. О действиях более подробно будет рассказано ниже.
** '''Счетчик'''  — компонент правила, обеспечивающий учет количества пакетов, которые попали под критерий данного правила. Также счетчик учитывает суммарный объем таких пакетов в байтах.
* '''Цепочка'''  — упорядоченная последовательность правил. Цепочки можно разделить на ''пользовательские'' и ''базовые''.
** '''Базовая цепочка'''  — цепочка, создаваемая по умолчанию при инициализации таблицы. Каждый пакет, в зависимости от того, предназначен ли он самому хосту, сгенерирован им или является транзитным, должен пройти положенный ему набор базовых цепочек различных таблиц. Схема следования пакетов приведена на рисунке. Кроме того, базовая цепочка отличается от пользовательской наличием «действия по умолчанию» (default policy). Это действие применяется к тем пакетам, которые не были обработаны другими правилами этой цепочки и вызванных из нее цепочек (см. переходы). Имена базовых цепочек всегда записываются в верхнем регистре (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING).
** '''Пользовательская цепочка'''  — цепочка, созданная пользователем. Может использоваться только в пределах своей таблицы. Рекомендуется не использовать для таких цепочек имена в верхнем регистре, чтобы избежать путаницы с базовыми цепочками и встроенными действиями.
* '''Таблица'''  — совокупность ''базовых'' и ''пользовательских'' цепочек, объединенных общим функциональным назначением. Имена таблиц (как и модулей критериев) записываются в нижнем регистре, так как в принципе не могут конфликтовать с именами пользовательских цепочек. При вызове команды iptables таблица указывается в формате <tt>-t имя_таблицы</tt>. При отсутствии явного указания, используется таблица filter. Более подробно таблицы будут рассмотрены ниже.
 
=== Принцип работы ===
 
Все пакеты пропускаются через определенные для них последовательности цепочек (см. рис.). При прохождении пакетом цепочки, к нему последовательно применяются все правила этой цепочки в порядке их следования. Под применением правила понимается: во-первых, проверка пакета на соответствие критерию, и во-вторых, если пакет этому критерию соответствует, применение к нему указанного действия. Под действием может подразумеваться как элементарная операция (встроенное действие, например, ACCEPT, MARK), так и переход в одну из пользовательских цепочек. В свою очередь, действия могут быть как терминальными, то есть прекращающими обработку пакета в рамках данной базовой цепочки (например, ACCEPT, REJECT), так и нетерминальными, то есть не прерывающими процесса обработки пакета (MARK, TOS). Если пакет прошел через всю базовую цепочку и к нему так и не было применено ни одного терминального действия, к нему применяется действие по умолчанию для данной цепочки (обязательно терминальное). Например,
<source lang="bash">
Строка 51 ⟶ 49 :
iptables -P OUTPUT ACCEPT # Разрешаем все исходящие пакеты
</source>
Теперь цепочка INPUT таблицы filter содержит единственное правило, которое пропускает все пакеты, относящиеся к уже установленным соединениям. Ко всем остальным входящим пакетам будет применено действие по умолчанию  — DROP. Цепочка же OUTPUT вообще не содержит правил, поэтому ко всем исходящим пакетам будет применяться действие по умолчанию ACCEPT. Таким образом хост, настроенный согласно этому примеру и подключенный к {{w |Интернет}}у, будет недоступен извне (все попытки установить соединение снаружи блокируются), однако с самого хоста доступ к Интернету будет свободный (исходящие пакеты разрешены, а ответы на них уже относятся к установленным соединениям).
 
=== Основные компоненты ===
 
==== netfilter ====
<!-- Пока здесь будет англоязычный оригинал. Постараюсь в ближайшее время перевести — FIXED -->
 
<!-- Пока здесь будет англоязычный оригинал. Постараюсь в ближайшее время перевести — FIXED -->
[[Файл:Netfilter-components-ru.svg|600px|thumb|Взаимосвязь основных компонентов netfilter и conntrack]]
<!-- Поставил 600, потому что иначе нифига не разглядеть. С удовольствием приму ценные предложения по улучшению верстки для небольших экранных разрешений -->
 
Компонент ядра [[Linux]], обеспечивающий фильтрацию и модификацию трафика. Собственно, именно он и является фаерволом. В состав netfilter входят следующие модули:
* '''ip_tables'''  — фаервол для протокола [[w:IPv4|IPv4]]. Обеспечивает фильтрацию пакетов, модификацию их заголовков и [[w:NAT|трансляцию сетевых адресов]].
* '''ip6_tables'''  — фаервол для протокола [[w:IPv6|IPv6]]. Обеспечивает фильтрацию пакетов и модификацию их заголовков.
* '''arp_tables'''  — фаервол для протоколов [[w:ARP|ARP]] и [[w:RARP|RARP]]. Обеспечивает фильтрацию и модификацию пакетов.
* '''x_tables'''  — бэкенд для ip_tables, ip6_tables и arp_tables. В этом модуле определены основные операции для работы с фаерволами «таблично-цепочечной» структуры и их компонентами.
* '''ebtables'''  — [[w:Ethernet|Ethernet]]-фаервол (префикс eb от Ethernet Bridge). В отличие от трех перечисленных выше фаерволов, работающих с протоколами [[w:Сетевой уровень|сетевого]] и более высоких уровней, ebtables работает на канальном уровне, выполняя фильтрацию и модификацию ethernet-кадров, проходящих через [[w:Сетевой мост|сетевые мосты]], если таковые имеются на хосте.
 
Принципы работы с ip_tables и ip6_tables практически идентичны, с тем небольшим отличием, что в ip6_tables отсутствует таблица nat и соответствующие действия (NAT уже присутствует в ip6tables). В то же время, принципы построения правил в arp_tables и ebtables несколько иные. В частности, arp_tables и ebtables имеют четыре базовых действия  — ACCEPT (пропустить), DROP (заблокировать), CONTINUE (продолжить обработку в данной цепочке) и RETURN (прекратить обработку в данной цепочке, вернуть в цепочку уровнем выше). Эти действия могут использоваться отдельно, либо применяться к пакетам после выполнения какого-либо преобразующего действия (например, маркировки). Таким образом, после применения преобразования пакет может быть, скажем, немедленно пропущен фаерволом (ACCEPT), либо будет вынужден проследовать через последующие правила (CONTINUE). Этим arptables и ebtables отличаются от ip_tables и ip6_tables  — в последних существует четкое разделение действий на терминальные и нетерминальные, которое нельзя изменить при составлении набора правил, а чтобы, например, пропустить пакет после некоторого нетерминального преобразования, необходимо добавлять дополнительное правило («<tt>iptables ... -j MARK ...; iptables ... -j ACCEPT</tt>» вместо «<tt>ebtables ... -j mark ... --mark-target ACCEPT</tt>»). Также, система conntrack не&nbsp; производит отслеживание соединений для ARP/RARP и Ethernet, поэтому возможности stateful-фильтрации в arp_tables и ebtables отсутствуют (нет критерия conntrack и таблицы raw).
 
В данной статье рассматриваются только аспекты работы с ip_tables и ip6_tables. В их задачи входит:
* Классификация пакетов на основе различных критериев. В качестве критерия могут выступать, например, [[w:IP-адрес|IP-адресадреса]]а источника и/или назначения, состояние соединения (новое/уже установленное), [[w:Порт (TCP/IP)|порты]] источника и/или назначения (для протоколов [[w:Транспортный уровень|транспортного уровня]], имеющих порты), вспомогательные значения в заголовках пакетов (скажем, длина пакета, [[w:Type_of_ServiceType of Service|TOS]], [[w:Time_to_liveTime to live|TTL]]) и  т.  п. Результаты этой классификации используются при решении других задач из данного списка.
* Фильтрация входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов, сводящаяся либо к их пропусканию (ACCEPT), либо к блокированию (DROP или REJECT). Также поддерживаются дополнительные возможности, например, блокирование попыток сканирования портов (DELUDE и CHAOS), эффективное противодействие [[w:DoS-атака|(D)DoS-атакам]] (TARPIT).
* Модификация заголовков пакетов и связанной информации. К этому классу задач можно отнести:
** Трансляцию сетевых адресов ([[w:NAT|NAT]]), включая [[w:маскарадинг|маскарадинг]] (SNAT или MASQUERADE), [[w:Трансляция_портТрансляция порт-адрес|«проброс»]] адресов и портов (DNAT) и даже целых подсетей (NETMAP). Эта задача касается только модуля ip_tables. Модуль ip6_tables не&nbsp; производит трансляции адресов.
** Изменение различных вспомогательных величин в заголовках пакетов, например, [[w:Type_of_ServiceType of Service|TOS]], [[w:Time_to_liveTime to live|TTL]], [[:en:Maximum Segment Size|TCP MSS]].
** Установку и изменение маркировки пакетов и соединений. Впоследствии эта маркировка может быть использована системой [[w:iproute2|iproute2]] для [[w:Маршрутизация|маршрутизации]] и [[w:Шейпинг (информатика)|шейпинга]] трафика.
* Учет количества обработанных пакетов и их суммарного размера при помощи счетчиков.
* Занесение информации о пакетах в [[w:syslog|системный журнал]] (LOG и LOGMARK).
* Передача на обработку userspace-[[w:Демон (программа)|демонам]] пакетов целиком (NFQUEUE) либо информации о них (NFLOG), что позволяет решать самый широкий круг задач по фильтрации, модификации и учету трафика.
* Внутренние задачи, связанные с обеспечением работы критериев и действий netfilter. Например, сопровождение списков [[w:IP-адрес|IP-адресадресов]]ов для критериев recent и hashlimit.
 
==== iptables ====
Userspace-утилита, через которую [[w:Root|системный администратор]] может управлять {{w |IPv4}}-фаерволом (ip_tables). К ее задачам относятся:
 
Userspace-утилита, через которую [[w:Root |системный администратор]] может управлять {{w |IPv4}}-фаерволом (ip_tables). К ее задачам относятся:
* Создание и удаление пользовательских цепочек.
* Установка действий по умолчанию для базовых цепочек.
Строка 92 ⟶ 88 :
* Проверка корректности задания параметров, определяющих работу критериев и действий.
* Вывод справки по использованию критериев (<tt>iptables -m ''критерий'' -h</tt>) и действий (<tt>iptables -j ''действие'' -h</tt>).
Также в комплект поставки вместе с iptables обычно входят вспомогательные утилиты, обеспечивающие сохранение (iptables-save) и последующее восстановление (iptables-restore) состояния фаервола, его инициализацию при запуске системы ({{w |init}}-скрипт) и  т.  п.
 
Сегментом фаервола, отвечающим за фильтрацию {{w |IPv6}}-пакетов (ip6_tables), управляет утилита ip6tables. Так как обычно она поставляется вместе с iptables, имеет похожий синтаксис и выполняет схожие задачи, под термином «iptables» часто подразумевают сразу обе эти утилиты.
 
Также в рамках данного проекта разрабатываются два набора библиотек:
* '''libiptc'''  — содержит функции, осуществляющие вышеперечисленные операции по управлению цепочками и правилами. Именно с этими функциями и работают утилиты iptables (библиотека libip4tc) и ip6tables (библиотека libip6tc). Приложения, использующие эти библиотеки, могут обращаться к netfilter напрямую, минуя вызов утилит iptables и ip6tables. В качестве примера такого приложения можно назвать [[Perl]]-модуль [http://search.cpan.org/~hawk/IPTables-libiptc-0.18/lib/IPTables/libiptc.pm IPTables::libiptc], предоставляющий доступ к функциям этих библиотек из Perl-{{w |скрипт}}ов.
* '''libipq'''  — содержит функции, позволяющие пользовательским приложениям принимать [[IP-пакет]]ы на обработку. Отправка со стороны ядра выполняется через модуль ip_queue (ip6_queue для IPv6), что соответствует действию QUEUE. В настоящее время этот механизм [http://netfilter.org/projects/libnetfilter_queue/index.html объявлен устаревшим], и вместо него рекомендуется использовать действие NFQUEUE, работа которого реализуется через модуль ядра nfnetlink_queue и библиотеку libnetfilter_queue.
 
==== conntrack ====
 
Компонент netfilter, обеспечивающий отслеживание состояния соединений и классификацию пакетов с точки зрения принадлежности к соединениям, что позволяет netfilter осуществлять полноценную stateful-фильтрацию трафика. Как и netfilter, система conntrack является частью ядра [[Linux]]. К его задачам относятся:
* Отслеживание состояний отдельных соединений с тем, чтобы классифицировать каждый пакет либо как относящийся к уже установленному соединению, либо как открывающий новое соединение. При этом понятие "«состояние соединения"» искусственно вводится для протоколов, в которых оно изначально отсутствует ({{w |UDP}}, {{w |ICMP}}). При работе же с протоколами, поддерживающими состояния (например, {{w |TCP}}), conntrack активно использует эту возможность, тесно взаимодействуя с базовой сетевой подсистемой ядра Linux.
* Отслеживание связанных соединений, например, {{w |ICMP}}-ответов на {{w |TCP}} и {{w |UDP}}-пакеты. Более сложный вариант  — протоколы, использующие несколько соединений в одной сессии, например, {{w |FTP}}. Для правильной обработки таких протоколов conntrack использует специальные модули (conntrack helpers), которые анализируют трафик и «выхватывают» информацию протокола о новых соединениях (например, порт, на который оно будет открыто), что позволяет обеспечить их корректную фильтрацию, маршрутизацию, шейпинг и пропускание через NAT.
 
Более подробно о возможностях системы conntrack и их использовании при работе с iptables/netfilter см. [[#Механизм определения состояний|чуть ниже]].
Строка 110 ⟶ 105 :
В состав conntrack входят следующие компоненты:
* Главный модуль nf_conntrack. Реализует базовую функциональность отслеживания соединений, интерфейсы для работы с модулями расширений, а также механизмы отслеживания протоколов {{w |TCP}} и {{w |UDP}}.
* Трекеры протоколов [[w:Протоколы сетевого уровня |сетевого уровня]]: nf_conntrack_ipv4 и nf_conntrack_ipv6. Реализуют операции, специфичные для «своих» протоколов ({{w |IPv4}} и {{w |IPv6}} соответственно), а также механизмы отслеживания соответствующих протоколов управляющих сообщений ({{w |ICMP}} и {{w |ICMPv6}} соответственно).
* Трекеры протоколов [[w:Транспортный уровень |транспортного уровня]] (кроме {{w |TCP}} и {{w |UDP}}, реализованных в главном модуле): nf_conntrack_proto_sctp ({{w |SCTP}}), nf_conntrack_proto_dccp ({{w |DCCP}}), nf_conntrack_proto_gre ([[w:GRE (протокол) |GRE]]), nf_conntrack_proto_udplite ({{w |UDP Lite}}).
* Вспомогательные модули (helpers), обеспечивающие отслеживание протоколов [[w:Протоколы прикладного уровня |прикладного]] и [[w:Сеансовый уровень |сеансового]] уровней: nf_conntrack_ftp, nf_conntrack_irc, nf_conntrack_pptp, nf_conntrack_netbios_ns и  т.  п. Требуются далеко не&nbsp; для всех протоколов, а только для тех, отслеживание которых требует знания специфики протокола. Например, неоднократно упоминающийся в этой статье протокол {{w |FTP}} использует в одном сеансе два соединения (управляющее соединение и соединение передачи данных), и чтобы корректно отследить соединение передачи данных, необходимо анализировать трафик управляющего соединения и выделять в нем информацию, касающуюся открытия соединения данных.
* Модуль nf_nat. Реализует базовую функциональность [[w:NAT |трансляции сетевых адресов]] и [[w:Трансляция порт-адрес |портов]] с учетом информации о соединениях. Также этот модуль содержит механизмы трансляции для протоколов {{w |IPv4}}, {{w |TCP}}, {{w |UDP}} и {{w |ICMP}} ({{w |IPv6}} и {{w |ICMPv6}} не&nbsp; поддерживаются NAT-подсистемой conntrack).
* NAT-трекеры протоколов [[w:Транспортный уровень |транспортного уровня]]: nf_nat_proto_sctp, nf_nat_proto_dccp, nf_nat_proto_gre, nf_nat_proto_udplite.
* Вспомогательные модули NAT для протоколов [[w:Протоколы прикладного уровня |прикладного]] и [[w:Сеансовый уровень |сеансового]] уровней: nf_nat_ftp, nf_nat_irc, nf_nat_pptp и  т.  п.
* Модуль взаимодействия с userspace через протокол nfnetlink (см. следующий раздел) nf_conntrack_netlink, которому соответствует userspace-библиотека libnetfilter_conntrack.
* Кроме того, к conntrack можно условно отнести и модули netfilter, обеспечивающие взаимодействие этих двух подсистем: критерий conntrack (xt_conntrack), действия NOTRACK и CT (xt_NOTRACK и xt_CT), практически все действия [[#Таблица nat|таблицы nat]], а также соответствующие модули (библиотеки iptables/ip6tables): libxt_conntrack, libxt_NOTRACK, libxt_CT и  т.  п.
 
Для взаимодействия с системой conntrack из userspace разработан комплект [http://conntrack-tools.netfilter.org/ conntrack-tools], содержащий две утилиты:
* '''conntrack'''  — инструмент, позволяющий [[w:Root |системному администратору]] наблюдать таблицы состояний соединений и взаимодействовать с ними: очищать таблицы целиком, удалять отдельные записи, маркировать соединения вручную (аналог действия CONNMARK), устанавливать [[Тайм-аут (Телекоммуникации)|тайм-аутауты]]ы соединений. Поддерживается фильтрация вывода (например, на основании адресов и/или портов источника и/или назначения), а также вывод в различных форматах, включая {{w |XML}}. Кроме того, данная утилита позволяет отслеживать в реальном времени события системы conntrack, например, открытие новых соединений или изменение состояния существующих.
* '''conntrackd'''  — демон, обеспечивающий синхронизацию таблиц состояний с другими хостами, что в сочетании с возможностями демона [[keepalived]] позволяет создавать фаерволы на {{w |кластер}}ах высокой доступности (High Availability)  — при выходе из строя одного из хостов кластера его соединения будут «подхвачены» другими хостами кластера и корректно обработаны с учетом состояний. Также conntrackd можно использовать просто для удаленного сбора статистики по соединениям.
 
Взаимодействие conntrack с этими программами производится посредством интерфейса nfnetlink, который будет рассмотрен в следующем разделе.
 
==== nfnetlink ====
 
Интерфейс, позволяющий различным userspace-приложениям взаимодействовать с netfilter и conntrack. Со стороны userspace он обеспечивается набором библиотек libnfnetlink. Ключевые библиотеки из этого набора:
* '''libnetfilter_conntrack''' (ранее libnfnetlink_conntrack и libctnetlink)  — обеспечивает взаимодействие приложений с системой conntrack. В качестве примеров приложений, использующих эту библиотеку, можно упомянуть:
** Описанные выше программы '''conntrack''' и '''conntrackd''' из комплекта conntrack-tools.
** '''iptstate'''  — в какой-то мере аналог утилиты conntrack, хотя и не&nbsp; имеющий таких богатых возможностей. Предназначена для непрерывного вывода таблицы состояний соединений с периодическим обновлением, в стиле широко известной утилиты {{w |top}}. Поддерживает различные виды сортировки (по адресам/портам источника/назначения, [[Тайм-аут (Телекоммуникации)|тайм-ауту]], счетчикам и  т.  п.). Позволяет удалять записи из таблицы состояний. Не&nbsp; поддерживает работу с таблицей ожидаемых (expected) соединений.
* '''libnetfilter_queue''' (ранее libnfnetlink_queue)  — отвечает за передачу пакетов демонам на предмет анализа. По результатам этого анализа пакет может быть заблокирован или пропущен. При пропускании пакета возможна установка или изменение его маркировки (nfmark). Идеологическим предшественником libnetfilter_queue была ныне устаревшая библиотека libipq. В качестве примеров приложений, использующих libnetfilter_queue, можно упомянуть:
** '''nufw'''  — фаервол, выполняющий фильтрацию трафика на основе авторизации пользователей. Позволяет устанавливать ограничения на доступ к сетям, находящимся за фаерволом, для отдельных пользователей. Авторизация пользователей на фаерволе обеспечивается отдельным демоном nuauth. Например, в случае, если клиенты используют [[Linux]], авторизация может выполняться совершенно прозрачно, благодаря возможностям {{w |PAM}} (модуль pam_nufw) в момент входа пользователя в систему. Особенно удобны подобные системы в корпоративных сетях, где используются системы централизованного управления аккаунтами пользователей (nufw/nuauth поддерживает {{w |LDAP}} и [[winbind]]).
** '''{{w |l7-filter}}-userspace'''  — демон, позволяющий определить протокол [[w:Протоколы прикладного уровня |7-го (прикладного) уровня]] [[w:Сетевая модель OSI |модели OSI]], которому принадлежит полученный пакет, на основании анализа его содержимого при помощи [[Регулярные выражения|регулярных выражений]]. Результат анализа возвращает в маркировке пакета. Полезен при фильтрации и [[w:Шейпинг (информатика) |шейпинге]] трафика протоколов, не&nbsp; имеющих фиксированных номеров портов для соединений данных, например, [[BitTorrent]]. Впрочем, в настоящее время существуют и альтернативные решения  — {{w |P2P}}-протоколы можно выделять при помощи критерия ipp2p (из набора xtables-addons), а вспомогательные соединения в известных системе conntrack протоколах ({{w |FTP}}, {{w |IRC}}, {{w |SIP}}) можно выделять при помощи критерия helper и маркировки соединений.
** '''iplist'''  — userspace-альтернатива ipset. Как и ipset, позволяет считывать большие списки {{w |IP-адрес}}ов и проверять пакеты на предмет нахождения адреса их источника/назначения в данном списке. В зависимости от результата проверки, пакет может быть пропущен или заблокирован, либо промаркирован соответствующим образом. Разумеется, ipset, работая на уровне ядра, обеспечивает более высокую скорость проверки, а также поддерживает дополнительные возможности, например, динамическое изменение списков при помощи действия SET (добавление и удаление записей), сохранение дополнительной информации (номера [[w:Порт (компьютерные сети) |портов]], {{w |MAC-адрес}}а, [[Тайм-аут (Телекоммуникации)|тайм-ауты]] записей). Несмотря на то, что в настоящий момент ipset пока что не&nbsp; принят в ядро, современные дистрибутивы ipset позволяет произвести сборку и установку необходимых компонентов без необходимости наложения {{w |патч}}ей на ядро и iptables, благодаря возможностям подгружаемых модулей ([[:en:LKM]]) ядра [[Linux]]. Поэтому, с учетом вышесказанного, необходимость в iplist в настоящее время сомнительна.
* '''libnetfilter_log''' (ранее libnfnetlink_log)  — предоставляет демонам интерфейс для получения служебной информации о пакетах на предмет регистрации и учета трафика. В настоящее время известен только один проект, использующий данную библиотеку  — '''ulogd2''' ([netfilter] userspace logging daemon, версия&nbsp; 2). Данный проект находится пока в бета-стадии разработки. Надо заметить, что ulogd2 может получать информацию не&nbsp; только через libnetfilter_log (действие NFLOG), но и через классический механизм libipulog (действие ULOG), а также через libnetfilter_conntrack (данный метод позволяет получать информацию не&nbsp; об отдельных пакетах, а о соединениях в целом).
 
Со стороны ядра взаимодействие обеспечивается базовым модулем nfnetlink и «специализированными» модулями nf_conntrack_netlink, nfnetlink_queue и nfnetlink_log соответственно.
Строка 142 ⟶ 136 :
 
==== ipset ====
Представляет собой набор инструментов, позволяющий работать с большими списками (sets) {{w |IP-адрес}}ов и/или [[w:Порт (компьютерные сети)|портов]]. Поддерживается возможность динамического обновления списков при прохождении пакетов через правила {{w |netfilter}}.
 
В версии ipset 4 и более ранних поддерживалась работа только с семейством адресов {{w |IPv4}}, однако начиная с пятой версии реализована также и поддержка {{w |IPv6}}.
Представляет собой набор инструментов, позволяющий работать с большими списками (sets) {{w |IP-адрес}}ов и/или [[w:Порт (компьютерные сети) |портов]]. Поддерживается возможность динамического обновления списков при прохождении пакетов через правила {{w |netfilter}}.
 
Стоит отметить, что долгое время проект ipset существовал вне основной ветки развития [[w:Ядро Linux|ядра Linux]]. В частности, в четвертой версии ipset «ядерные» компоненты приходилось собирать отдельно, используя заголовочные файлы текущего ядра. Однако, после выхода пятой версии, в которой были учтены все предыдущие замечания, началась работа по включению ipset в основную ветку. Она [http://www.spinics.net/lists/netfilter-devel/msg17027.html завершилась успехом]: поддержка ipset присутствует в Linux начиная с 2.6.39. В ходе этих работ протокол взаимодействия ядерной и userspace-частей ipset подвергся значительной переработке, и окончательная версия [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=ipset.git;a=commit;h=d6ee5bb4e5346b84efa33858091ba4add2b26de2 получила] номер 6.0. Таким образом, в современных ядрах поддержка ipset присутствует штатно, а пользователи более старых ядер могут воспользоваться реализациями ipset версий 4 и 5, включенными в набор [http://xtables-addons.sourceforge.net/ xtables-addons].
В версии ipset&nbsp;4 и более ранних поддерживалась работа только с семейством адресов {{w |IPv4}}, однако начиная с пятой версии реализована также и поддержка {{w |IPv6}}.
 
Стоит отметить, что долгое время проект ipset существовал вне основной ветки развития [[w:Ядро Linux |ядра Linux]]. В частности, в четвертой версии ipset «ядерные» компоненты приходилось собирать отдельно, используя заголовочные файлы текущего ядра. Однако, после выхода пятой версии, в которой были учтены все предыдущие замечания, началась работа по включению ipset в основную ветку. Она [http://www.spinics.net/lists/netfilter-devel/msg17027.html завершилась успехом]: поддержка ipset присутствует в Linux начиная с 2.6.39. В ходе этих работ протокол взаимодействия ядерной и userspace-частей ipset подвергся значительной переработке, и окончательная версия [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=ipset.git;a=commit;h=d6ee5bb4e5346b84efa33858091ba4add2b26de2 получила] номер 6.0. Таким образом, в современных ядрах поддержка ipset присутствует штатно, а пользователи более старых ядер могут воспользоваться реализациями ipset версий 4 и 5, включенными в набор [http://xtables-addons.sourceforge.net/ xtables-addons].
 
ipset состоит из следующих элементов:
* Модуль ядра ip_set, обеспечивающий базовый инструментарий работы со списками записей, который используется модулями расширений.
* Модули расширений, определяющие конкретные структуры записей и методы работы с ними, например, ip_set_hash_ip (тип данных hash: ip), ip_set_bitmap_port (тип данных bitmap: port) и  т.  д.
* Userspace-утилита ipset, позволяющая выполнять различные операции со списками и записями в них:
** Создание, удаление, переименование, вывод, очистка списков.
** Добавление и удаление записей из списков, проверка наличия записи в списке.
** Вывод справочной информации по работе со списками различного типа.
* Модули расширений для утилиты ipset, соответствующие модулям расширений в ядре, например, ipset_hash_ip (тип данных hash: ip), ipset_bitmap_port (тип данных bitmap: port) и  т.  д. Каждый такой модуль отвечает за обеспечение {{w |интерфейс}}а между «своим» модулем ядра и конечным пользователем, в частности, проверку корректности вводимых и форматирование выводимых данных, а также вывод справочной информации по допустимым командам и параметрам. В ранних версиях ipset (до 4 включительно) такие модули выделялись в виде подгружаемых библиотек, однако в современных версиях ipset они статически включаются в основной бинарник, поэтому разделение существует лишь в исходном коде.
* Модуль netfilter xt_set (критерий set и действие SET), а также соответствующие модули (библиотеки) iptables (libxt_set и libxt_SET). Критерий set позволяет проверять различные параметры пакета ([[w:IP-адрес |IP]]/{{w |MAC-адрес}}а, {{w |TCP}}/{{w |UDP}}-[[w:Порт (компьютерные сети) |порты]] источника и/или получателя) на предмет нахождения или отсутствия в списке. Действие SET позволяет добавлять или удалять записи из списка на основании указанных параметров пакета. <!-- Отметим, что, начиная с версии iptables 1.4.9 {{w |IPv4}}-специфичные модули libipt_set и libipt_SET [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=commit;h=d40f1628c3717daebc437a398a285e371b5b6f7f заменены] на более универсальные libxt_set и libxt_SET, которые могут использоваться как в iptables, так и в ip6tables. -->
 
ipset поддерживает следующие типы данных (в скобках приведены названия согласно терминологии устаревшей версии ipset&nbsp; 4):
* '''bitmap: ip''' (ipmap)  — полный перечень {{w |IP-адрес}}ов.
* '''bitmap: ip, mac''' (macipmap)  — полный перечень IP-адресов, причем вместе с каждым IP-адресом может быть сохранен {{w |MAC-адрес}}.
* '''bitmap: port''' (portmap)  — полный перечень [[w:Порт (компьютерные сети) |портов]].
* '''hash: ip''' (iphash)  — выборочный перечень IP-адресов (либо IP-подсетей с одинаковой маской).
* '''hash: net''' (nethash)  — выборочный перечень IP-подсетей (блоков IP-адресов). В отличие от hash: ip, в одном списке могут присутствовать подсети с различными масками.
* '''hash: ip, port''' (ipporthash)  — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт. В версии ipset&nbsp; 4 и более ранних существует ограничение: адреса в пределах одного перечня должны принадлежать одному [[w:Бесклассовая адресация |блоку /16]] (/255.255.0.0, максимум 65536 адресов). Начиная с версии ipset&nbsp; 5, для каждого номера порта можно также сохранять идентификатор протокола [[w:Транспортный уровень |транспортного уровня]].
* '''hash: ip, port, ip''' (ipportiphash)  — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и еще один IP-адрес. В версии ipset&nbsp; 4 и более ранних ограничение на «первичные» адреса (первые в тройке адрес-порт-адрес) такое же, как и для ipporthash. Начиная с версии ipset&nbsp; 5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня.
* '''hash: ip, port, net''' (ipportnethash)  — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и IP-подсеть. В версии ipset&nbsp; 4 и более ранних ограничение на «первичные» адреса такое же, как и у типа ipporthash. Начиная с версии ipset&nbsp; 5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня.
* '''list: set''' (setlist)  — список списков. Может содержать списки любого перечисленного здесь типа, кроме list: set. При обращении к такому объекту из netfilter, включенные в него списки рассматриваются как один большой список. Поиск записей (критерий set) производится по всем вложенным спискам соответствующего типа. При добавлении записей (действие SET), вложенные списки поочередно проверяются (согласно порядку их перечисления) на соответствие типа и наличие свободного места, и запись добавляется в первый же подходящий. В то же время, при обращении к такому списку через утилиту ipset, он рассматривается именно как совокупность элементов-списков, что позволяет добавлять, удалять и проверять наличие именно вложенных списков, но не их элементов.
* '''hash: net, iface'''  — выборочный перечень IP-подсетей, причем с каждой подсетью может быть сохранено название сетевого интерфейса. Появился в версии ipset 6.7 (входит в [[w:Ядро Linux |Linux]] 3.1), ранние версии ipset не имеют подобных возможностей. Существует ограничение: нельзя сохранять более 64 имен интерфейсов с одним и тем же адресом подсети. Этот тип данных удобен при наличии в системе большого количества сетевых интерфейсов (например, сотен {{w |VLAN}}-интерфейсов).
 
В четвертой версии дополнительно присутствовали два типа списков, упраздненные в более поздних версиях:
* '''iptree'''  — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранено значение [[Тайм-аут (Телекоммуникации)|тайм-аута]] в секундах. По истечении тайм-аута адрес удаляется из списка. Чтобы активировать возможность использование тайм-аутов для определенного списка, нужно при его создании задать тайм-аут по умолчанию (опция <tt>--timeout</tt>). Начиная с версии ipset&nbsp; 5, данный тип не&nbsp; поддерживается, при попытке его использования автоматически заменяется на hash: ip. Заметим, что начиная с пятой версии тайм-ауты реализованы для всех поддерживаемых типов данных.
* '''iptreemap'''  — гибридный перечень, позволяющий сохранять адреса, блоки и диапазоны адресов. Начиная с версии ipset&nbsp; 5, данный тип не&nbsp; поддерживается, при попытке его использования автоматически заменяется на hash: ip. Стоит отметить, что в современных версиях ipset при работе с адресами IPv4 можно указывать диапазоны адресов и подсети, которые при обращении к внутренним спискам будут автоматически преобразованы в наборы соответствующих элементов, Например, <tt>ipset create foo hash:ip; ipset add foo 192.168.0.0-192.168.0.3</tt> добавит в список <tt>foo</tt> адреса 192.168.0.0, 192.168.0.1, 192.168.0.2 и 192.168.0.3 (аналогичный эффект может быть достигнут и командой <tt>ipset add foo 192.168.0.0/30</tt>).
 
Практически для всех типов списков, реализованных в ipset, существует общее ограничение на максимальный размер: 65536 записей.
Строка 179 ⟶ 172 :
Большинство перечисленных типов данных можно разделить на две группы: полные перечни (map, bitmap) и выборочные перечни (hash, tree). Разница между этими типами состоит в следующем: если выборочный перечень сохраняет только те элементы, которые в него входят, то полный перечень представляет собой таблицу логических значений ({{w |бит}}ов) для всех элементов, которые могут входить в данный перечень, и вхождение конкретного элемента в перечень определяется значением соответствующего бита. Полный перечень всегда формируется на базе ''одного непрерывного'' диапазона значений.
 
Таким образом, выбор необходимого вам типа данных определяется конкретными условиями задачи, прежде всего, отношением усредненного количества элементов в списке к требуемому диапазону охвата. Например, если вы собираетесь хранить в списке блэк-листы адресов, замеченных в атаках на ваш сервер, целесообразнее использовать тип hash: ip, потому что атакующие вас ботнеты, как бы они ни&nbsp; были велики, все равно занимают незначительную долю адресного пространства {{w |IPv4}}. К тому же, как следует из сказанного в предыдущем абзаце, тип bitmap: ip все равно не&nbsp; может хранить адреса, выходящие за предел одной подсети [[w:Бесклассовая адресация |префикса&nbsp; 16]]. Но в том случае, если вам, например, нужно задать список хостов из вашей локальной сети, имеющих доступ к каким-либо услугам (службам вашего {{w |сервер}}а, выходу в {{w |Интернет}}), и этот доступ должно иметь значительное количество хостов (а не&nbsp; единицы), то целесообразнее будет использовать bitmap: ip.
 
По поводу хранения адресов подсетей ([[w:Бесклассовая адресация |блоков]] {{w |IP-адрес}}ов) можно сказать следующее. Если вам нужно хранить большое количество блоков одного размера из ограниченного диапазона (не&nbsp; более 65536 возможных значений), например, блоки /24 из подсети /8, вы можете использовать тип bitmap: ip, указав маску. Если же вам нужно хранить блоки одного размера из достаточно широкого диапазона, например, /24 из всего адресного пространства {{w |IPv4}}, используйте тип hash: ip, также с указанием маски. При необходимости хранить в одном списке блоки ''разного'' размера, воспользуйтесь типом hash: net.
 
Что касается улучшений в версиях 5 и 6 по сравнению с четвертой и более ранними, то, помимо уже упомянутых (поддержка адресов {{w |IPv6}}, поддержка [[Тайм-аут (Телекоммуникации)|тайм-аутов]] для всех типов данных, возможность сохранения идентификатора протокола транспортного уровня в типах hash: ip, port, hash: ip, port, ip и hash: ip, port, net), стоит также отметить переход на использование nfnetlink (см. выше) для связи ядра и userspace, а также более простой синтаксис. Например, те действия, которые в ipset&nbsp; 4 выглядели бы так:
<source lang="bash">
ipset -N foo macipmap --network 192.168.0.0/16 # Создаем список
Строка 201 ⟶ 194 :
ipset destroy foo
</source>
Кроме того, современные версии ipset поддерживают работу в режиме простой [[w:Командный интерпретатор |оболочки]], принимающей команды со [[stdin]]. При этом в них обеспечивается полная обратная совместимость синтаксиса с четвертой версией, то есть синтаксис, корректно работающий для четвертой версии ipset, будет точно так же работать в пятой и шестой.
 
==== ipvs ====
Разработанный в рамках проекта [http://www.linuxvirtualserver.org/ Linux Virtual Server] инструментарий для балансировки входящих соединений на [[w:Транспортный уровень|транспортном уровне]], позволяющий создавать отказоустойчивые (highly available, HA) [[w:Кластер (группа компьютеров)|кластеры]] с балансировкой нагрузки. В структуру такого кластера входит один или несколько хостов-балансировщиков (front-end), а также группа хостов-обработчиков (back-end). Хост-балансировщик принимает входящие соединения и перенаправляет их на хосты-обработчики, причем выбор хоста-обработчика осуществляется по специальному алгоритму, обеспечивающему гибкое распределение нагрузки между обработчиками. В кластере также могут присутствовать дополнительные (резервные) балансировщики, которые вступают в игру в случае отказа основного балансировщика.
 
Как правило, IPVS работает в связке с демоном [[keepalived]], который обеспечивает отказоустойчивость балансировщика (с использованием протокола [[:en:VRRP|VRRP]]) и поддержку в актуальном состоянии списка обработчиков (демон периодически проверяет работоспособность обработчиков и выводит из состава кластера неработоспособные хосты). Также допускается «ручное» управление настройками кластера — через программу [[ipvsadm]].
Разработанный в рамках проекта [http://www.linuxvirtualserver.org/ Linux Virtual Server] инструментарий для балансировки входящих соединений на [[w:Транспортный уровень |транспортном уровне]], позволяющий создавать отказоустойчивые (highly available, HA) [[w:Кластер (группа компьютеров) |кластеры]] с балансировкой нагрузки. В структуру такого кластера входит один или несколько хостов-балансировщиков (front-end), а также группа хостов-обработчиков (back-end). Хост-балансировщик принимает входящие соединения и перенаправляет их на хосты-обработчики, причем выбор хоста-обработчика осуществляется по специальному алгоритму, обеспечивающему гибкое распределение нагрузки между обработчиками. В кластере также могут присутствовать дополнительные (резервные) балансировщики, которые вступают в игру в случае отказа основного балансировщика.
 
Как уже упоминалось выше, IPVS обеспечивает балансировку нагрузки на транспортном уровне, то есть конфигурационной единицей IPVS является ''кластерная служба''. Она характеризуется адресом ({{w |IPv4}} или {{w |IPv6}}), протоколом транспортного уровня (на данный момент IPVS поддерживает протоколы {{w |TCP}}, {{w |UDP}} и {{w |SCTP}}) и номером [[w:Порт (компьютерные сети)|порта]]. Обычно для кластерных служб выделяется отдельный адрес, который присваивается активному (на данный момент) балансировщику. В случае его отказа, адрес автоматически передается резервному балансировщику, и кластер продолжает работу. Обратите внимание, что обеспечением отказоустойчивости занимается не IPVS, а keepalived. Впрочем, использование keepalived не является строго обязательным — существуют и альтернативные подходы, например, встраивание IPVS в кластерный стек [http://linux-ha.org/ Linux-HA] (см. [[:en:Heartbeat (program)|Heartbeat]]). В том случае, если отказоустойчивость не критична (требуется только балансировка нагрузки), можно вообще обойтись без дополнительного демона, выполняя всю настройку через ipvsadm.
Как правило, IPVS работает в связке с демоном [[keepalived]], который обеспечивает отказоустойчивость балансировщика (с использованием протокола [[:en:VRRP|VRRP]]) и поддержку в актуальном состоянии списка обработчиков (демон периодически проверяет работоспособность обработчиков и выводит из состава кластера неработоспособные хосты). Также допускается «ручное» управление настройками кластера — через программу [[ipvsadm]].
 
Как уже упоминалось выше, IPVS обеспечивает балансировку нагрузки на транспортном уровне, т.е. конфигурационной единицей IPVS является ''кластерная служба''. Она характеризуется адресом ({{w |IPv4}} или {{w |IPv6}}), протоколом транспортного уровня (на данный момент IPVS поддерживает протоколы {{w |TCP}}, {{w |UDP}} и {{w |SCTP}}) и номером [[w:Порт (компьютерные сети) |порта]]. Обычно для кластерных служб выделяется отдельный адрес, который присваивается активному (на данный момент) балансировщику. В случае его отказа, адрес автоматически передается резервному балансировщику, и кластер продолжает работу. Обратите внимание, что обеспечением отказоустойчивости занимается не IPVS, а keepalived. Впрочем, использование keepalived не является строго обязательным — существуют и альтернативные подходы, например, встраивание IPVS в кластерный стек [http://linux-ha.org/ Linux-HA] (см. [[:en:Heartbeat (program)|Heartbeat]]). В том случае, если отказоустойчивость не критична (требуется только балансировка нагрузки), можно вообще обойтись без дополнительного демона, выполняя всю настройку через ipvsadm.
 
Для перенаправления пакетов на выбранный обработчик, IPVS может использовать один из следующих методов:
* '''Прямая {{w |маршрутизация}} (gatewaying)'''  — применяется в том случае, если между балансировщиком и обработчиками отсутствуют {{w |маршрутизатор}}ы, т.е.то есть они находятся в одном сегменте сети. В этом случае адрес назначения в заголовке пакетов сохраняется неизменным («кластерный» адрес), подменяются лишь {{w |MAC-адрес}}а назначения при отправке [[w:Кадр (телекоммуникации) |кадров]] с этими пакетами.
* '''[[w:Инкапсуляция (компьютерные сети) |Инкапсуляция]] IPIP'''  — модификация предыдущего метода на тот случай, когда балансировщик и обработчики находятся в разных сегментах сети. При помощи инкапсуляции IP-в-IP создаются [[w:Туннелирование (компьютерные сети) |сетевые туннели]], которые объединяют балансировщик и обработчик в один сегмент виртуальной сети.
* '''{{w |Маскарадинг}} ({{w |NAT}})'''  — наиболее гибкое и универсальное решение: балансировщик подменяет адреса/порты назначения проходящих пакетов на реальные адреса/порты обработчиков ({{w |трансляция порт-адрес}}). При этом обеспечивается как простота настройки (не нужно поднимать дополнительные адреса на обработчиках и туннели между балансировщиком и обработчиком), так и гибкость (целевой порт обработчика может отличаться от порта кластерной службы, что невозможно в рамках других методов). Недостатком данного метода является несколько большее потребление системных ресурсов (трансляция адресов является довольно ресурсоемкой задачей).
 
В настоящее время существует довольно обширная библиотека алгоритмов балансировки нагрузки между обработчиками:
* '''rr (round robin)'''  — классическая [[w:Round-robin (алгоритм) |кольцевая схема]], когда все обработчики получают новые соединения поочередно.
* '''wrr (weighted round robin)'''  — модификация кольцевой схемы на тот случай, когда одни сервера могут обрабатывать больше соединений, чем другие. Такие сервера включаются в один проход очереди по нескольку раз, и соответственно получают больше соединений.
* '''lc (least-connection)'''  — новое соединение передается тому серверу, который на текущий момент обрабатывает наименьшее число соединений.
* '''wlc (weighted least-connection)'''  — модификация предыдущего метода на случай, когда возможности серверов отличаются. При выборе нового сервера сравниваются не непосредственно количества открытых соединений, а отношения количества соединений к весовому коэффициенту (весу) обработчика (который и характеризует его возможности).
* '''lblc (locality-based least-connection)'''  — формирует привязку обработчиков к кластерному адресу назначения (их может быть несколько). В том случае, если для запрошенного адреса такой привязки еще нет, или привязанный обработчик сильно перегружен ­— выбирает (по алгоритму lc) и привязывает новый обработчик.
* '''lblcr (locality-based least-connection with replication)'''  — несколько усложненный вариант предыдущего алгоритма. К каждому кластерному адресу привязывается группа обработчиков, которая периодически обновляется (исключаются наиболее нагруженные обработчики, вместо них включаются наименее нагруженные).
* '''dh (destination hashing)'''  — обеспечивает жесткую, неуправляемую привязку обработчиков к кластерным адресам назначения (выбор обработчика производится исключительно на основании элементарных арифметических операций над кластерным адресом и ''никак не учитывает'' загруженности обработчиков). Может привести к перегрузкам отдельных обработчиков  — в этом случае кластер просто перестает обслуживать соответствующий адрес. В такой ситуации нужно либо увеличить лимит соединений на обработчик, либо выбрать другой алгоритм.
* '''sh (source hashing)'''  — аналогично dh, но обработчики привязываются к адресам клиентов. Как и dh, в случае перегрузки прекращает обслуживание. Отметим, что для формирования ''временных'' привязок обработчиков к адресам клиентов целесообразнее использовать механизм устойчивых соединений (persistent connections), доступный для всех алгоритмов.
* '''sed (shortest expected delay)'''  — выбирает сервер с наименьшей ожидаемой задержкой ответа. Эта задержка определяется как отношение числа обрабатываемых соединений плюс единица к весу обработчика. Таким образом, этот метод по принципу близок к wlc (отличается лишь прибавлением единицы к числителю сравниваемой величины, что немного меняет влияние веса обработчика на выбор).
* '''nq (never queue)'''  — пытается передать новое соединение обработчику, который в данный момент не обрабатывает других соединений. Если все обработчики уже заняты, использует предыдущий алгоритм (sed).
 
Для отслеживания соединений к кластерным службам IPVS использует собственную систему трекинга соединений, более примитивную, но менее ресурсоемкую, нежели классический conntrack. При этом поддерживается экспорт информации о кластерных соединениях в conntrack, в целях обеспечения их корректной обработки фаерволом и трансляции адресов (при трансляции адресов используются штатные средства netfilter). Однако, для корректной обработки протоколов, использующих связанные соединения (например, {{w |FTP}}), IPVS использует возможности conntrack. Синхронизация таблицы соединений между основным и дублирующими балансировщиками полностью реализована на уровне ядра (для сравнения, в conntrack эту задачу выполняет userspace-демон conntrackd).
 
=== Механизм определения состояний ===
Важной особенностью iptables/{{w |netfilter}} является механизм определения состояний (connection tracking, nf_[[conntrack]]) — специальная подсистема, отслеживающая состояния соединений и позволяющая использовать эту информацию при принятии решений о судьбе отдельных пакетов. Наличие этого механизма делает netfilter полноценным stateful-фаерволом.
 
Определение состояния соединения порою бывает довольно сложной задачей. Скажем, в случае {{w |TCP}} все относительно просто — контроль состояний реализован средствами самого протокола, установлены специальные процедуры открытия и закрытия соединения. А вот в протоколе {{w |UDP}} для этого специальных процедур не предусмотрено, поэтому UDP-соединением с точки зрения [[conntrack]] является поток пакетов, следующих с интервалом, не превышающим заданный тайм-аут ({{w |sysctl}}-параметр <tt>net.netfilter.nf_conntrack_udp_timeout</tt>, по умолчанию 30 секунд), с одного и того же порта одного хоста, на один и тот же порт другого хоста.
Важной особенностью iptables/{{w |netfilter}} является механизм определения состояний (connection tracking, nf_[[conntrack]]) — специальная подсистема, отслеживающая состояния соединений и позволяющая использовать эту информацию при принятии решений о судьбе отдельных пакетов. Наличие этого механизма делает netfilter полноценным stateful-фаерволом.
 
Определение состояния соединения порою бывает довольно сложной задачей. Скажем, в случае {{w |TCP}} все относительно просто — контроль состояний реализован средствами самого протокола, установлены специальные процедуры открытия и закрытия соединения. А вот в протоколе {{w |UDP}} для этого специальных процедур не предусмотрено, поэтому UDP-соединением с точки зрения [[conntrack]] является поток пакетов, следующих с интервалом, не превышающим заданный тайм-аут ({{w |sysctl}}-параметр <tt>net.netfilter.nf_conntrack_udp_timeout</tt>, по умолчанию 30 секунд), с одного и того же порта одного хоста, на один и тот же порт другого хоста.
 
Заметим, что классификация пакетов по отношению к соединениям, реализуемая системой conntrack, во многих случаях отличается от официального описания сетевых протоколов. Например, с точки зрения критерия conntrack, TCP-пакет SYN/ACK (отвечающий на SYN)  — уже часть существующего сеанса, а по определению TCP такой пакет  — всего лишь элемент открытия сеанса.
 
Существует также понятие «связанных соединений». Например, когда в ответ на {{w |UDP}}-пакет с нашего хоста удаленный хост отвечает {{w |ICMP}}-пакетом icmp-port-unreachable, формально этот ответ является отдельным соединением, так как использует совсем другой протокол. {{w |netfilter}} отслеживает подобные ситуации и присваивает таким соединениям статус «связанных» (RELATED), позволяя корректно пропускать их через фильтры фаервола.
 
Более сложный вариант связанного соединения  — соединение данных в пассивном режиме {{w |FTP}}. FTP-сервер самостоятельно выбирает порт для прослушивания из достаточно большого диапазона, и сообщает номер порта клиенту через управляющее соединение, после чего клиент подключается к этому порту и передает данные. {{w |netfilter}}, а точнее модуль conntrack_ftp, выделяет в потоке данных управляющего соединения нужный номер порта, что позволяет корректно определить новое соединение как связанное и, соответственно, корректно пропустить его через правила фильтрации.
 
В некоторых случаях целесообразно отключить отслеживание состояния соединений. Например, если ваш сервер находится под [[w:DoS-атака |(D)DoS-атакой]] типа флуд, и вам удалось локализовать ее источники, отслеживать соединения с атакующих хостов и тратить для этого ресурсы своей системы явно не имеет смысла. В подобных случаях используется действие NOTRACK, применяемое в [[#Таблица raw|таблице raw]].
 
Ниже кратко перечислены возможности, предоставляемые системой отслеживания состояний:
 
==== Критерий состояния соединения ====
При помощи [[#conntrack 2|критерия conntrack]] вы можете классифицировать пакеты на основании их отношения к соединениям. В частности, состояние NEW позволяет выделять только пакеты, открывающие новые соединения, состояние ESTABLISHED — пакеты, принадлежащие к установленным соединениям, состоянию RELATED соответствуют пакеты, открывающие новые соединения, логически связанные с уже установленными (например, соединение данных в пассивном режиме {{w |FTP}}). Состояние INVALID означает, что принадлежность пакета к соединению установить не удалось.
 
При помощи [[#conntrack_2|критерия conntrack]] вы можете классифицировать пакеты на основании их отношения к соединениям. В частности, состояние NEW позволяет выделять только пакеты, открывающие новые соединения, состояние ESTABLISHED — пакеты, принадлежащие к установленным соединениям, состоянию RELATED соответствуют пакеты, открывающие новые соединения, логически связанные с уже установленными (например, соединение данных в пассивном режиме {{w |FTP}}). Состояние INVALID означает, что принадлежность пакета к соединению установить не удалось.
 
Например, одним простым правилом
Строка 256 ⟶ 246 :
вы можете обеспечить корректное пропускание всех входящих пакетов, принадлежащих установленным соединениям, и сконцентрироваться только на фильтрации новых соединений.
 
Заменив в предыдущем правиле <tt>ESTABLISHED</tt> на <tt>ESTABLISHED,RELATED</tt> и подгрузив соответствующие модули ядра, вы автоматически обеспечите корректную фильтрацию протоколов, использующих связанные соединения  — {{w |FTP}}, {{w |SIP}}, {{w |IRC}}, {{w |H.323}} и других. Такое простое (с точки зрения пользователя) решение сложной (с технической точки зрения) проблемы является безусловным достоинством фаервола {{w |netfilter}} и ядра [[Linux]] в целом.
 
Более подробно об использовании этого критерия вы можете почитать [[#conntrack_2conntrack 2|ниже]].
 
Кроме критерия conntrack, стоит упомянуть и его идеологического предшественника  — [[#state|критерий state]]. Изначально для определения состояния соединения использовался именно он, то есть вместо <tt>-m conntrack --ctstate ESTABLISHED,RELATED</tt> использовалось <tt>-m state --state ESTABLISHED,RELATED</tt>. Подобные формулировки до сих пор сохраняются во многих руководствах по iptables. Однако в настоящее время критерий state считается устаревшим, и разработчики iptables [http://jengelh.medozas.de/documents/Perfect_Ruleset.pdf рекомендуют] использовать вместо него критерий conntrack. Также заметим, что критерий conntrack обладает более широкими возможностями, нежели state, и позволяет использовать дополнительную информацию о соединении, в частности, состояние самого соединения (ctstatus), факт применения к нему [[w:NAT |трансляции адресов]], тайм-аут для «повисших» соединений (ctexpire) и  т.  п.
 
==== Маркировка соединений ====
Этот прием позволяет классифицировать соединение в целом на основании информации об отдельном пакете. Выделив этот пакет, вы применяете к нему действие CONNMARK, и выбранную вами маркировку автоматически приобретают все пакеты в соединении. Впоследствии вы можете, например, модифицировать эти пакеты каким-либо образом, или использовать эту маркировку для [[w:Маршрутизация|маршрутизации]] или [[w:Шейпинг (информатика)|шейпинга]] пакетов. Таким образом, вы оперируете с соединением как с единым целым. Более того, эта маркировка автоматически копируется и на соединения, связанные с текущим.
 
==== [[w:NAT|Трансляция сетевых адресов]] ====
Этот прием позволяет классифицировать соединение в целом на основании информации об отдельном пакете. Выделив этот пакет, вы применяете к нему действие CONNMARK, и выбранную вами маркировку автоматически приобретают все пакеты в соединении. Впоследствии вы можете, например, модифицировать эти пакеты каким-либо образом, или использовать эту маркировку для [[w:Маршрутизация |маршрутизации]] или [[w:Шейпинг (информатика) |шейпинга]] пакетов. Таким образом, вы оперируете с соединением как с единым целым. Более того, эта маркировка автоматически копируется и на соединения, связанные с текущим.
В операциях NAT, производимых с помощью iptables, отслеживание состояний используется автоматически. Вам достаточно указать критерии, под которые подпадет лишь первый пакет в соединении — и трансляция адресов будет применена ко всем пакетам в этом соединении, а также в связанных с ним соединениях.
 
==== [[w:NAT |Трансляция сетевых адресов]] ====
 
В операциях NAT, производимых с помощью iptables, отслеживание состояний используется автоматически. Вам достаточно указать критерии, под которые подпадет лишь первый пакет в соединении — и трансляция адресов будет применена ко всем пакетам в этом соединении, а также в связанных с ним соединениях.
 
==== Использование статистики по соединениям ====
Применяя критерий connbytes, вы можете контролировать количество байт или пакетов, переданных по каждому конкретному соединению. В простейшем случае этот механизм может использоваться, скажем, для назначения квот. Более сложный пример — шейпинг пакетов в зависимости от «весовой категории» соединения (ставить пониженный приоритет загрузкам больших файлов).
 
Применяя критерий connbytes, вы можете контролировать количество байт или пакетов, переданных по каждому конкретному соединению. В простейшем случае этот механизм может использоваться, скажем, для назначения квот. Более сложный пример — шейпинг пакетов в зависимости от «весовой категории» соединения (ставить пониженный приоритет загрузкам больших файлов).
 
Этот критерий рассмотрен ниже, в разделе [[#Лимитирующие критерии|лимитирующие критерии]].
 
==== Ограничение количества соединений ====
Используя критерий connlimit, вы можете ограничивать количество одновременно открытых {{w |TCP}}-соединений с каждого хоста или подсети на ваш сервер, что позволяет обеспечить эффективную защиту от [[w:DoS-атака|DoS-атак]] или просто некорректно работающего клиентского [[w:Программное обеспечение|ПО]].
 
Используя критерий connlimit, вы можете ограничивать количество одновременно открытых {{w |TCP}}-соединений с каждого хоста или подсети на ваш сервер, что позволяет обеспечить эффективную защиту от [[w:DoS-атака |DoS-атак]] или просто некорректно работающего клиентского [[w:Программное обеспечение |ПО]].
 
Этот критерий рассмотрен ниже, в разделе [[#Лимитирующие критерии|лимитирующие критерии]].
 
==== Отслеживание информации о соединениях ====
Пользователь (точнее, [[w:Root|системный администратор]]) или его процессы могут непосредственно наблюдать таблицу контроля состояний, считывать статистику по передаче данных, а также модифицировать эту таблицу (например, удалять из нее соединения). Для этого существуют специальные утилиты, такие как [[conntrack (Программа)|conntrack]] или [[iptstate]]. Впрочем, можно читать информацию и напрямую из псевдофайлов <tt>/proc/net/nf_conntrack</tt> и <tt>/proc/net/nf_conntrack_expect</tt>.
 
Пользователь (точнее, [[w:Root |системный администратор]]) или его процессы могут непосредственно наблюдать таблицу контроля состояний, считывать статистику по передаче данных, а также модифицировать эту таблицу (например, удалять из нее соединения). Для этого существуют специальные утилиты, такие как [[conntrack (Программа) | conntrack]] или [[iptstate]]. Впрочем, можно читать информацию и напрямую из псевдофайлов <tt>/proc/net/nf_conntrack</tt> и <tt>/proc/net/nf_conntrack_expect</tt>.
 
== Действия ==
 
=== Переходы ===
 
Для организации перехода пакета из текущей цепочки в другую (определенную пользователем), просто используйте действие <tt>-j имя_цепочки</tt>. В случае применения в этой цепочке к пакету действия RETURN (см. ниже), пакет вернется в исходную цепочку и продолжит ее прохождение начиная со следующего правила.
 
Строка 297 ⟶ 281 :
 
=== Встроенные действия ===
 
Как уже было сказано выше, каждое встроенное действие реализует какую-либо одну операцию, например, ACCEPT пропускает пакет, MARK меняет его маркировку, MASQUERADE обеспечиват {{w |маскарадинг}} соединения. Наиболее общими действиями являются:
* '''ACCEPT''', '''DROP''' и '''REJECT'''  — базовые операции фильтрации. Более подробно они рассмотрены ниже, при описании таблицы filter.
* '''RETURN'''  — обеспечивает возврат из текущей цепочки. В частности, если из цепочки A правилом номер 3 пакет был направлен в цепочку B, то применение к нему в цепочке B действия RETURN приведет к его переходу обратно в цепочку A, и он продолжит ее прохождение со следующего правила (номер 4).
Например, предположим, что нам нужно обеспечить доступ к определенным [[w:Порт (компьютерные сети) |портам]] нашего сервера для всех хостов из подсети 10.134.0.64/26, ''кроме'' 10.134.0.67 и 10.134.0.100.
<source lang="bash">
iptables -F # Очищаем все цепочки таблицы filter
Строка 318 ⟶ 301 :
iptables -P OUTPUT ACCEPT # На выход — можно все
</source>
Теперь все новые входящие пакеты, отправленные из нашей подсети 10.134.0.64/26, отправляются на проверку в цепочку <tt>our_subnet</tt>. К пакетам с «запрещенных» хостов применяется операция RETURN, и они покидают эту цепочку и впоследствии блокируются действием по умолчанию цепочки INPUT. Пакеты с остальных хостов этой подсети пропускаются в том случае, если они адресованы на порты [[w:Прокси-сервер |прокси]] (8080/tcp), {{w |SSH}} (22/tcp), {{w |SMB}} (139,445/tcp, 137,138/udp), {{w |DNS}} (53/tcp, udp), {{w |NTP}} (123/udp). Также для этих хостов разрешены {{w |ICMP}}-эхо-запросы (пинги). Все остальные пакеты (включая пакеты не из нашей подсети, пакеты с запрещенных хостов и пакеты на неразрешенные порты) блокируются действием по умолчанию DROP.
 
Нетрудно заметить, что в нашем простом примере вместо RETURN можно было использовать и DROP. Однако, существует понятие «принципа одного запрета». При организации фильтрующих правил в рамках этого принципа, сначала следует серия разрешающих правил, исключения оформляются в виде RETURN, а все не разрешенные пакеты доходят до конца базовой цепочки и блокируются действием по умолчанию либо последним правилом. Следование этому принципу позволяет достичь гибкости в выборе и смене метода блокирования пакетов. Допустим, вы хотите сменить блокирующее действие DROP на REJECT. Нет ничего проще  — просто меняете правило по умолчанию. Так же просто вводятся специфические методы блокировки для TCP, например, REJECT <tt>--reject-with tcp-reset</tt> или DELUDE  — достаточно просто добавить это действие (вместе с указанием протокола <tt>-p tcp</tt>) в конец цепочки. Все не-TCP пакеты при этом будут по-прежнему блокироваться действием по умолчанию.
 
Впрочем, изложенный принцип теряет первоначальный смысл, если в разных случаях нужно обеспечить разные способы блокирования. Рассмотрим чуть более сложный пример: допустим, наш сервер подключен к локальной сети 10.0.0.0/8. В ней есть некий «недоверенный» сегмент, скажем, 10.122.0.0/16, для которого нужно полностью заблокировать доступ к нашему серверу. Но в этом сегменте есть несколько «хороших» хостов (скажем, 10.122.72.11 и 10.122.180.91), которые блокировать не&nbsp; нужно. Поставленную задачу можно решить следующим образом:
<source lang="bash">
iptables -F # Очищаем все цепочки таблицы filter
Строка 343 ⟶ 326 :
iptables -P OUTPUT ACCEPT # На выход — можно все
</source>
Заметим, что в данном примере хосты из недоверенного сегмента блокируются «молча» (DROP), в то время как при обращении «хороших» хостов на неправильные порты сервер вежливо сообщает им об отказе (REJECT). Этот принцип также является очень важным при построении фаерволов  — чем меньше информации попадает к потенциальному злоумышленнику, тем лучше, поэтому на опасных направлениях целесообразно использовать «молчаливое» блокирование, в то время как явные сообщения для «своих» упрощают диагностику работы сети и поиск ошибок.
 
: ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → mac)''.
Например, предположим, что у нас есть объединенная через один [[w:Сетевой коммутатор |свитч]] подсеть 10.134.0.64/26, к которой наш компьютер подключен через интерфейс eth1. Тогда защиту от {{w |спуфинг}}а (подделки адресов отправителя) через проверку {{w |MAC-адрес}}а можно обеспечить следующим образом:
<source lang="bash">
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик
Строка 373 ⟶ 356 :
</source>
<!--В демонстрационных целях этот пример был слегка упрощён (вместо повтора правил с критерием <tt>-s 10.134.0.64/26</tt> эти правила логичнее было бы вынести в отдельные цепочки) но, тем не менее, наглядно показывает принципы работы действия RETURN.-->
Все новые входящие пакеты с обратным адресом из подсети 10.134.0.64/26 проходят двойную проверку в цепочке <tt>check_ours</tt>. Первый этап проверки  — соответствие интерфейса. Ведь к нашей подсети, по условию задачи, мы подключены только интерфейсом eth1. Если пакет якобы из этой подсети придет с любого другого интерфейса, он будет заблокирован. Второй этап проверки заключается в последовательном чтении списка соответствующих [[w:IP-адрес |IP]]- и {{w |MAC-адрес}}ов (цепочка <tt>check_ours_sp00f</tt>). Каждое правило этой цепочки, кроме последнего, выделяет пакеты от одного конкретного хоста нашей подсети. К пакетам, прошедшим проверку, применяется операция RETURN, выводящая пакет из этой цепочки. Если же пакет не подошел ни по одному из этих правил, он считается не прошедшим проверки и блокируется последним правилом <tt>-j DROP</tt>. Для прошедших же проверку пакетов дальнейшая судьба зависит от того, кому они адресованы. Если они идут через наш хост в другие подсети, то они пропускаются. Если же они адресованы непосредственно нашему хосту, то пропускаются только соединения на некоторые {{w |TCP}}-[[w:Порт (компьютерные сети) |порты]] ([[w:Прокси-сервер |прокси]], {{w |SSH}}, {{w |SMB}}).
* '''LOG'''  — позволяет записывать информацию о пакетах в журнал ядра (см. {{w |syslog}}).
Например, если в предыдущем примере перед строкой
<source lang="bash">
Строка 386 ⟶ 369 :
Jul 16 20:10:40 interdictor kernel: New connection from ours: IN=eth0 OUT= MAC=00:15:17:4c:89:35:00:1d:60:2e:ed:a5:08:00 SRC=10.134.0.67
DST=10.134.0.65 LEN=48 TOS=0x00 PREC=0x00 TTL=112 ID=38914 DF PROTO=TCP SPT=31521 DPT=8080 WINDOW=65535 RES=0x00 SYN URGP=0
Такая запись содержит очень много полезной информации. Начинается она с даты и времени получения пакета. Затем идет имя нашего хоста (interdictor) и источник сообщения (для сообщений фаервола это всегда ядро). Потом идет заданный нами префикс (<tt>New connection from ours:</tt>), после чего следуют данные о самом пакете: входящий интерфейс (определен для цепочек PREROUTING, INPUT и FORWARD), исходящий интерфейс (определен для цепочек FORWARD, OUTPUT и POSTROUTING), далее  — сцепленные вместе {{w |MAC-адрес}}а источника и назначения (сначала идет адрес назначения, в данном случае это наш интерфейс eth1 с маком 00:15:17:4C:89:35, затем адрес источника, в нашем случае это 00:1D:60:2E:ED:A5, и в конце следует значение [[:en:EtherType|EtherType]], 08:00 соответствует протоколу {{w |IPv4}}<ref>Если кратко, EtherType указывает тип протокола, инкапсулированного в {{w |Ethernet}}-[[w:Кадр (телекоммуникации) |кадр]]. При работе с iptables это значение будет всегда равно 08:00 (протокол {{w |IPv4}}), при работе с ip6tables  — 86:DD ({{w |IPv6}}). Полный список EtherTypes доступен [http://www.iana.org/assignments/ethernet-numbers на сайте IANA], список поддерживаемых netfilter’ом  — в файле /etc/ethertypes, который в большинстве дистрибутивов находится в пакете {{w |ebtables}}.</ref>), потом {{w |IP-адрес}}а источника (10.134.0.67) и получателя (10.134.0.65, это наш хост), а затем идет различная техническая информация. Например, протокол ({{w |TCP}}), [[w:Порт (компьютерные сети) |порты]] источника и назначения (31521 и 8080 соответственно), [[w:Тип обслуживания |TOS]] и [[w:Time to live |TTL]], длина пакета (48 байт), наличие флага SYN и  т.  д.
 
Указав соответствующие параметры действия LOG, можно дополнить эту информацию [[w:TCP#Номер последовательности |номером TCP-последовательности]] (опция <tt>--log-tcp-sequence</tt>), выводом включенных опций протоколов TCP (опция <tt>--log-tcp-options</tt>) и {{w |IP}} (<tt>--log-ip-options</tt>), а также идентификатором пользователя, процесс которого отправил данный пакет (<tt>--log-uid</tt>, имеет смысл только в цепочках OUTPUT и POSTROUTING).
 
Параметр <tt>--log-prefix</tt> позволяет задать поясняющую надпись, упрощающую поиск сообщений в системных журналах. Параметр <tt>--log-level</tt> определяет уровень важности лог-сообщения, от которого зависит, в частности, в какой именно из журналов будет записано это сообщение. За более подробными сведениями обратитесь к документации по вашему [[w:Syslog |демону системного лога]].
* '''LOGMARK'''  — специальная модификация действия LOG, реализованная в комплекте xtables-addons. Отличается тем, что заносит в лог информацию, специфичную для системы [[conntrack]], в частности, маркировку соединения (connmark aka ctmark), состояния соединения (ctstate и ctstatus) и  т.  п. Например:
Jul 16 20:10:40 interdictor kernel: New connection from ours: iif=1 hook=INPUT nfmark=0x0 secmark=0x0 classify=0x0 ctdir=ORIGINAL
ct=0xf5436bcc ctmark=0x0 ctstate=NEW ctstatus=
<tt>iif</tt> показывает внутренний идентификатор интерфейса, через который прошел пакет (1 в данном случае соответствует eth0, 0  — lo), <tt>hook</tt>  — имя цепочки, из которой было вызвано действие LOGMARK, <tt>nfmark</tt>  — маркировку пакета (mark), <tt>secmark</tt>  — контекст безопасности {{w |SELinux}} данного пакета (secmark), <tt>classify</tt>  — класс шейпера (также известный как <tt>skb->priority</tt>, соответствует обычной для [[w:Iproute2 |tc]] форме записи ''MAJOR'':''MINOR'' согласно формуле <tt>skb->priority == ''MAJOR'' << 16 | ''MINOR''</tt>), <tt>ctdir</tt>  — направление передачи информации с точки зрения conntrack, <tt>ct</tt>  — внутренний идентификатор соединения в системе conntrack (точнее говоря, адрес в памяти, по которому расположена структура, хранящая информацию о соединении), <tt>ctmark</tt>  — маркировку соединения (connmark), <tt>ctstate</tt>  — состояние соединения, <tt>ctstatus</tt>  — статус соединения в системе cоnntrack. Более подробно о параметрах ctdir, ctstate и ctstatus вы можете прочитать [[#conntrack|ниже]], в описании критерия conntrack. Здесь же ограничимся замечаниями, что «<tt>ctstate=NEW ctstatus=</tt>» соответствует первому пакету в соединении, «<tt>ctstate=ESTABLISHED ctstatus=SEEN_REPLY,CONFIRMED</tt>»  — второму и нескольким последующим пакетам, «<tt>ctstate=ESTABLISHED ctstatus=SEEN_REPLY,ASSURED,CONFIRMED</tt>»  — пакетам в полностью установленном соединении, «<tt>ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE</tt>»  — пакету, который не удалось отнести к существующим соединениям, «<tt>ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE</tt>»  — пакету, для которого была отключена трассировка conntrack (обычно это выполняется действием NOTRACK в таблице raw, см. [[#Таблица raw|ниже]]).
 
Таким образом, в сочетании с традиционным LOG, действие LOGMARK позволяет заносить в системный журнал исчерпывающую информацию о пакетах и соединениях.
 
Заметим, что LOGMARK принимает описанные выше опции <tt>--log-prefix</tt> и <tt>--log-level</tt>.
* '''ULOG'''  — позволяет передавать информацию об обработанных пакетах специальным демонам, таким, как [http://www.netfilter.org/projects/ulogd/ ulogd]. Такой подход позволяет эффективно управлять информацией о трафике, в частности, заносить ее в {{w |базы данных}}, такие как {{w |MySQL}}, {{w |PostgreSQL}} или {{w |SQLite}}. Впоследствии эти данные могут быть проанализированы и визуализированы с помощью таких средств, как [http://software.inl.fr/trac/wiki/EdenWall/NuLog NuLog].
* '''NFLOG'''  — более универсальный вариант ULOG, обеспечивающий передачу информации о пакете не напрямую в netlink-[[w:Сокет (программный интерфейс) |сокет]] (как это делает ULOG), а специальной подсистеме  — logging backend. Например, бэкенд nfnetlink_log обеспечивает передачу данных в netlink-сокет, то есть с ним NFLOG работает аналогично ULOG.
* '''NFQUEUE'''  — во многом похоже на ULOG, но передает специальному демону не информацию о пакете, а сам пакет целиком. Применяется, в частности, для организации работы {{w |l7-filter}}-userspace.
Например, если демон l7-filter был запущен командой
<source lang="bash">
Строка 413 ⟶ 396 :
</source>
Опция <tt>--queue-num</tt> позволяет указать номер очереди пакетов. Он должен быть совпадать с номером, указанным при запуске демона l7-filter (параметр <tt>-q</tt>).
* '''QUEUE'''  — устаревшая версия NFQUEUE. Не имеет параметров, так как работает только с очередью номер 0.
 
Выше были рассмотрены действия «общего назначения», то есть не привязанные по своей специфике к таблицам. Далее, при рассмотрении отдельных таблиц, будут описываться действия, специфичные для каждой таблицы. Термин «специфичные» надо понимать так: совсем не обязательно, что действие, специфичное для одной таблицы, будет в принципе недопустимо в другой, но в любом случае использование этого действия в других таблицах будет «плохим тоном»  — ведь таблицы и действия четко разделены по назначению. Не стоит «забивать гвозди микроскопом».
 
Порой эта разница бывает довольно тонкой. Например, если действие NFQUEUE передает пакеты демону {{w |l7-filter}}-userspace (который занимается маркировкой пакетов на основе анализа их содержимого), то правильнее будет разместить вызов такого действия в таблице mangle. Если же оно передает пакеты демону [[nufw]] (который обеспечивает разрешение или запрещение трафика на основе авторизации пользователя), то логичнее разместить это действие в таблице filter.
Строка 422 ⟶ 405 :
 
=== Терминальные и нетерминальные действия ===
* ''Терминальными'' называются действия, которые прерывают прохождение пакета через текущую базовую цепочку. То есть если к пакету в рамках некоторого правила было применено терминальное действие, он уже не проверяется на соответствие всем следующим правилам в этой цепочке (и в тех цепочках, из которых она была вызвана, если это пользовательская цепочка). Терминальными являются все действия, специфичные для таблиц filter и nat. Из приведенных выше в этом разделе — ACCEPT, DROP, REJECT, NFQUEUE, QUEUE.
 
* ''Терминальными'' называются действия, которые прерывают прохождение пакета через текущую базовую цепочку. То есть если к пакету в рамках некоторого правила было применено терминальное действие, он уже не проверяется на соответствие всем следующим правилам в этой цепочке (и в тех цепочках, из которых она была вызвана, если это пользовательская цепочка). Терминальными являются все действия, специфичные для таблиц filter и nat. Из приведенных выше в этом разделе — ACCEPT, DROP, REJECT, NFQUEUE, QUEUE.
Например,
<source lang="bash">
Строка 431 ⟶ 413 :
Второе из приведенных правил (логгирование) никогда не будет срабатывать, так как все пакеты, удовлетворяющие этому критерию (входящие TCP-пакеты на порт 80), будут пропущены по первому из этих правил, и до второго просто не дойдут.
 
* ''Нетерминальными'', соответственно, являются действия, ''не'' прерывающие процесс прохождения пакета через цепочки. Нетерминальными являются действия, специфичные для таблицы mangle, а из перечисленных выше  — LOG, ULOG и NFLOG.
Например,
<source lang="bash">
Строка 439 ⟶ 421 :
Теперь все входящие на TCP-порт 80 пакеты будут сначала заноситься в лог, и только потом пропускаться.
 
Действие RETURN с точки зрения такой классификации занимает промежуточное положение  — оно может прервать прохождение пакета через отдельную цепочку (или несколько цепочек, если для перехода в них использовалась опция <tt>-g</tt>, а не <tt>-j</tt>), но совсем не обязательно, чтобы это приводило к завершению обработки пакета в рамках текущей базовой цепочки.
 
== Таблицы ==
Строка 445 ⟶ 427 :
 
=== Таблица mangle ===
Данная таблица предназначена для операций по классификации и маркировке пакетов и соединений, а также модификации заголовков пакетов (поля [[w:Time to live |TTL]] и [[w:Тип обслуживания |TOS]]).
 
==== Цепочки ====
Таблица mangle содержит следующие цепочки:
* '''PREROUTING'''  — позволяет модифицировать пакет ''до'' принятия решения о маршрутизации.
* '''INPUT'''  — позволяет модифицировать пакет, предназначенный самому хосту.
* '''FORWARD'''  — цепочка, позволяющая модифицировать транзитные пакеты.
* '''OUTPUT'''  — позволяет модифицировать пакеты, исходящие от самого хоста.
* '''POSTROUTING'''  — дает возможность модифицировать все исходящие пакеты, как сгенерированные самим хостом, так и транзитные.
 
Заметим, что все цепочки таблицы mangle пакеты проходят раньше, чем одноименные цепочки таблиц nat и filter. Это позволяет классифицировать и маркировать пакеты и соединения в цепочках этой таблицы. Впоследствии эти маркировки могут быть использованы в цепочках двух других таблиц при принятии решений о фильтрации и трансляции адресов.
Строка 459 ⟶ 441 :
==== Действия ====
Допустимыми действиями в этой таблице являются:
* '''TOS'''  — изменяет поле [[w:Тип обслуживания |TOS]] данного пакета. Поддерживаются опции <tt>--set-tos</tt> (установить поле TOS в заданное значение), а также <tt>--and-tos</tt>, <tt>--or-tos</tt> и <tt>--xor-tos</tt>, комбинирующие текущее значение поля TOS с заданным в правиле значением по соответствующему логическому правилу и записывающие результат как новое значения поля TOS.
 
Кроме того, опция <tt>--set-tos</tt> поддерживает расширенный синтаксис <tt>--set-tos ''значение''/''маска''</tt>. При использовании такого синтаксиса в исходном значении TOS пакета зануляются те биты, которые установлены в маске, затем полученное число XOR’ится с указанным в параметрах значением, и полученная величина записывается в поле TOS. Используя синтаксис [[w:Си (язык программирования) |языка C]], это можно записать так: <tt>NEW_TOS = (OLD_TOS & ~''маска'') ^ ''значение''</tt>. Заметим, что в случае с {{w |IPv6}} операция отрицания маски не&nbsp; выполняется (то есть в исходном значении зануляются те биты, которые в маске ''не&nbsp; установлены''), хотя это и не&nbsp; отражено в документации.
 
Также, в случае {{w |IPv4}} (iptables) в параметре <tt>--set-tos</tt> вы можете указать одно из допустимых символьных обозначений: Minimize-Delay (TOS 16, требование минимальной задержки), Maximize-Throughput (TOS 8, требование максимальной пропускной способности), Maximize-Reliability (TOS 4, максимальная надежность доставки), Minimize-Cost (TOS 2, минимальная стоимость), Normal-Service (TOS 0, специальные требования отсутствуют). В ip6tables использование этих обозначений не&nbsp; запрещено, однако в этом случае более корректным будет использование действия DSCP (см. ниже).
 
Практический пример использования действия TOS представлен [[#Лимитирующие критерии|ниже]], в описании критерия connbytes.
 
Отметим, что, в соответствии с современными соглашениями, поле TOS в заголовке IP-пакета разделяется на две части: {{w |DSCP}} (первые шесть бит кода TOS) и [[w:Explicit Congestion Notification |ECN]] (последние два бита TOS). Современные версии netfilter/iptables не&nbsp; поддерживают изменение значений ECN в IP-заголовках, поэтому фактически действие TOS работает только с полем DSCP, отличаясь от действия DSCP (см. чуть ниже) разве что интерфейсом (фактически, синтаксисом).
 
* '''DSCP'''  — изменяет поле {{w |DSCP}} (класс [[:en:Differentiated services|DiffServ]]) в заголовке пакета. Поддерживаются опции <tt>--set-dscp</tt> (позволяет задать значение DSCP числом) и <tt>--set-dscp-class</tt> (позволяет установить заданный класс DiffServ, например, EF или AF13).
* '''TTL'''  — изменяет поле [[w:Time to live |TTL]] данного пакета (работает только с {{w |IPv4}}, для {{w |IPv6}} используется действие HL). Поддерживаются опции <tt>--ttl-set</tt> (установить поле TTL в заданное значение), а также <tt>--ttl-inc</tt> и <tt>--ttl-dec</tt> (соответственно увеличить или уменьшить текущее значение поля TTL на заданное значение). Допустимые значения TTL  — от 0 до 255. При достижении TTL=0 пакет уничтожается.
 
В качестве полезного примера использования этого действия можно привести команду
Строка 476 ⟶ 458 :
iptables -t mangle -I PREROUTING -j TTL --ttl-inc 1
</source>
делающую наш шлюз невидимым для большинства [[w:Traceroute |трассировщиков]].
 
Обратите внимание, что автоматически выполняемая сетевым стеком ядра операция уменьшения TTL на единицу и проверки на равенство нулю выполняется ''после'' цепочки PREROUTING, но ''до'' цепочки FORWARD. Таким образом, переместив это правило в цепочку FORWARD, вы обеспечите «невидимость» следующего за вами шлюза.
 
Другой полезный пример  — выравнивание TTL на выходе в Интернет (интерфейс eth0)
<source lang="bash">
iptables -t mangle -I POSTROUTING -o eth0 -j TTL --ttl-set 64
Строка 488 ⟶ 470 :
'''Будьте очень осторожны''' с правилами, которые увеличивают или, что особенно опасно, напрямую задают значение TTL, так как, при наличии определенных ошибок маршрутизации, это может привести к появлению «бессмертных» пакетов, которые будут долго циркулировать между одними и теми же узлами, захламляя канал и затрудняя работу сетевого оборудования.
 
* '''HL'''  — изменяет поле Hop Limit в заголовке {{w |IPv6}}-пакета. Является аналогом IPv4-действия TTL и поддерживает те же операции: <tt>--hl-set</tt> (установить поле HL в заданное значение), а также <tt>--hl-inc</tt> и <tt>--hl-dec</tt> (соответственно увеличить или уменьшить текущее значение поля HL на заданное значение).
* '''MARK'''  — устанавливает или изменяет маркировку пакета. Поддерживает опции <tt>--set-mark</tt>, <tt>--and-mark</tt>, <tt>--or-mark</tt> и <tt>--xor-mark</tt>, аналогичные опциям действия TOS. Важно понимать, что маркировка пакета не хранится в его заголовке или содержимом, и поэтому действует только в пределах одного хоста. Также нужно отличать маркировку пакета от маркировки соединения. Маркировка пакетов может применяться для их дальнейшей обработки фаерволом (критерии mark и connmark), а также для классификации трафика фильтрами [[w:Шейпинг (информатика) |шейпинговой]] подсистемы [[w:Iproute2 |tc]] (лексема handle ''mark'' fw).
* '''CONNMARK'''  — устанавливает или изменяет маркировку соединения. Поддерживает те же опции, что и MARK, а также дополнительные опции <tt>--restore-mark</tt> (копирует маркировку соединения в маркировку пакета) и <tt>--save-mark</tt> (копирует маркировку пакета в маркировку соединения).
* '''CLASSIFY'''  — устанавливает [[:en:Class Based Queueing|CBQ]]-класс пакета для его последующей обработки [[w:Шейпинг (информатика) |шейпером]] (опция <tt>--set-class</tt>).
* '''TCPMSS'''  — устанавливает [[:en:Maximum segment size|максимальный размер TCP-сегмента]]. Бывает крайне полезной при использовании {{w |VPN}}-подключения<ref>Обычно проблемы с пониженным {{w |MTU}} в {{w |Ethernet}}-сетях возникают как раз из-за {{w |VPN}}-туннелей</ref> в том случае, если VPN-сервер блокирует {{w |ICMP}}-сообщения destination unreachable/fragmentation needed (тип 3, код 4), тем самым нарушая работу процедуры [[w:Maximum transmission unit#Технология Path MTU discovery |Path MTU discovery]].
 
С точки зрения клиента, эта проблема выглядит так: {{w |пинг}}и проходят нормально, но при попытке открыть какую-либо {{w |веб}}-страницу, {{w |браузер}} «подвисает». При этом с самого шлюза все работает нормально. В этом случае достаточно применить на шлюзе следующую команду
Строка 498 ⟶ 480 :
iptables -t mangle -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
</source>
которая обеспечит автоматическую установку размера сегмента в TCP-заголовках SYN- и SYN,ACK-пакетов в соответствии с минимальным из известных нашему шлюзу значений {{w |MTU}} на пути следования пакета. Например, если пакет пришел с интерфейса eth0 (MTU 1500) и уходит через интерфейс ppp0 (MTU 1492), а суммарный размер заголовков [[w:Протоколы сетевого уровня |сетевого]] и [[w:Транспортный уровень |транспортного]] уровней составляет 40 {{w |байт}} (20 байт {{w |TCP}} и 20 байт {{w |IP}}), то целесообразно установить MSS равным 1452 байтам.
 
Помимо возможности автоматического выбора TCP MSS, вы можете задать необходимое значение и вручную, используя параметр <tt>--set-mss ''значение''</tt>. Это бывает полезным в том случае, если вам заведомо известно, что дальше на маршруте встречаются участки с еще меньшим MTU, а пограничные сервера этих участков опять же блокируют ICMP destination unreachable/fragmentation needed.
* '''ECN'''  — обеспечивает обнуление [[w:Explicit Congestion Notification |ECN]]-битов (флаги CWR и ECE) в TCP-заголовке (единственная опция <tt>--ecn-tcp-remove</tt>). Может использоваться только в {{w |IPv4}}-модуле (iptables, но не&nbsp; ip6tables) для {{w |TCP}}-пакетов (<tt>-p tcp</tt>). Данное действие предназначено для защиты пакетов от ECN blackholes (маршрутизаторов, которые некорректно обрабатывают пакеты с установленными в TCP-заголовке ECN-битами)  — рекомендуется применять это действие ко всем пакетам, уходящим на такие маршрутизаторы. Обратите внимание, что данное действие никак не&nbsp; влияет на ECN-биты в {{w |IP}}-заголовках (последние два бита поля [[w:Тип обслуживания |TOS]]).
 
Кроме того, данное действие поддерживает три потенциально опасные опции, не отраженные в документации: <tt>--ecn-tcp-cwr</tt> (установка значения бита CWR в TCP-заголовке, 0 или 1), <tt>--ecn-tcp-ece</tt> (установка значения бита ECE в TCP-заголовке, 0 или 1) и <tt>--ecn-ip-ect</tt> (установка значения ECT codepoint в IPv4-заголовке, от 0 до 3). Использование этих опций настолько опасно, что они не отражены даже во встроенной справке iptables (<tt>iptables -j ECN -h</tt>)  — их можно увидеть, только изучив [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=blob;f=extensions/libipt_ECN.c исходный код]. Без крайней необходимости применять их не рекомендуется.
* '''TCPOPTSTRIP'''  — выполняет удаление заданных TCP-опций из заголовка TCP-пакета (единственный параметр <tt>--strip-options ''значение''[,''значение''[,...]]</tt>). Удаляемые опции могут быть указаны через их номера (согласно [http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml списку на сайте IANA]) или в виде символьных обозначений (список обозначений, поддерживаемых в вашей версии iptables можно посмотреть, выполнив команду <tt>iptables -j TCPOPTSTRIP -h</tt>). Разумеется, данное действие допустимо только для протокола TCP (<tt>-p tcp</tt>). Например,
<source lang="bash">
iptables -t mangle -A POSTROUTING -p tcp -j TCPOPTSTRIP --strip-options timestamp
</source>
обеспечит удаление штампов времени (RFC 1323). С одной стороны, такое правило будет препятствовать удаленному злоумышленнику определить {{w |аптайм}} нашего хоста, а также тех хостов, маршрут от которых до злоумышленника проходит через наш хост. С другой стороны, блокирование штампов времени может негативно сказаться на быстродействии сети, особенно если вы используете подключения на скорости [[w:Fast Ethernet |100&nbsp; МБит]] и выше. Заметим также, что если вам нужно управлять использованием именно штампов времени для TCP IPv4-пакетов, исходящих от вашего хоста, вы можете воспользоваться {{w |sysctl}}-параметром net.ipv4.tcp_timestamps (1  — штампы включены, 0  — выключены).
* '''TPROXY'''  — реализует механизм полностью прозрачного [[w:Прокси-сервер |проксирования]]. Такой подход отличается от традиционно используемого «прозрачного» проксирования (действие REDIRECT [[#Таблица nat|таблицы nat]], см. ниже) тем, что заголовок пакета никак не&nbsp; модифицируется, в том числе не&nbsp; заменяется {{w |IP-адрес}} назначения (при традиционном прозрачном проксировании он заменяется на адрес проксирующего хоста). Кроме того, полностью прозрачное проксирование является прозрачным с точки зрения обеих общающихся сторон. Например, при проксировании обращений некоторой подсети клиентов к серверам из другой подсети, можно сделать так, чтобы не&nbsp; только клиенты считали, что обращаются напрямую к серверам, но и сервера «видели» настоящие исходные адреса клиентов и могли бы устанавливать с ними обратные соединения (например, в случае активного режима {{w |FTP}}). При традиционном же «прозрачном» проксировании, сервера могут видеть только адрес прокси-сервера.
 
TPROXY позволяет перенаправить транзитный пакет на локальный [[w:Сокет (программный интерфейс) |сокет]] типа AF_INET (iptables) или AF_INET6 (ip6tables), заданный портом, а также может промаркировать пакет таким образом, чтобы система марушрутизации ({{w |iproute2}}) не&nbsp; позволила пакету покинуть наш хост. Разумеется, поддержка полностью прозрачного проксирования должна быть реализована и в самом {{w |прокси-сервер}}е. В частности, прозрачное проксирование {{w |IPv4}} {{w |HTTP}} [http://wiki.squid-cache.org/Features/Tproxy4 поддерживается] прокси-сервером {{w |Squid}} начиная с версии 3.1.
 
В качестве примера можно привести простейший случай конфигурации iptables и iproute2 для обеспечения полностью прозрачного проксирования {{w |IPv4}} {{w |HTTP}}.
Строка 531 ⟶ 513 :
 
=== Таблица nat ===
Предназначена для операций stateful-преобразования [[w:IP-адрес|сетевых адресов]] и [[w:Порт (компьютерные сети)|портов]] обрабатываемых пакетов.
 
Предназначена для операций stateful-преобразования [[w:IP-адрес |сетевых адресов]] и [[w:Порт (компьютерные сети) |портов]] обрабатываемых пакетов.
 
==== Цепочки ====
 
Таблица nat содержит следующие цепочки:
* '''PREROUTING'''  — в эту цепочку пакеты попадают ''до'' принятия решения о маршрутизации. По сути, термин «решение о маршрутизации» подразумевает деление трафика на входящий (предназначенный самому хосту) и транзитный (идущий через этот хост на другие хосты). Именно на данном этапе нужно проводить операции проброса (DNAT, REDIRECT, NETMAP).
* '''OUTPUT'''  — через эту цепочку проходят пакеты, сгенерированные процессами самого хоста. На данном этапе при необходимости можно повторить операции проброса, так локально сгенерированные пакеты ''не'' проходят цепочку PREROUTING и ''не'' обрабатываются ее правилами. См. пример для действия DNAT ниже.
* '''POSTROUTING'''  — через эту цепочку проходят все исходящие пакеты, поэтому именно в ней целесообразно проводить операции {{w |маскарадинг}}а (SNAT и MASQUERADE).
 
==== Действия ====
 
Допустимыми действиями в таблице nat являются:
* '''MASQUERADE'''  — подменяет адрес источника для исходящих пакетов адресом того интерфейса, с которого они исходят, то есть осуществляет {{w |маскарадинг}}. Такая операция позволяет, например, предоставлять доступ в {{w |Интернет}} целым [[w:Локальная вычислительная сеть |локальным сетям]] через один [[w:Сетевой шлюз |шлюз]].
 
Допустим, у нас есть локальная сеть 192.168.1.0/255.255.255.0 с несколькими компьютерами, имеющими адреса 192.168.1.2, 192.168.1.3 и  т.  д. Адрес 192.168.1.1 имеет внутренний (подключенный к локальной сети) сетевой интерфейс шлюза, назовем этот интерфейс eth1. Другой его интерфейс, назовем его eth0, подключен к сети Интернет и имеет адрес, допустим, 208.77.188.166. Тогда, чтобы обеспечить выход хостов из этой локальной сети в Интернет, на шлюзе достаточно выполнить следующие команды
<source lang="bash">
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик
Строка 559 ⟶ 538 :
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
</source>
Теперь, если один из хостов локальной сети, например, 192.168.1.2, попытается связаться с одним из интернет-хостов, например, 199.204.44.194 (kernel.org), при проходе его пакетов через шлюз, их исходный адрес будет подменяться на внешний адрес шлюза, то есть 208.77.188.166. С точки зрения удаленного хоста (kernel.org), это будет выглядеть, как будто с ним связывается непосредственно сам шлюз. Когда же удаленный хост начнет ответную передачу данных, он будет адресовать их именно шлюзу, то есть 208.77.188.166. Однако, на шлюзе адрес назначения этих пакетов будет подменяться на 192.168.1.2, после чего пакеты будут передаваться настоящему получателю. Для такого обратного преобразования никаких дополнительных правил указывать не нужно  — это будет делать все та же операция MASQUERADE. Простота трансляции сетевых адресов является одним из важнейших достоинств stateful-фильтрации.
 
Если же такой трансляции не производить, удаленный хост просто не сможет ответить на адрес 192.168.1.2, так как адресные пространства локальных сетей изолировано от адресного пространства Интернета. В мире могут существовать миллионы локальных сетей 192.168.1.0/255.255.255.0, и в каждой может быть свой хост 192.168.1.2. Эти сети могут и не быть связаны с Интернетом. Но если они с ним связаны  — то только благодаря механизмам трансляции сетевых адресов.
 
* '''SNAT''' (Source Network Address Translation)  — работает аналогично MASQUERADE, однако позволяет указать адрес «внешнего» интерфейса (опция <tt>--to-source</tt>). Такой подход позволяет экономить процессорное время шлюза, так как в случае с MASQUERADE для каждого пакета адрес внешнего интерфейса определяется заново. Таким образом, если в предыдущем примере внешний адрес шлюза 208.77.188.166 является статическим (то есть никогда не меняется), команду
<source lang="bash">
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Строка 579 ⟶ 558 :
Теперь для каждого нового соединения адрес для подмены будет выбираться случайным образом.
 
* '''DNAT''' (Destination Network Address Translation)  — подменяет адрес назначения для входящих пакетов, позволяя «пробрасывать» адреса или отдельные порты внутрь локальной сети.
 
Возвращаясь к предыдущему примеру, предположим, что нам нужно «пробросить» внешний адрес шлюза 208.77.188.166 на хост 192.168.1.2, то есть все, кто будет обращаться по внешнему адресу шлюза 208.77.188.166, должны попадать на хост 192.168.1.2. Это достигается следующими командами:
Строка 601 ⟶ 580 :
iptables -t nat -A POSTROUTING -d 192.168.1.2 -s 192.168.1.0/24 -j SNAT --to-source 192.168.1.1
</source>
Теперь, с точки зрения 192.168.1.2, к нему будет обращаться только сам шлюз (192.168.1.1), поэтому ответ также пойдет через шлюз, где будет корректно оттранслирован. Такое решение тоже имеет недостаток  — подмена исходного адреса пакета приводит к тому, что компьютер, на который мы пробрасываем соединение, не может определить реального инициатора соединения. Чтобы уменьшить «вредность» этого правила, в него добавлена опция «-s 192.168.1.0/24», которая ограничивает применение этого правила только пакетами из локальной сети. Таким образом, соединения из локальной сети будут выглядеть как соединения, инициированные шлюзом, а соединения из внешней сети будут иметь свои оригинальные адреса.
 
Вторым недостатком предложенного примера является некорректная обработка запросов с самого шлюза. Ведь пакеты, генерируемые локальными процессами, не проходят цепочку PREROUTING. Поэтому правило DNAT нужно также добавить и в цепочку OUTPUT таблицы nat:
Строка 617 ⟶ 596 :
</source>
 
Кроме того, при помощи действия DNAT можно пробрасывать не только сразу весь IP-адрес, но и отдельные {{w |TCP}}- или {{w |UDP}}-[[w:Порт (компьютерные сети) |порты]]. Например, если в предыдущем примере мы в каждое из правил
<source lang="bash">
iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2
Строка 627 ⟶ 606 :
-p tcp --dport 80
</source>
то мы «пробросим» не сам адрес 208.77.188.166, а только его {{w |TCP}}-[[w:Порт (компьютерные сети) |порт]] 80 ({{w |HTTP}}). Обращения на все остальные {{w |TCP}}- и {{w |UDP}}-порты, а также {{w |ICMP}}-пакеты, поступившие на адрес 208.77.188.166, будут обрабатываться шлюзом, и лишь входящие TCP-соединения на порт 80 будут передаваться на 192.168.1.2.
 
Как и SNAT, DNAT поддерживает указание диапазонов адресов для подмены. Таким образом можно, например, балансировать нагрузку между несколькими серверами.
 
* '''REDIRECT'''  — подменяет номер порта в TCP- или UDP-пакете, а также подменяет адрес назначения на свой собственный. Например,
<source lang="bash">
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080
</source>
позволяет «завернуть» все исходящие из локальной сети TCP-соединения на порт 80, на TCP-порт 8080 шлюза. Если этот порт обслуживается специально настроенным {{w |прокси-сервер}}ом, то можно организовать «прозрачное проксирование»  — клиенты из локальной сети даже не будут подозревать, что их запросы идут через прокси-сервер. Разумеется, входящие соединения из локалки на TCP-порт 8080 должны быть разрешены в таблице filter.
 
Другой полезный пример:
Строка 644 ⟶ 623 :
«заворачивает» все входящие из Интернета, а точнее подсети 213.180.0.0/255.255.0.0 TCP-соединения на порт 80, переадресуя их на порт 8000 того же сервера (где, например, может работать специальный веб-сервер). Как обычно, входящие соединения на TCP-порт 8000 должны быть разрешены в таблице filter.
 
* '''SAME'''  — в зависимости от цепочки (PREROUTING или POSTROUTING) может работать как DNAT или SNAT. Однако, при указании (в параметре <tt>--to-ip</tt>) одного или нескольких диапазонов IP-адресов, определяет для каждого нового соединения подставляемый адрес не случайно, а базируясь на IP-адресе клиента. Таким образом, адрес для подмены остается постоянным для одного и того же клиента при повторных соединениях (что ''не'' выполняется для обычных DNAT/SNAT). В некоторых случаях это бывает важным. Примечание: в соответсвиисоответствии с iptables-extensions'sextensions’s man page действие SAME убрано и заменено на опцию --persistent для действий '''DNAT'''/'''SNAT'''.
* '''NETMAP'''  — позволяет «пробросить» целую сеть. Например, для шлюза, стоящего между сетями 192.168.1.0/24 и 192.168.2.0/24 можно организовать следующий проброс:
<source lang="bash">
iptables -t nat -A PREROUTING -s 192.168.1.0/24 -d 192.168.3.0/24 -j NETMAP --to 192.168.2.2/24
</source>
Теперь, при обращении, например, хоста 192.168.1.3 на IP-адрес 192.168.3.2 он будет попадать на 192.168.2.2 (при условии, что такой транзитный трафик разрешен на шлюзе в цепочке FORWARD таблицы filter, а также на хостах сети 192.168.1.0/24 наш шлюз [[w:Маршрутизация |прописан]] в качестве шлюза для подсети 192.168.3.0/24).
 
: ''Примечание: следующее действие планируется к переносу в еще не написанный раздел статьи (Устаревшие критерии и действия)''.
* '''MIRROR'''  — довольно интересная игрушка. Меняет местами адрес источника и назначения и высылает пакет обратно. Создано исключительно для демонстрационных целей. Однако, может, например, применяться для защиты от сканирования портов  — в результате атакующий сканирует свои собственные порты. Однако наличие двух встречных MIRROR’ов на двух хостах может повлечь бесконечное блуждание одних и тех же пакетов, забивающее канал. Поэтому применяйте это действие с осторожностью.
 
=== Таблица filter ===
 
Предназначена для фильтрации трафика, то есть разрешения и запрещения пакетов и соединений.
 
==== Цепочки ====
 
Таблица filter содержит следующие цепочки:
* '''INPUT'''  — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту.
* '''FORWARD'''  — позволяет фильтровать транзитный трафик.
* '''OUTPUT'''  — эта цепочка позволяет фильтровать трафик, исходящий от самого хоста.
 
==== Действия ====
 
Допустимыми действиями в таблице filter являются:
* '''ACCEPT'''  — пропуск пакета. Пакет покидает текущую базовую цепочку и следует дальше по потоковой диаграмме (см. рис.).
* '''REJECT'''  — заблокировать пакет и сообщить его источнику об отказе. По умолчанию об отказе сообщается отправкой ответного {{w |ICMP}}-пакета «icmp-port-unreachable». Однако, это действие поддерживает опцию <tt>--reject-with</tt>, позволяющую указать формулировку сообщения об отказе (возможные значения: <tt>icmp-net-unreachable</tt>, <tt>icmp-host-unreachable</tt>, <tt>icmp-proto-unreachable</tt>, <tt>icmp-net-prohibited</tt>, <tt>icmp-host-prohibited</tt>). Для протокола {{w |TCP}} поддерживается отказ в форме отправки RST-пакета (<tt>--reject-with tcp-reset</tt>).
* '''DROP'''  — заблокировать пакет, не сообщая источнику об отказе. Более предпочтительна при фильтрации трафика на интерфейсах, подключенных к интернету, так как понижает информативность сканирования портов хоста злоумышленниками.
 
Также определенный интерес представляют действия, предоставляемые модулями [http://xtables-addons.sourceforge.net/ xtables-addons] (в настоящее время этот проект уже [http://packages.debian.org/squeeze/xtables-addons-common включен] в {{w |Debian}} testing). Некоторые из них:
* '''STEAL'''  — аналогично DROP, но в случае использования в цепочке OUTPUT при блокировании исходящего пакета не сообщает об ошибке приложению, пытавшемуся отправить этот пакет.
* '''TARPIT'''  — «подвесить» {{w |TCP}}-соединение. Используется лишь в самых крайних случаях, например, при борьбе с {{w |DoS-атака}}ми. Отвечает на входящее соединение, после чего уменьшает размер фрейма до нуля, блокируя возможность передачи данных. Соединение будет «висеть» в таком состоянии пока не истечет тайм-аут на атакующей стороне (обычно 20—30 минут). При этом на такое соединение расходуются системные ресурсы атакующей стороны (процессорное время и оперативная память), что может быть весьма ощутимо при значительном количестве соединений. В случае правильного использования действия TARPIT ресурсы атакуемой стороны практически не расходуются.
Под правильным применением понимается предотвращение обработки таких соединений подсистемой [[conntrack]], так как в противном случае будут расходоваться системные ресурсы самого атакуемого хоста. Например, перед добавлением правила блокирования порта
<source lang="bash">
Строка 684 ⟶ 660 :
</source>
предотвращающее обработку блокируемых соединений подсистемой conntrack.
* '''DELUDE'''  — создать видимость открытого TCP-порта. На SYN-пакеты отвечает пакетами SYN/ACK, на все прочие пакеты отвечает RST. Очень полезно для введения в заблуждение злоумышленника, сканирующего порты вашего хоста.
* '''CHAOS'''  — для каждого нового TCP-соединения случайно выбрать одно из двух действий. Первое из них  — REJECT, второе, в зависимости от выбранной опции, либо TARPIT (<tt>--tarpit</tt>), либо DELUDE (<tt>--delude</tt>). В частности, при использовании действия <tt>CHAOS --delude</tt> для всех неиспользуемых портов, сканирующий ваши порты злоумышленник получит совершенно неверную информацию о состоянии ваших портов. В случае с <tt>CHAOS --tarpit</tt> ситуация усугубится еще и «подвисающими» соединениями.
 
Особо заметим, что все действия, перечисленные в качестве допустимых в таблице filter, можно применять в любой из цепочек любой из таблиц (конечно, с разумными ограничениями  — например, не стоит ставить действия TARPIT, CHAOS и DELUDE для собственных исходящих пакетов). Однако эти действия предназначены именно для фильтрации, и применение их за пределами таблицы filter является дурным тоном. Как и, например, применение действий, специфичных для таблицы mangle, в таблицах filter и nat.
 
=== Таблица security ===
 
Предназначена для изменения маркировки безопасности (меток {{w |SELinux}}) пакетов и соединений.
 
==== Цепочки ====
 
Аналогичны цепочкам таблицы filter:
* '''INPUT'''  — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту.
* '''FORWARD'''  — через эту цепочку проходит транзитный трафик.
* '''OUTPUT'''  — эта цепочка позволяет обрабатывать трафик, исходящий от самого хоста.
 
Так как эта таблица появилась относительно недавно, ее редко можно увидеть на схемах следования пакетов через цепочки и таблицы {{w |netfilter}}'а. Поэтому стоит отметить, что все цепочки таблицы security пакеты проходят непосредственно после одноименных цепочек таблицы filter.
 
==== Действия ====
Данная таблица добавлена в ядро [[w:Ядро Linux|Linux]] в версии 2.6.27. Ранее операции с метками безопасности выполнялись в таблице mangle, и в целях обратной совместимости все действия, разрешенные для таблицы security, можно использовать и в таблице mangle.
 
* '''SECMARK''' — устанавливает для пакета контекст безопасности {{w |SELinux}} (единственная допустимая опция <tt>--selctx</tt>).
Данная таблица добавлена в ядро [[w:Ядро Linux |Linux]] в версии 2.6.27. Ранее операции с метками безопасности выполнялись в таблице mangle, и в целях обратной совместимости все действия, разрешенные для таблицы security, можно использовать и в таблице mangle.
* '''CONNSECMARK''' — позволяет скопировать контекст безопасности SELinux с отдельного пакета на соединение в целом (опция <tt>--save</tt>) и наоборот (опция <tt>--restore</tt>).
 
* '''SECMARK''' — устанавливает для пакета контекст безопасности {{w |SELinux}} (единственная допустимая опция <tt>--selctx</tt>).
* '''CONNSECMARK''' — позволяет скопировать контекст безопасности SELinux с отдельного пакета на соединение в целом (опция <tt>--save</tt>) и наоборот (опция <tt>--restore</tt>).
 
=== Таблица raw ===
 
Предназначена для выполнения действий с пакетами до их обработки системой [[conntrack]].
 
Обратите внимание, что в данной таблице не&nbsp; будут срабатывать критерии, которым для корректной работы необходим conntrack (это критерии conntrack, connmark, connlimit, connbytes).
 
==== Цепочки ====
* '''PREROUTING''' — в эту цепочку входящие пакеты попадают раньше, чем в любую другую из цепочек iptables, и ''до'' обработки их системой conntrack.
 
* '''OUTPUT''' — аналогично для пакетов, сгенерированных самим хостом.
* '''PREROUTING''' — в эту цепочку входящие пакеты попадают раньше, чем в любую другую из цепочек iptables, и ''до'' обработки их системой conntrack.
* '''OUTPUT''' — аналогично для пакетов, сгенерированных самим хостом.
 
==== Действия ====
 
<!-- В таблице raw целесообразно применять действие '''NOTRACK''', позволяющее предотвратить обработку пакетов системой conntrack. Разумеется, применять ее стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше). -->
* '''NOTRACK'''  — позволяет предотвратить обработку пакетов системой conntrack. Разумеется, применять его стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше).
* '''CT'''  — более функциональный инструмент, добавленный в версии [[w:Ядро Linux |Linux]] 2.6.34. Позволяет задать различные настройки [[conntrack]], в соответствии с которыми будет обрабатываться соединение, открытое данным пакетом. В частности, можно:
:* Отключить отслеживание соединения (опция <tt>--notrack</tt>). Таким образом, функциональность действия CT включает и функциональность NOTRACK, так что, возможно, действие NOTRACK будет объявлено устаревшим.
:* Задать вспомогательный модуль (conntrack helper) для данного соединения. Если раньше указать нестандартные порты для такого модуля можно было только в параметрах его загрузки (<tt>/etc/modprobe.conf</tt> или <tt>/etc/modprobe.d/netfilter.conf</tt>, например, <tt>options nf_conntrack_ftp ports=2121</tt>), то теперь это можно сделать и через правила netfilter:
Строка 734 ⟶ 704 :
iptables -t raw -I PREROUTING -p tcp --dport 8000 -j CT --ctevents new,destroy
</source>
: будет предписывать для всех соединений на {{w |TCP}}-[[w:Порт (компьютерные сети) |порт]] 8000 генерировать только события «открытие соединения» (NEW) и «завершение соединения» (DESTROY), игнорируя все прочие события. Полный список возможных событий: new, related, destroy, reply, assured, protoinfo, helper, mark, natseqinfo, secmark.
:* Задать ''зону conntrack'' для данного пакета (параметр <tt>--zone</tt>). Механизм зон conntrack позволяет корректно отслеживать, фильтровать и {{w |NAT}}'ить соединения даже в том случае, если хост подключен к нескольким сетям, использующим одинаковые пространства имен, через различные интерфейсы (например, интерфейсы eth0 и eth1 подключены к двум разным сетям, но обе эти сети используют пространство 192.168.0.0/24). Традиционно, для идентификации соединений conntrack использует кортежи (tuples)  — набор значений в который входят адреса и порты (в случае ICMP  — типы и коды ICMP) источника и назначения при передаче данных в прямом и обратном направлении. Очевидно, что при наличии нескольких подсетей с одинаковыми адресными пространствами, возможно возникновение путаницы, когда сразу нескольким соединениям ставится в соответствие одна и та же запись в таблице соединений. Чтобы избежать такой ситуации, в кортеж был добавлен идентификатор зоны conntrack  — целое число, которое можно устанавливать через специальное правило в таблице raw в зависимости от входящего/исходящего интерфейса (как уже говорилось выше, цепочки таблицы raw пакеты проходят еще до обработки их conntrack’ом). Например,
<source lang="bash">
iptables -t raw -I PREROUTING -i eth1 -j CT --zone 1
iptables -t raw -I OUTPUT -o eth1 -j CT --zone 1
</source>
: Таким образом, пакеты, входящие или исходящие через интерфейс eth1, будут получать идентификатор зоны 1, в то время как пакеты интерфейса eth0 будут по-прежнему использовать зону по умолчанию (идентификатор 0), и путаницы не&nbsp; произойдет.
: Кроме того, идентификатор зоны можно задать для каждого интерфейса через {{w |sysfs}}, минуя iptables (псевдофайл <tt>/sys/class/net/имя_интерфейса/nf_ct_zone</tt>):
<source lang="bash">
Строка 746 ⟶ 716 :
</source>
: Однако, стоит заметить, что iptables/netfilter позволяют реализовать более гибкую логику управления идентификатором зоны, опирающуюся на различные параметры пакетов, и поэтом данный параметр действия CT может быть полезен при решении различных сложных задач управления трафиком при использовании зон conntrack.
* '''RAWDNAT'''  — позволяет выполнять [[w:NAT |«проброс»]] адресов и портов «сырым» методом  — без использования системы conntrack, то есть без учета состояний соединений. Это действие реализовано в рамках проекта xtables-addons. Применять его можно только в таблице raw. Имеет единственную опцию <tt>--to-destination ''адрес''[/''маска'']</tt>, по смыслу аналогичную опции <tt>--to</tt> действия NETMAP, то есть при указании маски заменяются только те биты в адресе, которые соответствуют единичным битам маски. Биты адреса, соответствующие нулевым битам маски, остаются неизменными. При отсутствии маски изменяется весь адрес.
 
: Отметим, что в отличие от действий [[#Таблица nat|таблицы nat]], которые работают только с соединениями в целом, операции «сырого» преобразования адресов работают только с отдельными пакетами, никак не&nbsp; учитывая контекст их передачи. Вышесказанное можно проиллюстрировать, скажем, таким простым примером: для элементарной операции «проброса» внешнего адреса на другой адрес при использовании обычных операций NAT достаточно одного правила<ref>На самом деле, для «чистого» проброса адреса, даже при использовании stateful NAT, необходимо обычно два или три правила, в частности, для проброса соединений с самого сервера в цепочке OUTPUT. Более подробно это описано при рассмотрении операции DNAT [[#Таблица nat|таблицы nat]], и здесь, с целью упрощения понимания примера, эти аспекты опущены</ref>
<source lang="bash">
iptables -t nat -A PREROUTING -i eth0 -d 212.201.100.135 -j DNAT --to-destination 199.181.132.250
Строка 757 ⟶ 727 :
iptables -t rawpost -A POSTROUTING -o eth0 -s 199.181.132.250 -j RAWSNAT --to-source 212.201.100.135
</source>
: Как уже говорилось выше, при использовании обычной операции DNAT в ответных пакетах, приходящих с пробрасываемого адреса (199.181.132.250), производится автоматическая (без необходимости писать для этого отдельные правила) подмена исходного адреса на изначальный (212.201.100.135), и обращающиеся по адресу 212.201.100.135 хосты даже не&nbsp; подозревают, что общаются с кем-то другим. В случае же «сырого» преобразования такая автоматическая обработка невозможна, так как она требует возможности проверять пакеты на принадлежность соединению. С другой стороны, операции «сырого» преобразования являются более гибким инструментом, а также могут работать даже с UNTRACKED и INVALID-пакетами.
 
=== Таблица rawpost ===
Данная таблица предназначена для выполнения операций «сырого» преобразования адресов (без использования информации о соединениях), которые не могут быть реализованы в рамках таблицы raw, а именно, для операции «сырой» подмены исходного адреса ({{w |маскарадинг}}а).
 
Как и в таблице raw, в rawpost отсутствует возможность обращения к [[conntrack]], поэтому критерии, использующие эту подсистему (conntrack, connmark, connlimit, connbytes), в этой таблице работать не будут.
Данная таблица предназначена для выполнения операций «сырого» преобразования адресов (без использования информации о соединениях), которые не&nbsp;могут быть реализованы в рамках таблицы raw, а именно, для операции «сырой» подмены исходного адреса ({{w |маскарадинг}}а).
 
Как и в таблице raw, в rawpost отсутствует возможность обращения к [[conntrack]], поэтому критерии, использующие эту подсистему (conntrack, connmark, connlimit, connbytes), в этой таблице работать не&nbsp;будут.
 
Данная таблица реализована в рамках проекта xtables-addons и отсутствует в стандартном комплекте iptables/netfilter.
 
==== Цепочки ====
* '''POSTROUTING''' — обрабатывает весь исходящий трафик.
 
* '''POSTROUTING''' — обрабатывает весь исходящий трафик.
 
==== Действия ====
 
В таблице rawpost можно использовать действие '''RAWSNAT''', выполняющее операцию «сырой» подмены исходного адреса. Имеет единственную опцию <tt>--to-source ''адрес''[/''маска'']</tt>, позволяющую задать новый исходный адрес для обрабатываемых пакетов. Как обычно, при наличии маски, в обрабатываемых адресах изменяются только те биты, которые в маске установлены в единицу, при отсутствии маски адрес изменяется целиком. Например, если по правилу
<source lang="bash">
Строка 779 ⟶ 746 :
будет обработан пакет с исходным адресом 10.125.32.28, то этот адрес будет заменен на 192.168.32.28.
 
Если же при задании правила маску /16 в параметре <tt>--to-source</tt> опустить, адрес будет заменен на 192.168.0.20. Но так лучше не&nbsp; делать, потому что мы выполняем трансляцию для всех пакетов из подсети 10.125.0.0/16, и без отслеживания соединений не&nbsp; сможем отличить, какие пакеты следует вернуть 10.125.32.28, а какие  — другим хостам из этой подсети. Сама же операция «возвращения» пакетов требует отдельного RAWDNAT-правила:
<source lang="bash">
iptables -t raw -A PREROUTING -i eth0 -s 172.18.1.100 -d 192.168.0.0/16 -j RAWDNAT --to-destination 10.125.0.0/16
</source>
которое выполняет обратную подмену, заменяя адреса назначения в пакетах-ответах. Таким образом, хост 172.18.1.100 будет считать, что к нему обращаются хосты из подести 10.125.0.0/16, а вовсе не&nbsp; из 192.168.0.0/16.
 
Для сравнения, с использованием stateful-преобразования достаточно одного правила
Строка 794 ⟶ 761 :
 
== Критерии ==
Напоминаем, критерий — это логическое выражение, определяющее, соответствует ли пакет или соединение данному конкретному правилу.
 
Напоминаем, критерий — это логическое выражение, определяющее, соответствует ли пакет или соединение данному конкретному правилу.
 
В одном правиле можно указать несколько критериев. Для того, чтобы пакет был обработан правилом, должны выполняться ''все'' критерии, то есть критерии неявно объединяются логическим AND.
 
Также многие критерии и параметры критериев можно инвертировать, поставив перед ними восклицательный знак. В описании синтаксиса таких критериев присутствует пометка «<tt>[!]</tt>». Инверсия меняет смысл критерия или его параметра на ровно противоположный. Например, критерию <tt>-s 127.0.0.1</tt> соответствуют все пакеты, имеющие обратный адрес 127.0.0.1, а критерию <tt>! -s 127.0.0.1</tt>  — все пакеты, ''кроме'' имеющих обратный адрес 127.0.0.1. В ранних версиях iptables восклицательный знак можно было ставить между названием критерия и значением, например, <tt>-s ! 127.0.0.1</tt>, однако последние версии iptables (в частности, 1.4.3.2 и выше), уже не поддерживают этот синтаксис, выдавая следующую ошибку:
Using intrapositioned negation (`--option ! this`) is deprecated in favor of extrapositioned (`! --option this`).
 
Строка 805 ⟶ 771 :
 
=== Универсальные критерии ===
 
Под этим термином понимаются критерии, применимые ко все пакетам и соединениям, независимо от протокола транспортного уровня, и не требующие подключения внешних модулей (<tt>-m</tt>).
 
Строка 812 ⟶ 777 :
Позволяет указать протокол транспортного уровня. Наиболее часто употребляются <tt>[[tcp]]</tt>, <tt>[[udp]]</tt>, <tt>[[icmp]]</tt> и <tt>all</tt>. Протокол также можно указать с помощью номера или названия согласно перечню, приведенному в <tt>/etc/protocols</tt>. Значение «любой протокол» можно указать с помощью слова <tt>all</tt> или числа 0. Если протокол не указан, подразумевается «любой протокол».
 
При указании протокола становится возможным использовать специфичные для него критерии. Например, для {{w |TCP}} и {{w |UDP}} доступны критерии <tt>--sport</tt> и <tt>--dport</tt>, для {{w |ICMP}}  — <tt>--icmp-type</tt>. Подробнее эти критерии будут рассмотрены ниже.
 
* <tt>[!] '''-s'''</tt>, <tt>--src</tt>, <tt>--source ''адрес''[/''маска''][,''адрес''[/''маска'']...]</tt>
 
Определяет адрес отправителя. В качестве адреса может выступать {{w |IP-адрес}} (возможно с [[w:Маска подсети |маской]]), имя хоста из /etc/hosts, или {{w |доменное имя}} (в последних двух случаях перед добавлением правила в цепочку имя [[w:DNS |резольвится]] в IP-адрес). Маска подсети может быть указана в классическом формате (например, 255.255.0.0) либо в формате {{w |CIDR}} (например, 16)<ref>Заметим, что для расчета масок подсетей и диапазонов адресов существует очень удобная утилита [[ipcalc]].</ref>. Например,
<source lang="bash">
iptables -I INPUT -i eth0 -s 192.168.0.0/16 -j DROP
</source>
(где eth0  — интерфейс, подключенный к интернету), позволяет заблокировать простейший вид {{w |спуфинг}}а  — из интернета ''не могут'' приходить пакеты с обратным адресом, принадлежащим к диапазону, зарезервированному для локальных сетей.
 
Начиная с версии iptables 1.4.6, в одном параметре <tt>-s</tt> можно указывать более одного адреса, разделяя адреса запятой. При этом для каждого адреса будет добавлено ''отдельное'' правило. Например, запись
Строка 834 ⟶ 799 :
При добавлении через команду <tt>-A</tt> (вставка в конец цепочки) порядок добавляемых правил будет соответствовать порядку перечисления адресов в исходной команде, при использовании команды <tt>-I</tt> (вставка в начало цепочки либо после заданного правила) порядок будет обратным исходному.
 
Настойчиво не рекомендуется использовать доменные имена, для разрешения (резольва) которых требуются {{w |DNS}}-запросы, так как на этапе конфигурирования фаервола DNS может работать некорректно. Также, заметим, имена резольвятся всего один раз  — при добавлении правила в цепочку. Впоследствии соответствующий этому имени IP-адрес может измениться, но на уже записанные правила это никак не повлияет (в них останется старый адрес). Если указать доменное имя, которое резольвится в несколько {{w |IP-адрес}}ов, то для каждого адреса будет добавлено отдельное правило (как и в случае перечисления нескольких адресов, см. выше).
 
* <tt>[!] '''-d'''</tt>, <tt>--dst</tt>, <tt>--destination ''адрес''[/''маска''][,''адрес''[/''маска'']...]</tt>
Строка 858 ⟶ 823 :
iptables -I INPUT -i lo -j ACCEPT
</source>
позволит принимать весь трафик, входящий через интерфейс [[w:Loopback |обратной петли]].
 
* <tt>[!] '''-o'''</tt>, <tt>--out-interface ''имя_интерфейса''</tt>
Строка 866 ⟶ 831 :
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE
</source>
будет [[w:Маскарадинг |маскарадить]] весь трафик, исходящий через интерфейс eth0.
 
=== Критерии, специфичные для протоколов ===
 
==== Протоколы [[w:Транспортный уровень |транспортного уровня]] ====
 
===== {{w |TCP}} =====
 
* <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt>
 
Строка 880 ⟶ 844 :
iptables -I INPUT -m conntrack --ctstate NEW -p tcp --sport 0:1023 -j DROP
</source>
заблокирует все входящие соединения с [[w:Список портов TCP и UDP |привилегированных]] портов (''привилегированными'' в TCP/UDP считаются порты с 0 по 1023 включительно, так как для их использования нужны привилегии [[w:Root |суперпользователя]], и обычно такие порты используются [[w:Демон (программа) |демонами]] только в режиме прослушивания).
 
* <tt>[!] '''--dport'''</tt>, <tt>--destination-port ''порт''[:''порт'']</tt>
Строка 892 ⟶ 856 :
* <tt>[!] '''--tcp-flags''' ''маска'' ''установленные_флаги''</tt>
 
Позволяет указать список установленных и снятых [[w:TCP#Флаги (управляющие биты) |TCP-флагов]]. В ''маске'' перечисляются (через запятую, без пробелов) все проверяемые флаги, далее, после пробела, перечисляются (также через запятую) те из них, которые должны быть установлены. Все остальные перечисленные в маске флаги должны быть сняты. Возможные флаги: SYN ACK FIN RST URG PSH. Также можно использовать псевдофлаги ALL и NONE, обозначающие «все флаги» и «ни одного флага» соответственно.
 
Пример:
Строка 924 ⟶ 888 :
 
===== {{w |UDP}} =====
 
* <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt>
 
Строка 934 ⟶ 897 :
 
===== {{w |SCTP}} =====
 
* <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt>
 
Строка 945 ⟶ 907 :
* <tt>[!] '''--chunk-types''' {all|any|only} ''тип_секции''[:''флаги''][,''тип_секции''[:''флаги'']...]</tt>
 
Позволяет анализировать набор [[:en:SCTP_packet_structureSCTP packet structure|секций (chunks)]], входящих в состав SCTP-пакета. Возможные типы секций: DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK. Также, для секций, имеющих флаги (DATA, ABORT и SHUTDOWN_COMPLETE) можно проверить состояние флагов, указав соответствующие буквы после названия секции (для DATA  — U, B и E, для ABORT и SHUTDOWN_COMPLETE  — T). Литера в верхнем регистре предполагает установленный флаг, в нижнем  — снятый. Ключевое слово в начале позволяет определить логику работы: в случае <tt>all</tt> должны присутствовать ''все'' перечисленные секции, для <tt>any</tt>  — хотя бы одна из них, для <tt>only</tt>  — пакет должен состоять только из перечисленных секций. Примеры:
<source lang="bash">
iptables -I INPUT -p sctp --chunk-types only DATA,INIT -j DROP
Строка 956 ⟶ 918 :
 
===== {{w |DCCP}} =====
 
* <tt>[!] '''--sport'''</tt>, <tt>--source-port ''порт''[:''порт'']</tt>
 
Строка 974 ⟶ 935 :
 
===== {{w |UDP Lite}} =====
 
Поддержка специфических опций протокола UDPLite (а именно, проверки портов источника и/или назначения) в netfilter реализована не вполне очевидным образом: через критерий multiport (см. раздел [[#Вспомогательные критерии|вспомогательные критерии]]).
 
Строка 980 ⟶ 940 :
 
==== {{w |IPv4}} ====
Ниже перечислены критерии, которые реализованы только для протокола IPv4 и, соответственно, могут быть вызваны только через iptables, но не через ip6tables.
 
Ниже перечислены критерии, которые реализованы только для протокола IPv4 и, соответственно, могут быть вызваны только через iptables, но не&nbsp;через ip6tables.
 
* <tt>[!] '''-f'''</tt>, <tt>--fragment</tt>
Строка 991 ⟶ 950 :
блокирует фрагменты {{w |ICMP}}-пакетов. Так как, в силу функционального назначения протокола, ICMP-пакеты должны быть очень небольшими и нормально укладываться в {{w |MTU}}, наличие их фрагментов обычно свидетельствует об ошибке или попытке атаки.
 
У второго и последующего фрагментов нет заголовка транспортного уровня, поэтому бессмысленно пытаться использовать для них критерии номеров [[w:Порт (компьютерные сети) |TCP/UDP-портов]] или типа ICMP.
 
* '''addrtype'''  — позволяет проверить тип адреса источника и/или назначения с точки зрения подсистемы маршрутизации сетевого стека ядра. Допустимые типы адресов: UNSPEC (адрес 0.0.0.0), [[w:Unicast |UNICAST]], LOCAL (адрес принадлежит нашему хосту), [[w:Broadcast |BROADCAST]], [[w:Anycast |ANYCAST]], [[w:Мультивещание |MULTICAST]], [[:en:Black hole (networking)|BLACKHOLE]], UNREACHABLE, PROHIBIT, THROW, NAT, XRESOLVE. Подробнее о большинстве перечисленных типов адресов и их использовании в [[w:Ядро Linux |Linux]] (точнее, в подсистеме {{w |iproute2}}) можно почитать [http://linux-ip.net/html/routing-tables.html здесь]. Данный критерий поддерживает следующие параметры:
 
<tt>[!] --src-type ''тип''[,''тип''...]</tt>  — проверка, принадлежит ли исходный адрес пакета одному из перечисленных типов.
 
<tt>[!] --dst-type ''тип''[,''тип''...]</tt>  — проверка, принадлежит ли адрес назначения пакета одному из перечисленных типов.
 
<tt>--limit-iface-in</tt>  — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вошел на хост. Допускается использовать этот параметр только в цепочках PREROUTING, INPUT и FORWARD.
 
<tt>--limit-iface-out</tt>  — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вышел с хоста. Допускается использовать этот параметр только в цепочках POSTROUTING, OUTPUT и FORWARD.
 
Критерии <tt>--limit-iface-in</tt> и <tt>--limit-iface-out</tt> нельзя указывать одновременно.
Строка 1011 ⟶ 970 :
Это правило заблокирует пакеты, которые пришли с внешних интерфейсов, но при этом в качестве обратного адреса у них указан один из адресов, принадлежащих нашему хосту (например, {{w |127.0.0.1}}).
 
* '''ecn'''  — позволяет проверять значения битов [[w:Explicit Congestion Notification |ECN]] в заголовках {{w |TCP}} и {{w |IPv4}}. Допустимые параметры:
 
<tt>[!] --ecn-tcp-cwr</tt>  — проверка флага ECN CWR (Congestion Window Received) в TCP-заголовке пакета.
 
<tt>[!] --ecn-tcp-ece</tt>  — проверка флага ECN ECE (ECN Echo) в TCP-заголовке пакета.
 
<tt>[!] --ecn-ip-ect ''значение''</tt>  — проверка значения, сформированного ECN-битами поля [[w:Тип обслуживания |TOS]] (последние два бита). Возможные значения от 0 до 3.
 
* '''realm'''  — проверка области маршрутизации (realm) пакета. Имеет единственный параметр
 
<tt>[!] --realm ''значение''[/''маска'']</tt>, позволяющий указать численный идентификатор области. Если указана маска, то значение realm каждого проверяемого пакета сначала объединяется с маской при помощи [[w:Битовые операции#Побитовое И (AND) |побитового AND]], а затем сравнивается со значением, указанным в правиле. Также вместо числа можно указать символьное название области согласно обозначениям в файле <tt>/etc/iproute2/rt_realms</tt> (в этом случае маску использовать нельзя).
 
* '''ttl'''  — обеспечивает проверку поля [[w:Time to live |TTL]] в заголовке пакета. Позволяет установить, является ли значение TTL проверяемого пакета большим (<tt>--ttl-gt</tt>), меньшим (<tt>--ttl-lt</tt>), равным или не&nbsp; равным (<tt>[!] --ttl-eq</tt>) указанному значению.
 
===== {{w |ICMP}} =====
ICMP является протоколом контрольных сообщений IPv4. Несмотря на то, что ICMP формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv4, и поэтому соответствующий критерий может использоваться только в iptables, но не в ip6tables.
 
ICMP является протоколом контрольных сообщений IPv4. Несмотря на то, что ICMP формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не&nbsp;для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv4, и поэтому соответствующий критерий может использоваться только в iptables, но не&nbsp;в ip6tables.
 
Критерий этого протокола имеет единственный параметр
 
<tt>[!] '''--icmp-type''' ''тип''</tt>  — обеспечивает проверку [[w:ICMP#Типы ICMP пакетов (полный список) |типа]] ICMP-пакета. Список возможных типов выводится по команде <tt>iptables -p icmp -h</tt>. Также можно указать стандартные числовые тип и, при
необходимости, код. Например,
<source lang="bash">
Строка 1043 ⟶ 1001 :
 
==== {{w |IPv6}} ====
Ниже перечислены критерии, которые реализованы только для протокола IPv6 и, соответственно, могут быть вызваны только через ip6tables, но не через iptables.
 
Ниже перечислены критерии, которые реализованы только для протокола IPv6 и, соответственно, могут быть вызваны только через ip6tables, но не&nbsp;через iptables.
 
Особо отметим, что критерии для некоторых подзаголовков IPv6 (dst, frag, hbh, rt) корректно вызываются ''только'' с использованием синтаксиса для расширенных критериев (ключ <tt>-m</tt>), хотя имеют номера протоколов в <tt>/etc/protocols</tt> и, формально, могут быть вызваны с использованием синтаксиса для протоколов (ключ <tt>-p</tt>) что, однако, является неверным. В таких случаях ip6tables выдает предупреждение вида
Строка 1050 ⟶ 1007 :
Warning: never matched protocol: ipv6-frag. use extension match instead.
</source>
гласящее, что в такое правило никогда не&nbsp; будет срабатывать. Если вы видите подобное предупреждение, удалите правило, которое его вызвало, и перепишите это правило с использованием корректного синтаксиса (<tt>-m</tt>).
 
С другими же критериями, которые представляют более или менее самостоятельные протоколы ({{w |ICMPv6}}, [[MH]], {{w |IPSec}} [[:en:IPSec#Authentication_HeaderAuthentication Header|AH]] и [[:en:IPSec#Encapsulating_Security_PayloadEncapsulating Security Payload|ESP]]), все ровно наоборот, и для них корректным будет использование именно синтаксиса протокола (ключ <tt>-p</tt>), а не&nbsp; расширенного критерия. Во избежание путаницы, такие критерии вынесены в отдельные подзаголовки, по аналогии с протоколами транспортного уровня (выше).
 
* '''dst'''  — проверят опции назначения (подзаголовок 60 Destination Options). Имеет две опции:
 
<tt>[!] --dst-len ''значение''</tt>  — проверяет длину подзаголовка;
 
<tt>[!] --dst-opts ''код''[:''длина''][,''код''[:''длина'']...]</tt>  — позволяет проверить вхождение в данный подзаголовок конкретных опций. Также можно проверить длину каждой из них. Можно указать до 16 опций (представленных числовыми кодами), разделяя их запятой.
 
* '''eui64'''  — сравнивает младшие 64 бита исходного IPv6-адреса с битами исходного {{w |MAC-адрес}}а, преобразованными согласно правилам автоконфигурирования IPv6-адресов на основании MAC-адресов. Таким образом, позволяет проверить, является ли IPv6-адрес отправителя пакета автоматически сконфигурированным (работает, если отправитель находится в одном [[w:Широковещательный домен |широковещательном домене]] с нашим хостом, так как в противном случае сохранность MAC-адреса отправителя не&nbsp; может быть гарантирована).
* '''frag'''  — позволяет проверять параметры фрагментации (подзаголовок 44 Fragment). Допустимые опции:
 
<tt>[!] --fragid ''мин''[:''макс'']</tt>  — сверяет величину идентификатора фрагмента. Если указано одно значение, проверяется равенство, если указан диапазон  — проверяется вхождение значения в этот диапазон (включая границы).
 
<tt>--fragres</tt>  — проверяет, заполнены ли нулями зарезервированные поля заголовка (биты 29-30).
 
<tt>--fragfirst</tt>  — проверяет, является ли данный фрагмент первым в последовательности.
 
<tt>--fraglast</tt>/<tt>--fragmore</tt>  — проверяют M-флаг, показывающий, является ли данный фрагмент последним в последовательности (в этом случае <tt>--fraglast</tt> дает истину, а <tt>--fragmore</tt> ложь), или после него должны быть еще фрагменты (соответственно, наоборот). Эти две опции являются взаимоисключающими.
 
Также в документации можно найти упоминание параметра <tt>--fraglen </tt>, который якобы проверяет длину подзаголовка Fragment. Однако, согласно текущим соглашениям, длина этого подзаголовка фиксирована и равна 8&nbsp; {{w |байт}}ам, а названная опция ни на что не&nbsp; влияет.
 
* '''hbh'''  — проверяет опции Hop-by-Hop (подзаголовок 0 Hop-by-Hop). Синтаксис аналогичен параметру dst.
* '''hl'''  — обеспечивает проверку поля Hop Limit в IPv6-заголовке. Позволяет установить, является ли значение HL проверяемого пакета большим (<tt>--hl-gt</tt>), меньшим (<tt>--hl-lt</tt>), равным или не&nbsp; равным (<tt>[!] --hl-eq</tt>) указанному значению.
* '''ipv6header'''  — позволяет проверить наличие вспомогательных подзаголовков IPv6. Допустимыми типами заголовков являются: hop (hop-by-hop 0), dst (ipv6-opts 60), route (ipv6-route 43), frag (ipv6-frag 44), auth (ah 50), esp (esp 59). В скобках указаны «длинные» названия и числовые идентификаторы протокола. Используя опцию
 
<tt>[!] --header ''тип''[,''тип''...]</tt>
 
вы можете указывать любые из этих обозначений  — короткие названия, длинные названия или числовые идентификаторы. Отметим, что пакет будет соответствовать критерию в том случае, если будет содержать ''только'' перечисленные подзаголовки. Изменить это поведение можно, указав опцию <tt>--soft</tt>  — в этом случае достаточно, чтобы пакет содержал хотя бы один из перечисленных подзаголовков.
 
* '''rt'''  — позволяет проверять параметры маршрутизации пакета (подзаголовок 43 Routing). Допустимые параметры:
 
<tt>[!] --rt-type ''тип''</tt>  — тип маршрутизации (0, 1 или 2);
 
<tt>[!] --rt-segsleft ''мин''[:''макс'']</tt>  — проверка значения поля Segment Left (показывает, сколько еще узлов должен пройти данный пакет, прежде чем достигнет цели);
 
<tt>[!] --rt-len ''значение''</tt>  — проверка длины всего подзаголовка.
 
Следующие три параметра работают для типа 0 (<tt>--rt-type 0</tt>):
 
<tt>--rt-0-res</tt>  — проверять зарезервированные поля;
 
<tt>--rt-0-addrs ''адрес''[,''адрес''...]</tt>  — проверяет адреса, перечисленные в подзаголовке. Можно указать не&nbsp; более 16 адресов, разделяя их запятыми. Пакет считается удовлетворяющим критерию, если подзаголовок содержит все адреса, которые были перечислены в правиле, в том же порядке;
 
<tt>--rt-0-not-strict</tt>  — делает условие проверки по предыдущем параметру не&nbsp; таким жестким: достаточно, чтобы хотя бы один из перечисленных адресов совпадал с соответствующим адресом в подзаголовке, при соблюдении порядка перечисления.
 
===== {{w |ICMPv6}} =====
ICMPv6 является протоколом контрольных сообщений IPv6. Несмотря на то, что ICMPv6 формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv6, и поэтому соответствующий критерий может использоваться только в ip6tables, но не в iptables.
 
ICMPv6 является протоколом контрольных сообщений IPv6. Несмотря на то, что ICMPv6 формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (<tt>-p</tt>), а не&nbsp;для вспомогательного критерия (<tt>-m</tt>), де-факто этот протокол неотделим от IPv6, и поэтому соответствующий критерий может использоваться только в ip6tables, но не&nbsp;в iptables.
 
Критерий этого протокола имеет единственный параметр
Строка 1121 ⟶ 1077 :
 
===== [[MH]] =====
 
Критерий mh позволяет определять пакеты с подзаголовком IPv6 Mobility Header (RFC 3775). Как и в случае с ICMPv6, вызов данного критерия должен выполняться в соответствии с синтаксисом для протокола (через ключ <tt>-p</tt>). Имеет единственную опцию
 
Строка 1134 ⟶ 1089 :
 
==== {{w |IPsec}} ====
netfilter «знает» два протокола из семейства IPsec: [[:en:IPSec#Authentication Header|Authentication Header]] (<tt>-p ah</tt>) и [[:en:IPSec#Encapsulating Security Payload|Encapsulating Security Payload]] (<tt>-p esp</tt>).
 
netfilter «знает» два протокола из семейства IPsec: [[:en:IPSec#Authentication_Header|Authentication Header]] (<tt>-p ah</tt>) и [[:en:IPSec#Encapsulating_Security_Payload|Encapsulating Security Payload]] (<tt>-p esp</tt>).
 
===== AH =====
Для протокола AH поддерживается единственная опция
* <tt>'''--ahspi''' ''значение''[:''значение'']</tt>  — позволяет указать значение (или диапазон значений) [[:en:Security_Parameter_IndexSecurity Parameter Index|SPI (Security Parameter Index)]].
 
===== ESP =====
Строка 1154 ⟶ 1108 :
 
==== conntrack ====
Основной критерий, используемый для контроля состояния соединения. Он предоставляет эффективный набор инструментов, позволяющий использовать информацию системы [[conntrack]] о состоянии соединения. Затронутую тему весьма проблематично осветить в двух словах и привести по ней простые примеры, не выходя за краткий формат, принятый для нашей статьи. Поэтому ограничимся мы подробно рассмотрим лишь наиболее важный параметр данного критерия — ctstate. Для прочих параметров мы лишь кратко опишем синтаксис и назначение. За более подробной информацией обратитесь к документации, прилагаемой к вашему дистрибутиву. Итак,
 
Основной критерий, используемый для контроля состояния соединения. Он предоставляет эффективный набор инструментов, позволяющий использовать информацию системы [[conntrack]] о состоянии соединения. Затронутую тему весьма проблематично осветить в двух словах и привести по ней простые примеры, не выходя за краткий формат, принятый для нашей статьи. Поэтому ограничимся мы подробно рассмотрим лишь наиболее важный параметр данного критерия — ctstate. Для прочих параметров мы лишь кратко опишем синтаксис и назначение. За более подробной информацией обратитесь к документации, прилагаемой к вашему дистрибутиву. Итак,
 
* <tt>[!] '''--ctstate''' ''маска''</tt>
Строка 1163 ⟶ 1116 :
Возможные состояния:
 
:* '''NEW'''  — соединение не открыто, то есть пакет является первым в соединении. Полезные примеры использования этого состояния приведены выше, в частности, при описании [[#TCP|TCP-специфичных критериев]].
 
:* '''ESTABLISHED'''  — пакет относится к уже установленному соединению. Обычно такие пакеты принимаются без дополнительной фильтрации, как и в случае с RELATED.
 
:* '''RELATED'''  — пакет открывает новое соединение, логически связанное с уже установленными, например, открытие канала данных в пассивном режиме {{w |FTP}}.
Например:
<source lang="bash">
Строка 1185 ⟶ 1138 :
С обработкой активного режима таких проблем не возникает, так как сервер сам устанавливает соединение данных с порта 20, поэтому первый пакет пропускается согласно правилу по умолчанию цепочки OUTPUT. Правда, проблемы могут возникнуть на стороне фаервола клиента, но это уже не относится к компетенции сервера.
 
:* '''INVALID'''  — пакет по смыслу должен принадлежать уже установленному соединению (например, ICMP-сообщение port-unreachable), однако такое соединение в системе не зарегистрировано. Обычно к таким пакетам применяют действие DROP:
<source lang="bash">
iptables -I INPUT -m conntrack --ctstate INVALID -j DROP
</source>
 
:* '''UNTRACKED'''  — отслеживание состояния соединения для данного пакета было отключено. Обычно оно отключается с помощью действия NOTRACK в таблице raw.
 
:* '''DNAT'''  — показывает, что к данному соединению применена операция подмены адреса назначения (об операциях преобразования адресов см. [[#Таблица nat|выше]]).
 
:* '''SNAT'''  — показывает, что к данному соединению применена операция подмены адреса источника (об операциях преобразования адресов см. [[#Таблица nat|выше]]).
 
Остальные параметры критерия conntrack, как уже говорилось, мы опишем лишь конспективно.
Строка 1201 ⟶ 1154 :
 
Применяется для определения статуса соединения в системе conntrack. Возможные статусы:
:* '''EXPECTED'''  — данное соединение ожидалось системой conntrack по результатам анализа других соединений. Например, после того, как клиент и сервер через управляющее {{w |FTP}}-соединение согласуют номер порта для соединения данных в пассивном режиме, система [[conntrack]] на сервере будет ожидать входящее соединение на этот порт.
:* '''CONFIRMED'''  — подтвержденное соединение. Такой статус присваивается соединению после того, как инициатор начал передачу пакетов.
:* '''SEEN_REPLY'''  — соединение, по которому поступил ответ, то есть имеет место передача данных в обоих направлениях (поддержка данного состояния появилась сравнительно недавно).
:* '''ASSURED'''  — соединение можно считать полностью установленным. Этот статус присваивается соединению после передачи определенного количества данных. Присвоение данного статуса приводит к увеличению conntrack-тайм-аута для данного соединения (эти тайм-ауты используются для определения и удаления «повисших» и оборванных соединений).
:* '''NONE'''  — нет статуса. Соединение не соответствует ни одному из перечисленных критериев.
 
* <tt>[!] '''--ctproto''' ''протокол''</tt>
 
Протокол [[w:Транспортный уровень |транспортного уровня]], определенный системой conntrack. Синтаксис аналогичен стандартному критерию <tt>-p</tt>.
 
* <tt>[!] '''--ctdir''' {ORIGINAL|REPLY}</tt>
 
Позволяет указать направление прохождения пакетов (ORIGINAL  — от инициатора к отвечающему, REPLY  — наоборот). Если не указывать эту опцию, под критерий будут подпадать пакеты, идущие в обоих направлениях.
 
* <tt>[!] '''--ctorigsrc''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctorigdst''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctreplsrc''' ''адрес''[/''маска'']</tt>, <tt>[!] '''--ctrepldst''' ''адрес''[/''маска'']</tt>
Строка 1221 ⟶ 1174 :
Обычно адрес-порт источника при передаче в прямом направлении совпадают с адресом-портом назначения при передаче в обратном направлении, и наоборот, адрес-порт источника при передаче в обратном направлении совпадает с адресом-портом назначения при передаче в прямом направлении. То есть, если клиент 192.168.1.2 обращается к серверу 192.168.1.1, то с точки зрения системы conntrack ситуация выглядит следующим образом:
: → В прямом направлении (от инициатора к отвечающему):
::  — Адрес источника (ctorigsrc): 192.168.1.2 (адрес клиента)
::  — Адрес назначения (ctorigdst): 192.168.1.1 (адрес сервера)
: ← В обратном направлении (от отвечающего к инициатору):
::  — Адрес источника (ctreplsrc): 192.168.1.1 (адрес сервера)
::  — Адрес назначения (ctrepldst): 192.168.1.2 (адрес клиента)
 
Однако для соединений, к которым применена трансляция адресов или портов, это может не выполняться. Например, рассмотрим ситуацию, когда клиент из нашей подсети (192.168.1.2) обращается к некоторому серверу в интернете (204.152.191.37) через наш сервер (внешний адрес нашего сервера 208.77.188.166, внутренний 192.168.1.1). Для корректной работы такой схемы нужно обеспечить на нашем сервере подмену исходного адреса (SNAT), например,
Строка 1233 ⟶ 1186 :
Тогда, с точки зрения системы conntrack нашего сервера,
: → В прямом направлении (от инициатора к отвечающему):
::  — Адрес источника (ctorigsrc): 192.168.1.2 (внутренний адрес клиента)
::  — Адрес назначения (ctorigdst): 204.152.191.37 (адрес интернет-сервера)
: ← В обратном направлении (от отвечающего к инициатору):
::  — Адрес источника (ctreplsrc): 204.152.191.37 (адрес интернет-севера)
::  — Адрес назначения (ctrepldst): 208.77.188.166 (внешний адрес нашего сервера)
 
В том случае, если адрес-порт источника при передаче в прямом направлении отличаются от адреса-порта назначения при передаче в обратном направлении, соединению будет присвоен статус SNAT.
Строка 1247 ⟶ 1200 :
то при обращении на этот адрес клиента извне (допустим, все тот же 204.152.191.37), получим
: → В прямом направлении (от инициатора к отвечающему):
::  — Адрес источника (ctorigsrc): 204.152.191.37 (адрес клиента)
::  — Адрес назначения (ctorigdst): 208.77.188.166 (наш внешний адрес)
: ← В обратном направлении (от отвечающего к инициатору):
::  — Адрес источника (ctreplsrc): 192.168.1.2 (адрес внутреннего сервера)
::  — Адрес назначения (ctrepldst): 204.152.191.37 (адрес клиента)
 
В том случае, если адрес-порт назначения при передаче в прямом направлении отличаются от адреса-порта источника при передаче в обратном направлении, соединению будет присвоен статус DNAT.
Строка 1270 ⟶ 1223 :
 
==== state ====
 
Идеологический предшественник критерия conntrack. Имеет единственный параметр <tt>--state</tt>, аналогичный параметру <tt>--ctstate</tt> критерия conntrack (но, в отличие от него, не поддерживающий состояния DNAT и SNAT).
 
Строка 1276 ⟶ 1228 :
 
=== Дополнительные критерии ===
Дополнительные критерии iptables подгружаются при помощи параметра <tt>-m</tt> (<tt>--match</tt>). Далее можно указать дополнительные параметры, специфичные для данного конкретного критерия. Если дополнительных критериев несколько, не смешивайте их параметры — указывайте нужные параметры каждого критерия непосредственно после его вызова через <tt>-m</tt>.
 
Дополнительные критерии iptables подгружаются при помощи параметра <tt>-m</tt> (<tt>--match</tt>). Далее можно указать дополнительные параметры, специфичные для данного конкретного критерия. Если дополнительных критериев несколько, не смешивайте их параметры — указывайте нужные параметры каждого критерия непосредственно после его вызова через <tt>-m</tt>.
 
Перед некоторыми дополнительными параметрами критерия может стоять восклицательный знак. В соответствии с принятыми в iptables соглашениями, это означает логическую инверсию параметра, то есть его смысл меняется на противоположный. Но такая возможность предусмотрена отнюдь не для всех параметров.
Строка 1289 ⟶ 1240 :
 
==== Вспомогательные критерии ====
 
К этой группе можно отнести критерии, расширяющие возможности других критериев.
 
* '''multiport'''  — позволяет указать несколько (до 15) портов и/или их диапазонов (для протоколов {{w |TCP}}, {{w |UDP}}, {{w |SCTP}}, {{w |DCCP}} и {{w |UDP Lite}}). Поддерживает следующие параметры
 
<tt>[!] --sports</tt>, <tt>--source-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt>  — улучшенная версия критерия <tt>--sport</tt>, описанного выше. Позволяет перечислить (без пробелов, через запятую) до 15 портов или их диапазонов.
 
<tt>[!] --dports</tt>, <tt>--destination-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt>  — улучшенная версия критерия <tt>--dport</tt>, описанного выше. Например,
<source lang="bash">
iptables -I INPUT -p tcp -m multiport --dport 80,8000:8008 -j ACCEPT
Строка 1302 ⟶ 1252 :
позволит принимать TCP-пакеты, приходящие на порты 80 и с 8000 по 8008.
 
<tt>[!] --ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]</tt>  — пакет будет подпадать под этот критерий, если его исходный порт ''или'' порт назначения присутствует в указанном списке.
 
* '''iprange'''  — позволяет указать диапазон {{w |IP-адрес}}ов, не являющийся подсетью. Поддерживает следующие параметры:
 
<tt>[!] --src-range ''адрес''[-''адрес'']</tt>  — позволяет указать диапазон исходных адресов. Например,
<source lang="bash">
iptables -I INPUT -m iprange --src-range 192.168.0.8-192.168.0.25 -j DROP
Строка 1312 ⟶ 1262 :
заблокирует все пакеты, исходный адрес которых лежит в диапазоне с 192.168.0.8 по 192.168.0.25 включительно.
 
<tt>[!] --dst-range ''адрес''[-''адрес'']</tt>  — позволяет указать диапазон адресов назначения.
 
==== Критерии маркировки ====
* '''mark''' — позволяет выделять пакеты с заданной маркировкой (nfmark). Имеет единственную опцию
 
<tt>[!] --mark ''значение''[/''маска'']</tt> — указывает значение маркировки. Простейший пример:
* '''mark''' — позволяет выделять пакеты с заданной маркировкой (nfmark). Имеет единственную опцию
 
<tt>[!] --mark ''значение''[/''маска'']</tt> — указывает значение маркировки. Простейший пример:
<source lang="bash">
-m mark --mark 15
Строка 1324 ⟶ 1273 :
будет выделять пакеты с маркировкой 15.
 
Если указана маска, то перед сравнением с заданным значением маркировка каждого пакета комбинируется с этой маской посредством логической операции [[w:Конъюнкция |AND]], то есть проверяется условие <tt>x & ''маска'' == ''значение''</tt> (где x  — маркировка текущего пакета). Такой подход позволит сравнивать значения отдельных {{w |бит}}. Например, критерию
<source lang="bash">
-m mark --mark 64/64
</source>
будет отлавливать пакеты, в маркировке которых установлен 7-й бит (<math>2^6=64</math>, при этом первый бит соответствует <math>2^0</math>). В частности, 64…127, 192…255, 320…383 и  т.  д.
 
Еще один пример —
Строка 1334 ⟶ 1283 :
-m mark --mark 2/3
</source>
будет определять пакеты, в маркировке которых установлен второй бит, но снят первый. Такие числа будут нацело делиться на два, но не делиться на четыре  — 2, 6, 10, 14, …
 
* '''connmark'''  — полностью аналогичен mark, но проверяет не маркировку пакета (nfmark), а маркировку соединения (ctmark). Также имеет параметр <tt>--mark</tt> с аналогичным синтаксисом.
 
В качестве практического примера использования меток пакетов и соединений рассмотрим улучшение работы {{w |l7-filter}}-userspace.
 
Userspace-вариант {{w |l7-filter}} является [[w:Демон (программа) |демоном]], взаимодействующим с {{w |netfilter}} через подсистему nfnetlink_queue  — действие NFQUEUE в терминологии iptables. При помощи этого действия определенные пакеты можно направить на анализ демону l7-filter. По результатам анализа демон выставит маркировку пакетов: 1  — пакет принадлежит новому соединению, тип которого пока не идентифицирован; 2  — пакет принадлежит соединению, тип которого идентифицировать так и не удалось. Другие значения соответствуют установленным типам соединений (соответствие задается в конфигурационном файле демона) [http://l7-filter.sourceforge.net/HOWTO-userspace#Does].
 
Задача l7-filter  — определить тип протокола [[w:Протоколы прикладного уровня |прикладного уровня]] (см. {{w |модель OSI}}) для данного пакета/соединения. Решается эта задача путем анализа содержимого пакета с применением [[Регулярные выражения|регулярных выражений]], позволяющих определить типовые лексемы, характерные для различных протоколов (например, «<tt>220 ftp server ready</tt>» для {{w |FTP}} или «<tt>HTTP/1.1 200 OK</tt>» для {{w |HTTP}}). Пакет, в котором встречаются такие лексемы, может быть однозначно классифицирован. В принципе, это дает достаточное основание классифицировать соединение в целом. Однако, в этом поведение kernel и userspace версий l7-filter существенно различается.
 
Как описывается в [http://l7-filter.sourceforge.net/technicaldetails документации], версия l7-filter-kernel ''хранит'' данные о соединениях и ''использует'' их для классификации пакетов, принадлежащих к соединениям, тип которых уже установлен. В то же время, аналогичное утверждение в отношении l7-filter-userspace в документации отсутствует. И, как показывает практика, userspace-версия ''не&nbsp; использует'' информацию о соединениях. Возможно, это обусловлено техническими ограничениями nfnetlink_queue как средства взаимодействия l7-filter с системой netfilter.
 
Описанный недостаток значительно снижает эффективность l7-filter  — ведь однозначно классифицированы могут быть всего несколько пакетов из каждого соединения, а всего в соединении могут быть миллионы и миллиарды пакетов. Соответственно, применение l7-filter по своему основному назначению  — классификация трафика для последующего [[w:Шейпинг (информатика) |шейпинга]]  — не оправдывает себя.
 
Итак, рассмотрим, как, используя возможности netfilter, можно исправить этот недостаток.
Строка 1352 ⟶ 1301 :
Идея решения проста: после обработки пакетов демоном l7-filter, нужно добавить операции по переносу маркировки пакета на соединение (чтобы классифицировать соединение в целом) и с соединения на пакеты (чтобы пометить уже ''все'' пакеты в соединении для дальнейшей обработки шейпером, так как шейпер воспринимает только метки пакетов). Таким образом, классификация одного пакета в соединении влечет классификацию всех последующих пакетов.
 
Для начала, запустим демон l7-filter-userspace. Небольшое замечание: в его конфигурационном файле (назовем его, например, <tt>l7-filter.conf</tt>) будем помечать протоколы метками в диапазоне от 16 до 31 включительно (почему  — станет понятно из дальнейших пояснений).
<source lang="bash">
l7-filter -f /etc/l7-filter.conf -q 2 -m 0x1f
</source>
Параметр <tt>-f</tt> указывает путь к конфигурационному файлу, <tt>-q</tt>  — номер очереди, <tt>-m</tt>  — задает биты маркировки, модифицируемые демоном l7-filter (в нашем случае  — с первого по пятый, что соответствует диапазону значений маркировки от 0 до 31).
 
Далее, добавим правила, направляющие весь входящий и исходящий трафик (кроме локального) на анализ демону l7-filter:
Строка 1366 ⟶ 1315 :
iptables -t mangle -A OUTPUT ! -o lo -j NFQUEUE --queue-num 2
</source>
Добавлять второе из этих правил в цепочку POSTROUTING не стоило  — ведь в нее попадает как трафик, исходящий от самого хоста, так и транзитный трафик, который уже был обработан ранее, в цепочке PREROUTING. Посмотрев на диаграмму выше, вы можете убедиться, что приведенные правила обрабатывают весь трафик, как принадлежащий самому хосту, так и транзитный, за исключением локального. Локальный трафик (идущий через интерфейс [[w:Loopback |lo]]), бессмысленно шейпить, а значит, не стоит и классифицировать.
 
Теперь добавим правила, обеспечивающие копирование маркировки пакетов в маркировку соединений и обратно:
Строка 1379 ⟶ 1328 :
iptables -t mangle -A POSTROUTING -m connmark --mark 0x10/0xfffffff0 -j CONNMARK --restore-mark
</source>
Поясним два момента. Во-первых, добавление этих правил в цепочки PREROUTING и OUTPUT, сразу после правил, передающих трафик демону l7-filter, не имеет смысла  — после обработки пакетов демон [http://l7-filter.sourceforge.net/HOWTO-userspace#Does применяет] к ним действие ACCEPT, прекращающее обработку пакета в рамках исходных цепочек. Поэтому мы добавляем эти правила в цепочки, идущие «ниже по течению». Как вы можете заметить по диаграмме выше, такая комбинация правил также обеспечивает обработку всего трафика.
 
Второй момент, который стоит пояснить  — маски специального вида. По сути, они позволяют проверить, лежит ли маркировка пакета в диапазоне от 16 до 31. Такая защита позволяет избежать обработки маркировок 0 (такую маркировку имеет локальный трафик, так как он не проходит процедуру анализа), 1 и 2 (эти значения маркировки, как уже было замечено выше, означают, что тип пакета не определен), а также 32 и выше (эти значения мы оставляем для других задач).
 
Как показывает [http://www.linux.org.ru/jump-message.jsp?msgid=3790164&cid=3791754 практика], даже в самом примитивном случае (детекция протокола {{w |HTTP}}, сервер  — {{w |nginx}} 0.6.32, клиент  — [http://www.hping.org/wbox/ wbox] 4), эффективность детекции возрастает  — без использования маркировки соединений регистрируются лишь 2 исходящих пакета (l7-filter работает на сервере), с использованием  — 3 исходящих и 2 входящих. Детальное исследование показывает, что детекции избегают лишь первые четыре пакета в соединении  — 2 SYN-пакета и 2 пакета с данными. Это цифры, характерные для тестовой задачи  — при передаче больших объемов данных количество детектированных пакетов будет значительно больше, в то время как количество не определенных пакетов сохранит тот же порядок.
 
Более того, предложенный метод решает задачу, не решенную даже в реализации l7-filter-kernel  — маркировка связанных соединений. Согласно документации iptables, маркировка соединений автоматически копируется с исходных соединений на связанные с ними (например, с управляющего {{w |FTP}}-соединения на соединение данных).
 
: ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → statistic)''.
 
В качестве практического примера использования меток пакетов и соединений можно рассмотреть задачу [[w:Случайная величина |стохастической]] балансировки соединений между несколькими [[аплинк]]ами.
Допустим, у нас есть три провайдера, подключенных к интерфейсам eth0, eth1 и eth2 (это могут быть и {{w |VLAN}}-порты одного интерфейса, суть от этого не меняется, только названия), и их шлюзы имеются соответственно {{w |IP-адрес}}а 208.77.188.1, 208.77.189.1, 208.77.190.1.
 
Строка 1402 ⟶ 1351 :
112 prov2
113 prov3
устанавливающие соответствие между внутренними номерами таблиц маршрутизации и их символьными именами. Используемые здесь имена prov1, prov2 и prov3, разумеется, условны. Таблица static  — особая, ее мы рассмотрим чуть ниже.
 
Обратите внимание, что это действие выполняется только один раз  — не надо повторять его при каждой загрузке системы!
 
Далее, сделаем каждого провайдера шлюзом по умолчанию в «своей» таблице:
Строка 1422 ⟶ 1371 :
</source>
 
Таблица static предназначена для обслуживания статических маршрутов. В частности, в нее мы занесем подсети провайдеров (предположим, что все они [[w:Бесклассовая адресация |класса 1C]]), а также наши внутренние локальные сети (если таковые есть):
<source lang="bash">
# Провайдеры
Строка 1434 ⟶ 1383 :
ip route flush cache
</source>
Таким образом, если нашему хосту нужно будет обратиться в подсеть провайдера prov2 (208.77.189.0/24), то маршрут пойдет сразу через интерфейс eth1. Также в этой таблице присутствуют маршруты для наших внутренних локальных сетей  — с ними тоже все просто.
 
По сути дела, таблица static обычно содержит те же маршруты, что и таблица main (главная таблица маршрутизации), за исключением маршрута по умолчанию  — таких маршрутов у нас несколько и каждый из них размещается в отдельной таблице, выбор между которыми осуществляется на основании назначенной iptables/netfilter маркировки.
 
Заметим, что ни в таблицу static, ни в какие-либо другие таблицы не&nbsp; нужно вносить {{w |loopback}}-маршруты, например «127.0.0.1/8 dev lo», так как все эти маршруты фигурируют в автоматически создаваемой таблице local, которую любой пакет проходит в первую очередь (нетрудно убедиться в этом, посмотрев вывод команды «ip rule show»).
 
Далее, отключим статическую антиспуфинговую фильтрацию:
Строка 1444 ⟶ 1393 :
sysctl net.ipv4.conf.all.rp_filter=0
</source>
Reverse path filtering  — штука, конечно, удобная и полезная но, к сожалению, совершенно не совместимая с динамической маршрутизацией.
 
Если вы планируете использовать этот компьютер не&nbsp; только как [[w:Сетевой шлюз |шлюз]], и но и как интернет-{{w |сервер}} (то есть предоставлять доступ к нему извне), необходимо выполнить привязку входящих соединений к их интерфейсам&nbsp; — в противном случае могут возникнуть проблемы, если обращение извне придет через одного провайдера, а сервер ответит через другого.
<source lang="bash">
iptables -t mangle -N bind_connect # Создаем отдельную цепочку (для простоты управления)
Строка 1456 ⟶ 1405 :
iptables -t mangle -I INPUT -m conntrack --ctstate NEW -j bind_connect
</source>
Теперь, в сочетании с операцией <tt>-j CONNMARK --restore-mark</tt>, которой мы подвергнем исходящий с нашего сервера трафик (см. ниже), эта процедура обеспечит корректную обработку входящих соединений. (Отметим, что, если бы нам не нужно было бы балансировать исходящие соединения, мы могли бы обойтись вообще без помощи iptables/netfilter, выполнив привязку входящих соединений через правила вида <tt>ip rule add from 208.77.188.100 table prov1</tt> и  т. п.  — ответные пакеты всегда уходят с того же адреса, на который пришел запрос, так что в качестве критерия для выбора шлюза можно использовать исходный адрес.)
 
Ввиду того, что выбор исходящего адреса для каждого нового соединения осуществляется на основании правил статической маршрутизации (таблица main), могут возникнуть ошибки. Например, если в маршруте по умолчанию (default) в таблице main указан интерфейс eth0, то все исходящие от нас во внешнюю сеть (интернет) соединения будут иметь в качестве исходного адреса первый адрес интерфейса eth0, и ответные пакеты пойдут именно на этот интерфейс. Чтобы избежать возникновения таких ситуаций, добавим {{w |маскарадинг}} для всех исходящих соединений (предполагается, что у всех провайдеров наши внешние адреса имеют вид 208.77.x.100):
Строка 1465 ⟶ 1414 :
</source>
 
А теперь  — самое интересное. Используя описанный ниже критерий statistic, мы будем случайно распределять метки между пакетами.
<source lang="bash">
iptables -t mangle -N select_prov # Создаем для этого специальную цепочку
Строка 1474 ⟶ 1423 :
iptables -t mangle -A select_prov -j CONNMARK --set-mark 3 # Всем, кто дошел досюда, ставим маркировку 3
</source>
Первое правило в этой цепочке пройдут все пакеты, вошедшие в нее. После этого, 34  % (примерно треть из них) покинет цепочку согласно второму правилу. Далее, оставшиеся пакеты (66  % от первоначального количества) получат маркировку 2. После этого половина из них (то есть 33  % от начального) покинут цепочку с этой маркировкой. Оставшаяся половина (тоже 33  % от начального количества) получат маркировку 3.
 
После этого, создадим вспомогательную цепочку, осуществляющую маркировку соединений и пакетов:
Строка 1486 ⟶ 1435 :
iptables -t mangle -A sort_connect -j CONNMARK --restore-mark # Копируем маркировку соединений на пакеты
</source>
Через цепочку <tt>select_prov</tt> мы прогоняем только новые пакеты, то есть первые пакеты каждого соединения. После этой процедуры соединение уже имеет маркировку. К сожалению, на данный момент роутинговая подсистема ядра [[w:Ядро Linux |Linux]] не умеет маршрутизировать пакеты на основании маркировки соединения  — только на основании маркировки пакетов. Поэтому действием <tt>CONNMARK --restore-mark</tt> мы копируем маркировку соединений в маркировку пакетов.
 
Осталось только добавить вызов этой цепочки в таблицу mangle:
Строка 1499 ⟶ 1448 :
</source>
 
Разумеется, при этом должна быть разрешена передача транзитного трафика, как в таблице filter, так и на уровне sysctl. Как это делается  — см. выше.
 
Заметим, что кроме алгоритма случайной балансировки, критерий statistic позволяет реализовать балансировку в режим [[w:Round-robin (алгоритм) |round robin]]. Для этого поменяем цепочку <tt>select_prov</tt> следующим образом:
<source lang="bash">
iptables -t mangle -F select_prov # Очищаем ее
Строка 1517 ⟶ 1466 :
ip route add default scope global nexthop via 208.77.188.1 dev eth0 weight 1 nexthop via 208.77.189.1 dev eth1 weight 1 # И т.д.
</source>
Стоит обратить особое внимание на тот факт, что данный метод балансирует ''пакеты'', а не соединения. Например, в том случае, если вы хотите организовать выход в интернет из локальной сети через нескольких провайдеров, не имея единого внешнего адреса, этот метод может работать некорректно  — часть пакетов пройдет через одного провайдера и после операции {{w |NAT}} получит один исходный адрес, часть пойдет через другого и соответственно получит другой адрес, и в результате удаленные хосты не смогут правильно обрабатывать соединения, исходящие из вашей сети. Однако, в большинстве случаев этот негативный эффект нивелируется другим фактором  — кэшированием маршрутов. При прохождении через такое правило серии пакетов, адресованных некоторому хосту, действительно случайным выбор будет только для первого из них, после чего выбранный маршрут будет закэширован, и остальные пакеты к этому хосту будут маршрутизироваться через тот же шлюз. С одной стороны, подобный эффект позволяет соединениям корректно функционировать, с другой стороны  — балансировка оказывается не такой уж и случайной. К тому же, после очистки кэша маршрутов (например, посредством ввода команды <tt>ip route flush cached</tt>), работа существующих на этот момент соединений может быть нарушена. В качестве наиболее безопасного и целесообразного применения описанного метода можно привести задачу балансировки транзитного трафика в сетях без NAT (условия «прямой видимости» между балансирующим маршрутизатором и точкой схождения потоков трафика). В том случае, если доступ к шлюзам осуществляется через один сетевой интерфейс, этим методом можно балансировать и соединения, исходящие от самого хоста.
 
Также заметим, что описанные в этом примере методы балансировки не учитывают загруженность каналов. Для этого рекомендуется использовать критерий rateest и действие RATEEST совместно с уже знакомым нам CONNMARK.
 
==== Лимитирующие критерии ====
 
К этой группе относятся критерии, позволяющие ограничивать количество пакетов, соединений, и переданных байт.
 
* '''limit'''  — позволяет ограничить количество пакетов в единицу времени. Параметры:
 
<tt>--limit ''количество''[/second|/minute|/hour|/day]</tt>  — задает ограничение на количество пакетов в секунду (second), минуту (minute), час (hour) или сутки (day). Пакеты в пределах этого количества считаются удовлетворяющими критерию, сверх этого количества  — не удовлетворяющими.
 
<tt>--limit-burst ''количество''</tt>  — задает длину очереди, то есть максимальную пропускную способность.
 
Критерий -limit использует модель «дырявого ведра», и --limit-burst задает «объем ведра», а --limit  — «скорость вытекания». Каждому такому критерию соответствует своя очередь, длина которой задается параметром --limit-burst. Если в очереди есть пакеты, то со скоростью, заданной в --limit, они покидают очередь и считаются удовлетворяющими критерию. Если же вся очередь занята, то новые пакеты в ней не регистрируются и считаются ''не'' удовлетворяющими критерию.
Например,
<source lang="bash">
Строка 1538 ⟶ 1486 :
предполагает очередь на пять пакетов, которая «продвигается» со скоростью 3 пакета в минуту. При непрерывном поступлении входящих пакетов, очередь всегда будет заполнена, и в лог будут заноситься в среднем по три пакета в минуту. Однако, если входящих пакетов долго не будет, то очередь успеет очиститься, и при поступлении пяти и менее новых пакетов, они пойдут в лог подряд. В любом случае, скорость попадания пакетов в лог остается неизменной.
 
Типичная ошибка новичков  — использовать limit для ограничения TCP-трафика, например, так:
<source lang="bash">
iptables -A INPUT -p tcp --dport 80 -m limit --limit 10000/sec --limit-burst 10000 -j ACCEPT
iptables -P INPUT DROP
</source>
Это пример попытки защитить {{w |web-сервер}} от [[w:DoS-атака |DDoS-атаки]], ограничив количество пакетов в единицу времени. Однако, это правило не помешает без особого труда завалить сервер запросами (считая, что на один запрос требуется два входящих пакета  — SYN-пакет и пакеты данных, содержащий, например, только GET /, согласно спецификации HTTP 0.9). При этом могут возникнуть помехи для легальных пользователей, например, загружающих на сервер большой файл методом POST. Более корректным решением будет ограничивать не скорость входящего потока данных, а скорость открытия новых соединений:
<source lang="bash">
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Строка 1551 ⟶ 1499 :
Теперь мы ограничиваем количество не всех пакетов, а только новых, то есть мы разрешаем открывать не более 32 новых соединений в секунду. Впрочем, число 32 приведено здесь только для примера. Конкретное значение скорости для вашей задачи рекомендуем определять самостоятельно.
 
* '''hashlimit'''  — позволяет применять ограничения, аналогичные критерию limit, к группам хостов, подсетей или портов, используя всего одно правило. При этом для каждого хоста, подсети или порта создается отдельная очередь. Можно задвать, например, такие критерии:
 
«1000 пакетов в секунду с каждого хоста из подсети 192.168.0.0/16»
Строка 1572 ⟶ 1520 :
Рассмотрим основные параметры этого критерия более подробно:
 
<tt>--hashlimit-mode {srcip|srcport|dstip|dstport}[,...]</tt>  — задает список контролируемых параметров: адреса (ip) и порты (port) источника (src) и назначения (dst). Например, если указать параметр
<source lang="bash">
--hashlimit-mode srcip,dstip
</source>
то будет создаваться отдельная очередь для каждой пары «адрес источника  — адрес назначения», то есть ограничение будет вводиться на количество пакетов, передаваемых с каждого хоста на другой хост (разумеется, если эти пакеты идут через наш сервер). Или, например,
<source lang="bash">
--hashlimit-mode srcip,srcport
Строка 1582 ⟶ 1530 :
будет создавать отдельную очередь для каждого исходного порта каждого хоста.
 
<tt>--hashlimit-upto ''количество''[/second|/minute|/hour|/day]</tt>  — этот параметр задает скорость движения очереди (аналог <tt>--limit</tt>). Если пакеты поступают с такой же или меньшей скоростью, они считаются подпадающими под критерий. Обратите внимание, что этот параметр ''не'' поддерживает логической инверсии (отрицания) через восклицательный знак (см. ниже).
 
<tt>--hashlimit-above ''количество''[/second|/minute|/hour|/day]</tt>  — этот параметр таке задает скорость движения очереди, но смысл его противоположный  — если пакеты поступают с ''большей'' скоростью, они считаются подпадающими под критерий.
 
<tt>--hashlimit-burst ''количество''</tt>  — задает длину каждой очереди. Аналогичен <tt>--limit-burst</tt>.
 
<tt>--hashlimit-srcmask ''префикс''</tt>  — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим srcip. Как уже говорилось выше,
<source lang="bash">
-m hashlimit --hashlimit-mode srcip --hashlimit-srcmask 28
Строка 1595 ⟶ 1543 :
По умолчанию 32 (своя очередь для каждого отдельного хоста). Если указать 0, то контроль по параметру srcip теряет смысл.
 
<tt>--hashlimit-dstmask ''префикс''</tt>  — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим dstip. Принцип использования аналогичен hashlimit-srcmask.
 
<tt>--hashlimit-name ''имя''</tt>  — позволяет использовать несколько независимых таблиц очередей (hashes), распознаваемых по имени. Обязательный параметр. Например,
<source lang="bash">
iptables -F INPUT # Очищаем цепочку INPUT
Строка 1621 ⟶ 1569 :
Доступ к таблицам очередей возможен через procfs (файл <tt>/proc/net/ipt_hashlimit/имя_таблицы</tt>). Подробнее о формате этого файла можно почитать [http://www.opennet.ru/base/net/iptables_tbf.txt.html здесь], однако учтите, что большая часть сведений, приведенных в указанной статье, устарела.
 
Критерий haslimit также имеет ряд параметров, не описанных здесь (максимальный размер таблицы, время жизни записи в таблице, интервал [[w:Сборка мусора (программирование) |«сбора мусора»]], и  т.  п.). За подробными сведениями обратитесь к документации.
 
* '''connlimit'''  — позволяет ограничивать количество одновременно открытых соединений с каждого IP-адреса (или подсети). Параметры:
 
<tt>[!] --connlimit-above количество</tt>  — минимальное количество соединений. Все пакеты, проходящие по соединениям, установленным сверх заданного количества, считаются удовлетворяющими критерию. Например,
<source lang="bash">
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 3 -j DROP
Строка 1636 ⟶ 1584 :
</source>
 
<tt>--connlimit-mask</tt>  — маска подсети, для которой устанавливается общее ограничение на количество соединений. Например,
<source lang="bash">
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 5 --connlimit-mask 24 -j DROP
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
</source>
разрешит не более пяти одновременных соединений на порт 80 с каждой подсети [[w:Бесклассовая адресация |класса 1C]].
 
Не надо путать connlimit с hashlimit  — hashlimit позволяет ограничить ''скорость'' поступления пакетов с хостов или подсетей (в сочетании с <tt>-m conntrack --ctstate NEW</tt>  — скорость открытия новых соединений), а connlimit  — ''количество'' одновременно открытых соединений.
 
* '''connbytes'''  — позволяет ограничивать количество переданных байт или пакетов. Параметры:
 
<tt>[!] --connbytes ''мин'':[''макс'']</tt>  — собственно задает количество пакет или байт. Можно указать просто минимальное количество или диапазон.
 
<tt>--connbytes-dir {original|reply|both}</tt>  — задает направление движения пакетов. Проверяются только пакеты, движущиеся от инициатора соединения к отвечающему (original), наоборот (reply) или в обоих направлениях (both).
 
<tt>--connbytes-mode {packets|bytes|avgpkt}</tt>  — задает собственно учитываемую величину: количество пакетов (packets), количество байт (bytes) или средний размер пакета (avgpkt).
 
Пример:
Строка 1662 ⟶ 1610 :
iptables -t mangle -I OUTPUT -m connbytes ! --connbytes 51200: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Minimize-Delay
</source>
Таким образом, все пакеты, принадлежащие «легким» соединениям, будут маркироваться как наиболее приоритетные, а пакеты, проходящие по «тяжеловесным» соединениям  — как наименее приоритетные. Такой подход позволит рационально распределять канал между различными задачами, например, просмотром веб-страниц («легкие» соединения) и скачиванием файлов («тяжелые» соединения).
 
Конечно, при таком подходе даже «тяжелые» соединения будут занимать канал с наивысшим приоритетом, пока не превысят ограничение. Но даже на медленных соединениях (128 Кбит/с) для этого достаточно всего четырех секунд (если эта закачка в данный момент единственная). После превышения лимита 50 Кбайт соединение получит средний приоритет ([[w:Тип обслуживания |TOS]] не установлен), а еще через некоторое время соединение превысит второй лимит  — 500 Кбайт, и получит минимальный приоритет. В то же время, «легкие» соединения в большинстве случаев не превышают даже первого лимита, и поэтому целиком проходят с повышенным приоритетом.
 
* '''quota'''  — позволяет задать квоту в байтах для данного конкретного правила. Имеет единственный параметр
 
<tt>--quota количество_байт</tt>  — собственно задает квоту.
 
Для каждого правила, содержащего такой критерий, создается счетчик, который уменьшается с каждым прошедшим по этому правилу пакетом на количество байт, равное размеру этого пакета. Когда значение счетчика доходит до нуля, правило перестает срабатывать. Чтобы восстановить счетчик, удалите правило и добавьте его снова.
Строка 1681 ⟶ 1629 :
разрешает хосту передавать не более одного гигабайта транзитного трафика (учитывается трафик в обоих направлениях).
 
* '''quota2'''  — критерий из уже упоминавшегося набора xtables-addons. Является результатом развития идей, заложенных в критерии quota. Позволяет создавать именованные счетчики квот (для совместного использования одного счетчика в нескольких правилах), считать не только байты, но и пакеты, а также создавать отдельные правила для пакетов, превышающих квоту (логическая инверсия параметра <tt>--quota</tt>). Поддерживаются следующие параметры:
 
<tt>--name ''имя''</tt>  — задает имя счетчика. Текущее значение счетчика содержится в файле <tt>/proc/net/xt_quota/''имя''</tt>. Его можно вывести на экран
<source lang="bash">
cat /proc/net/xt_quota/имя
Строка 1691 ⟶ 1639 :
echo значение > /proc/net/xt_quota/имя
</source>
Для осуществления этих действий, как и для работы с iptables, нужны полномочия [[w:Root |суперпользователя]].
 
<tt>[!] --quota ''количество''</tt>  — проверяет текущее значение счетчика и уменьшает его на размер текущего пакета. Этот же параметр задает начальное значение счетчика (если счетчик с таким именем уже существует, он не сбрасывается). Пакет считается подпадающим под критерий, если счетчик еще не дошел до нуля (при указании логической инверсии  — наоборот). Если немного усложнить наш предыдущий пример,
<source lang="bash">
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик
Строка 1708 ⟶ 1656 :
Теперь для подсети 192.168.1.0/24 установлена квота в 1 Гб, и при превышении этой квоты пакеты блокируются, причем их отправителям хост отвечает пакетами icmp-port-unreachable, уведомляя их, что передача данных заблокирована. Для подсети 192.168.2.0/24 устанавливается квота 512 Мб, и при ее превышении никаких сообщений не посылается (пакеты блокируются «молча»). Так же молча блокируются транзитные пакеты из всех остальных подсетей.
 
<tt>--packets</tt>  — при указании этого параметра счетчик учитывает количество пакетов, а не их суммарный размер.
 
<tt>--grow</tt>  — ''увеличивает'' счетчик, вместо того, чтобы уменьшать его. Критерий с этим параметром всегда возвращает истину. Позволяет создавать счетчики «приходно-расходного типа». Например,
<source lang="bash">
-A INPUT -p tcp --dport 6881 -m quota2 --name bt --grow
Строка 1719 ⟶ 1667 :
Вот [http://jengelh.medozas.de/2009/0717-bandwidth-monitoring.php еще один пример] использования этого критерия для сбора статистики по трафику.
 
Обратите внимание, что при указании параметра grow критерий quota2 ''всегда'' будет возвращать истину. Действие для такого правила обычно назначать не имеет смысла  — правило изменяет только счетчик квоты, а не сам пакет.
 
* '''length'''  — позволяет использовать в качестве критерия размер пакета. Проверятся размер пакета протокола транспортного уровня ({{w |TCP}}, {{w |UDP}}, {{w |SCTP}}, {{w |DCCP}} и  т.  д.) или, иначе говоря, размер пакета протокола сетевого уровня ({{w |IP}}, {{w |IPv6}}) за вычетом размера заголовков сетевого уровня. Данный критерий имеет единственный параметр
 
<tt>[!] --length ''размер''[:''макс_размер'']</tt>, который может употребляться в нескольких формах:
 
: <tt>--length ''размер''</tt>  — пакет проверяется на точное соответствие заданному размеру,
 
: <tt>--length ''мин_размер'':</tt>  — размер пакета должен быть больше или равен заданной величине,
 
: <tt>--length :''макс_размер''</tt>  — размер пакета должен быть меньше или равен заданной величине,
 
: <tt>--length ''мин_размер'':''макс_размер''</tt>  — размер пакета должен попадать в указанный диапазон (включая границы).
 
Смысл всех приведенных форм может быть заменен на противоположный, как обычно, указанием перед данным параметром восклицательного знака. Все размеры задаются в байтах.
 
В качестве практического примера использования данного критерия можно рассмотреть установку высокого приоритета [[w:Тип обслуживания |TOS]] (требование минимальной задержки) для небольших транзитных пакетов (размер до 512 байт):
<source lang="bash">
iptables -t mangle -I INPUT -m length --length :512 -j TOS --set-tos Minimize-Delay
</source>
 
* '''length2'''  — расширение критерия length, доступное в наборе xtables-addons. Отличается от классического length возможностью проверять размеры пакетов на различных уровнях [[w:Сетевая модель OSI |модели OSI]]. Принимает следующие опции:
 
<tt>--layer3</tt>  — проверка размера пакета сетевого уровня (например, IPv4-пакета).
 
<tt>--layer4</tt>  — проверка размера пакета транспортного уровня (например, TCP-пакета).
 
<tt>--layer5</tt>  — проверка размера полезной нагрузки транспортного уровня (например, содержимого TCP-пакета, ''не''&nbsp; учитывая размер заголовков TCP). Работает корректно только для некоторых протоколов транспортного уровня, на момент написания этих строк (конец 2009) поддерживаются: {{w |TCP}}, {{w |UDP}}, [[UDPLite]] ([[:en:UDPLite|en]]), {{w |ICMP}}, {{w |ICMPv6}} ([[:en:ICMPv6|en]]), {{w |DCCP}}, {{w |SCTP}}, {{w |IPSec}} (AH и ESP). Для {{w |SCTP}}-пакета в этот размер включаются все [[:en:SCTP_packet_structureSCTP packet structure|секции (chunks)]] вместе с их заголовками.
 
<tt>--layer7</tt>  — для SCTP проверяется суммарный размер DATA-секций в пакете (то есть его полезная нагрузка), для остальных протоколов аналогично <tt>--layer5</tt>.
 
По умолчанию используется <tt>--layer3</tt>, однако во избежание недоразумений рекомендуется явно указывать одну из перечисленных опций. Если этого не делать, при вводе соответствующей команды появится сообщение
iptables: length match: Defaulting to --layer3. Consider specifying it explicitly.
Это ''не''&nbsp; является ошибкой (только предупреждением о возможной неоднозначности). Заданное вами правило должно добавиться успешно.
 
<tt>[!] --length ''размер''[:''макс_размер'']</tt>  — собственно, задает нужные значения размера. В отличие от аналогичного параметра в классическом критерии length, его синтаксические формы несколько беднее. Допускаются два варианта записи:
 
: <tt>--length ''размер''</tt>  — пакет проверяется на точное соответствие заданному размеру,
 
: <tt>--length ''мин_размер'':''макс_размер''</tt>  — размер пакета должен быть попадать в указанный диапазон (включая границы).
 
Впрочем, недостающие варианты легко выразить через имеющиеся: для имитации <tt>--length :''макс_размер''</tt> используйте <tt>--length 0:''макс_размер''</tt>, а вместо <tt>--length ''мин_размер'':</tt> применяйте <tt>--length ''мин_размер'':65535</tt>.
 
Будьте внимательны: в отличие от length, length2 не&nbsp; проверяет взаимное соответствие границ диапазона (<tt>''мин_размер'' <= ''макс_размер''</tt>), и если вы зададите их неправильно (<tt>''мин_размер'' > ''макс_размер''</tt>), ваше правило просто никогда не&nbsp; будет срабатывать. <!-- По крайней мере в xtables-addons 1.21 этот баг присутствует. -->
 
'''Подводя краткий итог по разделу «Лимитирующие критерии»''', хотелось бы заметить, что перечисленные в этом разделе критерии предназначены главным образом для ограничения доступа и защиты от различных атак. Не&nbsp; стоит пытаться ограничивать с их помощью трафик. Для ограничения и приоритезации трафика в [[Linux]] рекомендуется использовать стандартный [[w:Шейпинг (информатика) |шейпер]] ядра, управляемый при помощи утилиты [[w:Iproute2 |tc]].
<!-- Если же вам нужно ограничить именно трафик, а не отдельные пакеты или соединения, то рекомендуем использовать для этого [[w:Шейпинг (информатика) |шейпер]]. Управление шейпером ядра Linux производится при помощи утилиты [[w:Iproute2 |tc]]. Впрочем, этот шейпер позволяет эффективно управлять лишь исходящим трафиком.-->
 
==== Критерий recent ====
recent — это специальный критерий, позволяющий запоминать проходящие через него пакеты, а затем использовать полученную информацию для принятия решений. Ввиду его уникальности, широких возможностей и, как следствие, некоторых трудностей в понимании новичками принципов его использования, рассказ о нем был вынесен в отдельный подраздел.
 
Если быть точным, recent запоминает не сами пакеты, а их количество, время поступления, адрес источника (в последних версиях iptables также может запоминать и адрес назначения), а также, при необходимости, [[w:Time to live|TTL]].
recent — это специальный критерий, позволяющий запоминать проходящие через него пакеты, а затем использовать полученную информацию для принятия решений. Ввиду его уникальности, широких возможностей и, как следствие, некоторых трудностей в понимании новичками принципов его использования, рассказ о нем был вынесен в отдельный подраздел.
 
Если быть точным, recent запоминает не сами пакеты, а их количество, время поступления, адрес источника (в последних версиях iptables также может запоминать и адрес назначения), а также, при необходимости, [[w:Time to live |TTL]].
 
В начале кратко рассмотрим его опции:
 
<tt>[!] --set</tt>  — запомнить адрес источника/назначения пакета (внести его во внутренний список). Если такая запись уже присутствует в списке  — обновить время последнего доступа для нее. Обратите внимание, что критерию recent с опцией <tt>--set</tt> удовлетворяют ''все'' пакеты. Чтобы ему не удовлетворял ни один пакет  — используйте логическую инверсию (<tt>! --set</tt>).
 
<tt>[!] --rcheck</tt>  — позволяет проверить, присутствует ли адрес источника/назначения пакета во внутреннем списке. Критерий recent с этой опцией вернет истину, если адрес в списке присутствует.
 
<tt>[!] --update</tt>  — работает аналогично <tt>--rcheck</tt>, но еще и обновляет время последнего доступа для данной записи.
 
<tt>[!] --remove</tt>  — работает аналогично <tt>--rcheck</tt>, но еще и удаляет найденную запись из списка. Если запись не найдена, пакет считается ''не''&nbsp; соответствующим критерию.
 
<tt>--seconds ''число''</tt>  — дополнительная опция в режимах <tt>--rcheck</tt> и <tt>--update</tt>. Пакет считается соответствующим критерию, только если последний доступ к записи был не позднее, чем ''число'' секунд назад.
 
<tt>--hitcount ''число''</tt>  — дополнительная опция в режимах <tt>--rcheck</tt> и <tt>--update</tt>. Пакет считается удовлетворяющим критерию, если было не менее ''число'' обращений к данной записи. Обычно используется вместе с <tt>--seconds</tt>  — тогда критерий имеет смысл «не менее n обращений за последние m секунд».
 
Заметим, что, хотя в официальной документации для параметров <tt>--seconds</tt> и <tt>--hitcount</tt> указывается возможность отрицания (указания перед ними восклицательного знака), на самом деле такое отрицание никак не&nbsp; обрабатывается в коде и не&nbsp; меняет смысла параметров, так что указывать его бессмысленно. Эта ошибка в документации исправлена в версии iptables 1.4.7.
 
<tt>--rttl</tt>  — дополнительно к адресу источника/назначения, заносить в список и проверять еще и [[w:Time to live |TTL]] пакета.
 
<tt>--rsource</tt>  — эта опция появилась в последних версиях iptables, с тех пор, как критерий recent начал поддерживать запоминание адресов не только источника, но и назначения. Позволяет явно указать, что в список вносится именно адрес источника пакета. Однако в целях обратной совместимости этот режим используется по умолчанию, и поэтому указывать данную опцию не обязательно.
 
<tt>--rdest</tt>  — эта опция появилась в последних версиях iptables. Позволяет явно указать, что в список вносится именно адрес назначения пакета.
 
<tt>--name ''имя''</tt>  — позволяет указать имя списка при использовании нескольких списков. По умолчанию используется список DEFAULT. Каждый список представлен псевдофайлом <tt>/proc/net/xt_recent/''имя''</tt> (на старых ядрах критерий recent реализован только для {{w |IPv4}}, но не&nbsp; для {{w |IPv6}}, поэтому вместо <tt>xt_recent</tt> будет <tt>ipt_recent</tt>). В частности, вы можете:
<source lang="bash">
cat /proc/net/xt_recent/имя # вывести список на экран
Строка 1819 ⟶ 1766 :
iptables -P INPUT DROP # Что не разрешено — то запрещено
</source>
Теперь все попытки открыть новое SSH-соединение проверяются, и с одного {{w |IP-адрес}}а можно открывать не более 2 соединений за 10 минут. Обратите внимание, что за одно соединение злоумышленник может проверить несколько паролей  — число попыток аутентификации до обрыва соединения задает параметр MaxAuthTries в файле <tt>/etc/ssh/sshd_config</tt>. По умолчанию это число равно 6, так что в нашем примере злоумышленник сможет проверять не более 12 паролей за 10 минут.
 
Впрочем, данный пример весьма тривиален, и сходную функциональность можно получить и при помощи критерия hashlimit:
Строка 1826 ⟶ 1773 :
</source>
разрешит не более 5 новых соединений в час.
Данная реализация имеет недостаток по сравнению с recent  — вы не можете произвольно задавать временной период.
 
* Защита от сканирования портов (заметим, что кроме критерия recent для этой задачи можно также использовать критерии psd и lscan из комплекта xtables-addons).
Строка 1873 ⟶ 1820 :
</source>
 
Проводя аналогию с ныне почившим проектом [http://www.opennet.ru/docs/RUS/portsentry/portsentry-security.html.gz PortSentry], первый наш пример соответствует режиму PortSentry «Advanced Stealth Scan Detection», а второй  — «Enhanced Stealth Scan Detection». (Правда, заметим, что в режиме Advanced Stealth Scan Detection блокировка производится после ''первого'' попадания пакета на нерабочий порт&nbsp; — для достижения такого же эффекта в нашем примере достаточно выкинуть проверки на seconds и hitcount из блокирующих правил.) Однако, использование iptables/recent имеет значительное преимущество перед примитивными userspace-системами наподобие PortSentry&nbsp; — возможность интеграции с системой [[conntrack]], что позволяет избежать ошибочной блокировки, например, при использовании высоких портов для {{w |NAT}}.
 
* Открытие порта «по стуку».
 
Port knocking  — метод защиты портов, при котором доступ к определенному порту с отдельно взятого IP-адреса открывается после серии пакетов на заданную последовательность портов с заданными интервалами. <!-- Обычно эта задача решается демоном [[knockd]]. Также сходной функциональностью обладает критерий [http://www.netfilter.org/projects/patch-o-matic/pom-external.html#pom-external-pknock pknock] из [http://www.netfilter.org/projects/patch-o-matic/pom-external.htm patch-o-matic-ng], однако он, к сожалению, потерял разработчика и прекратил развиваться.--> Обычно эта задача решается при помощи демона [[knockd]] либо критерия pknock из комплекта xtables-addons.
 
Несколько самых простых вариантов такой защиты можно организовать и средствами критерия recent.
 
Самое простое  — открывать порт ssh (22) после стука в заданный высокий порт:
<source lang="bash">
iptables -N ssh_knock # Создаем цепочку для проверки попыток соединений на защищаемый порт
Строка 1953 ⟶ 1900 :
iptables -P INPUT DROP # Дефолтное правило цепочки INPUT
</source>
Принцип прост  — при стуке в порт, соответствующий очередной фазе, проверяется наличие записи в предыдущей фазе. Теперь порт 22 откроется на 5 секунд после стука в порты 21210, 11992, 16043, 23050 со строгим соблюдением порядка перечисления и интервалами не более 5 секунд.
 
Обратите внимание на технику реализации процесса  — цепочки фаз вызываются не через <tt>-j</tt>, а через <tt>-g</tt>, поэтому после прохождения этих цепочек к пакетам сразу применяется правило по умолчанию цепочки INPUT, то есть DROP. В противном случае пакеты доходили бы до правила сброса (которое с multiport), и процесс стука все время сбрасывался бы.
 
Последовательный стук в порты можно организовать, например, утилитой {{w |netcat}}
Строка 1968 ⟶ 1915 :
 
==== Критерий u32 ====
Данный критерий предоставляет очень гибкий инструмент, позволяющий производить сложные операции по анализу содержимого пакета. Алгоритм обработки содержимого исследуемого пакета задается на специальном [[Язык программирования|языке программирования]], своеобразном «[[w:Язык ассемблера|ассемблере]]». Такой подход позволяет получить огромную гибкость, но при этом его изучение и использование может представлять определенные трудности для пользователей, не знакомых с основами [[Программирование|программирования]] и принципами работы [[Машина Тьюринга|машины Тьюринга]].
 
Этот критерий имеет единственный параметр — <tt>[!] --u32</tt>, после которого в двойных кавычках записывается текст «программы». Если все проверки, заданные в программе, дают истинный результат, пакет считается удовлетворяющим данному критерию. Традиционно, если перед параметром указан восклицательный знак, означающий логическое отрицание, то удовлетворяющими критерию считаются только те пакеты, для которых хотя бы одна проверка дала ложный результат.
Данный критерий предоставляет очень гибкий инструмент, позволяющий производить сложные операции по анализу содержимого пакета. Алгоритм обработки содержимого исследуемого пакета задается на специальном [[Язык программирования|языке программирования]], своеобразном «[[w:Язык ассемблера |ассемблере]]». Такой подход позволяет получить огромную гибкость, но при этом его изучение и использование может представлять определенные трудности для пользователей, не знакомых с основами [[Программирование|программирования]] и принципами работы [[Машина Тьюринга|машины Тьюринга]].
 
Этот критерий имеет единственный параметр — <tt>[!] --u32</tt>, после которого в двойных кавычках записывается текст «программы». Если все проверки, заданные в программе, дают истинный результат, пакет считается удовлетворяющим данному критерию. Традиционно, если перед параметром указан восклицательный знак, означающий логическое отрицание, то удовлетворяющими критерию считаются только те пакеты, для которых хотя бы одна проверка дала ложный результат.
 
Ключевые операторы языка критерия u32:
* '''='''  — оператор сравнения. Собственно, на его основе и формируются все производимые проверки. Синтаксис его вполне очевиден: <tt>выражение = значение</tt>. В качестве значения можно использовать одно число, диапазон (в формате <tt>мин:макс</tt>) или список чисел и/или диапазонов разделенных запятой (например, <tt>1,3:5,8,11:14</tt>). В одном списке можно указывать не более 10 чисел/диапазонов.
* '''&&'''  — оператор логического И, объединяющий все производимые в программе проверки. В одном критерии u32 можно указывать не более 10 таких проверок. Обратите внимание, что операция логического ИЛИ отсутствует, так как это противоречит идеологии iptables (в каждом правиле все проверки объединяются логическим И, а логическое ИЛИ объединяет правила в одной цепочке).
* '''&'''  — оператор побитового логического И, позволяющий применить к обрабатываемому значению битовую маску.
* '''<<«''' и '''>>»'''  — операторы побитового сдвига влево и вправо соответственно. Эквивалентны домножению или делению обрабатываемого значения на 2 в соответствующей степени. Обратите внимание, что в одном выражении для проверки можно использовать не более 9 операторов &, << и >>.
* '''@'''  — оператор задания смещения. Добавляет результат предыдущего выражения к текущему значению начального смещения (в начале работы программы, до выполнения @-операций, начальное смещение считается нулевым). Очень полезен в тех случаях, когда нужно сместиться на некоторое значение, полученное в результате обработки пакета, например, узнав после некоторых вычислений длину IP-заголовка, мы можем сместиться на данные непосредственно после него, т.е.то есть на начало полезной нагрузки IP-пакета (как правило, там находится заголовок [[w:Транспортный уровень |транспортного уровня]]).
 
Все операторы имеют равный приоритет, исполнение операций всегда происходит слева направо.
 
Обратите внимание, что программа рассматривает все значения как целые беззнаковые величины, заданные 32 битами, или четырьмя октетами (что соответствует значениям от 0 до 4294967295). Именно поэтому критерий имеет такое название (u32  — unsigned 32-bit).
 
Другой не вполне очевидный момент  — синтаксис операторов =, &, << и >>. Дело в том, что в качестве первого операнда указывается не само значение, а его ''адрес'' в пределах пакета, заданный смещением в байтах от текущего начального смещения. Например, <tt>8 = 0x12345678</tt> означает, что нужно взять четыре байта, начиная с восьмого (обратите внимание, что нумерация байтов в пакете начинается с нуля), т.е.то есть байты 8, 9, 10 и 11, и сравнить полученное значение с шестнадцатеричным числом 0x12345678. Как уже говорилось, критерий u32 ''всегда'' манипулирует блоками по четыре байта, поэтому, если вас интересуют блоки меньшего размера, используйте оператор & и маску, например, <tt>8 & 0xFF = 0x78</tt> позволяет проверить только последний в блоке (11-й от начального смещения) байт. Также можно использовать и оператор смещения, например, <tt>8 >> 24 = 0x12</tt> возьмет первый в блоке (8-й от начального смещения) байт и сравнит его с числом 0x12. Более подробно о битовых операциях можно почитать в [[w:Битовые операции |соответствующей статье]].
 
Рассмотрим возможности критерия u32 на нескольких простых примерах из официальной документации:
* Проверить, превышает ли длина пакета величину 256 байт: <tt>--u32 "0 & 0xFFFF = 0x100:0xFFFF"</tt>.
Эта программа предписывает взять четыре байта, начиная с нулевого, затем занулить первые два байта (в них [[w:IP#Пакет (датаграмма) |содержится]] информация о версии протокола, длине заголовка и [[w:Тип обслуживания |типе обслуживания]], которая нас сейчас не интересует), и проверить значение, формируемого оставшимися двумя байтами (это и есть полная длина пакета в байтах) на принадлежность диапазону от 0x100 (256 в десятичном счислении) до 0xFFFF (65535, максимально возможная длина пакета).
* Проверить, является ли данный пакет {{w |ICMP}}-пакетом с типом 0 (эхо-ответ). Учитывая переменную длину IP-заголовка, эта проверка требует несколько большего количества операций: <tt>--u32 "6 & 0xFF = 1 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 >> 24 = 0"</tt>
Рассмотрим эти операции последовательно:
:* '''6 & 0xFF = 1'''  — проверка кода протокола. Код протокола хранится в 9-м (считая с нуля) байте IPv4-заголовка. Чтобы получить это значение, мы берем 4-х байтовый блок с шестого по девятый байт, а затем при помощи маски выделяем последний, интересующий нас байт в это блоке, и сравниваем его с единицей (код протокола ICMP).
:* '''4 & 0x3FFF = 0'''  — проверка, не является ли наш пакет фрагментом. Фрагменты ICMP-пакетов не содержат ICMP-заголовка, в котором должен храниться тип ICMP, поэтому для них дальнейшая проверка не имеет смысла. Пользуясь описанным выше принципом, наша программа выделяет последние 14 бит в блоке с 4-го по 7-й байт, и сравнивает полученное значение с нулем. Строго говоря, для наших целей достаточно было бы и 13 бит (маска 0x1FFF), выделяющих только поле смещения фрагмента (fragment offset, оно должно быть равным нулю для первого пакета в цепочке фрагментов), а использование 14 бит, как это сделано в примере из официальной документации, также захватит и флаг MF (more fragments), что отсечет вообще все фрагментированные пакеты, даже те, которые являются первыми в последовательности и содержат все нужные нам заголовки.
:* '''0 >> 22 & 0x3C @'''  — определение длины IP-заголовка в байтах. Последние четыре бита в первом байте IP-пакета показывают длину IP-заголовка в блоках по четыре байта. Смещая это значение на 22 позиции вправо, мы оставляем справа «зазор» в два бита, которые впоследствии зануляем при помощи маски (3C<sub>16</sub> = 111100<sub>2</sub>). Также эта маска отсекает лишние биты слева (версия протокола). Полученные два нулевых бита справа соответствуют умножению на четыре, так что в результате мы получаем длину заголовка уже в байтах. Например, если длина IP-заголовка составляет 5 четырехбайтовых блоков (т.е.то есть 20 байт), то изначально первый блок заголовка имеет вид <tt>xxxx0101 yyzzzzzz uuuuuuuu uuuuuuuu</tt> (где биты <tt>xxxx</tt> задают версию протокола, 0101<sub>2</sub>=5<sub>10</sub>­  — собственно длину заголовка, <tt>yyzzzzzz</tt>  — тип обслуживания, а два байта <tt>uuuuuuuu uuuuuuuu</tt> показывают полную длину пакета вместе с нагрузкой), то после смещения вправо на 22 бита мы получим в этом блоке следующую картину: <tt>00000000 00000000 000000xx xx0101yy</tt>. После применения маски она пример вид <tt>00000000 00000000 00000000 00010100</tt>. Полученное число  — 10100<sub>2</sub>=20<sub>10</sub> и будет равно длине заголовка в байтах. Наконец, оператор @ устанавливает полученное значение в качестве начального смещения, поэтому вся дальнейшая адресация ведется уже начиная с начала ICMP-заголовка, который следует непосредственно после IP-заголовка.
:* '''0 >> 24 = 0'''  — выделяет блок с нулевого по третий байт ICMP-заголовка, а затем при помощи смещения (на три байта вправо) оставляет от него только один, нулевой, байт, в котором и хранится тип ICMP. Нас интересует тип 0, поэтому мы и сравниваем этот байт с нулем.
* Проверить, задают ли байты с восьмого по одиннадцатый полезной нагрузки {{w |TCP}}-пакета одно из значений: 1, 2, 5, 8. Достигается следующим кодом: <tt>--u32 "6 & 0xFF = 6 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 12 >> 26 & 0x3C @ 8 = 1,2,5,8"</tt>
:* '''6 & 0xFF = 6'''  — выделение байта с кодом протокола и сравнение его с кодом 6 (соответствует TCP). Описание этой проверки уже приведено при рассмотрении предыдущего примера.
:* '''4 & 0x3FFF = 0'''  — проверка, не является ли данный пакет фрагментом. Полностью аналогична описанной в предыдущем примере.
:* '''0 >> 22 & 0x3C @'''  — определение длины IP-заголовка в байтах. Также полностью аналогично описанному в предыдущем примере. После данной операции, начальное смещение указывает на нулевой байт TCP-заголовка.
:* '''12 >> 26 & 0x3C @'''  — определение длины TCP-заголовка в байтах. Принцип действия аналогичен предыдущей операции, с тем лишь отличием, что длина TCP-заголовка закодирована в первых четырех битах двенадцатого байта (а не в последних четырех битах нулевого байта, как в случае с IP-заголовком), поэтому необходимое нам смещение вправо составляет уже 26 бит. Как и в предыдущей операции, мы оставляем справа зазор в два бита, которые впоследствии зануляем маской, и таким образом сразу получаем длину заголовка в байтах. Итак, после второго оператора @, начальное смещение будет указывать на начало полезной нагрузки TCP-пакета (следует непосредственно после заголовка).
:* '''8 = 1,2,5,8'''  — эта операция сравнения вполне тривиальна: выделяется четырехбайтовый блок, начиная с восьмого байта (разумеется, считая от начала полезной нагрузки), и полученное значение сравнивается с одним из допустимых по условию задачи.
 
Также, в качестве полезных примеров использования критерия u32, можно упомянуть проверку портов источника и назначения в протоколе [[UDPLite]] ([[:en:UDPLite|en]]): <tt>--u32 "6 & 0xFF = 136 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 >> 16 = исходный_порт"</tt> и <tt>--u32 "6 & 0xFF = 136 && 4 & 0x3FFF = 0 && 0 >> 22 & 0x3C @ 0 & OxFFFF = порт_назначения"</tt> соответственно (после сказанного выше нетрудно догадаться, что исходный порт указывается в первой паре байт UDPLite-заголовка, а порт назначения  — во второй, согласно [http://tools.ietf.org/html/rfc3828 RFC3828]).
 
==== Прочие критерии ====
 
{{В планах}}
 
==== Критерии из набора xtables-addons ====
 
{{В планах}}
 
Строка 2019 ⟶ 1963 :
 
===== Работа с цепочками =====
 
iptables [-t table] -N chain
 
Строка 2026 ⟶ 1969 :
iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
 
* -F - — Удалить все правила из цепочки
* -L - — Просмотреть цепочку
* -Z - — Обнулить счётчики пакетов в цепочке
 
iptables [-t table] -P chain target
Строка 2039 ⟶ 1982 :
 
===== Работа с правилами =====
 
iptables [-t table] -I chain [rulenum] rule-specification
 
Строка 2050 ⟶ 1992 :
iptables [-t table] {-A|-C|-D} chain rule-specification
 
* -A - — добавить правило в конец
* -С - — проверить, что такое правило есть в таблице
* -D - — удалить правило по описанию или по rulenum
 
===== Вывод информации =====
Строка 2064 ⟶ 2006 :
==== ipset ====
ipset работает с типами данных, которые представляют из себя (man ipset):
* bitmap: ip  — список IP адресов из определенной подсети
* bitmap: ip,mac mac — связки IP+MAC
* bitmap: port  — список портов
* hash: ip  — произвольный набор IP
* hash: net  — произвольный набор сетей
* hash: mac
* hash: net, net
* hash: ip, port
* hash: net, port
* hash: ip, port, ip
* hash: ip, port, net
* hash: ip, mark
* hash: net, port, net
* hash: net, iface
* list: set
 
 
Строка 2090 ⟶ 2032 :
 
==== Полезные при конфигурировании фаервола ====
 
<!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении
 
Строка 2103 ⟶ 2044 :
 
==== Полезные при тестировании фаервола ====
 
<!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении
 
Строка 2113 ⟶ 2053 :
 
===== netstat и ss =====
--><blockquote>iptables -L -n -v #Статистика всех правил iptables и счетчики обработанных пакетов<br>
</blockquote>
 
Строка 2123 ⟶ 2063 :
 
=== С веб-интерфейсом ===
[http://www.117.su iptadmin] - — это пользовательский web интерфейс для iptables, редактор настроек файрволла операционной системы Linux. Реализован в виде отдельного http(s) сервера.
 
Особенностью программы являются подробные сообщения об ошибках при редактировании правил файрволла.
Строка 2180 ⟶ 2120 :
 
== Команды ==
Программа позволяет задать правила, которым должны соответствовать проходящие через [[w:Межсетевой экран |брандмауэр]] [[IP-пакет]]ы. Эти правила, как и все настройки [[Linux]], записываются в текстовый файл, находящийся в папке /etc. Последовательность правил называется цепочкой (CHAIN). Для одного и того же сетевого интерфейса используются несколько цепочек. Если проходящий пакет не соответствует ни одному из правил, то выполняется действие по умолчанию.
 
При вызове, параметром указывается команда, которую нужно выполнить. Обычно можно указать только одну команду (но есть исключения). Команду можно указать одной большой буквой или словом. Если при вызове любой команды не указано название таблицы, то команда выполняется в таблице filter. Программа имеет подробную справку, вызываемую командой ''man iptables''.
Строка 2228 ⟶ 2168 :
 
=== Команды модификации правил ===
 
;Добавить новое правило (<tt>-A</tt>, <tt>--append chain</tt>)
<tt>'''iptables''' [-t ''таблица''] -A ''цепочка'' ''спецификация_правила'' [''параметры'']</tt>
Строка 2258 ⟶ 2197 :
* <tt>[!] '''-s'''</tt>, <tt>--src</tt>, <tt>--source ''адрес''[/''маска'']</tt>
 
Перечисленные ниже параметры используются при задании спецификации правил и указываются с командами модификации правил. Эти параметры ограничивают применение правил  — если обрабатываемый пакет не соответствует указанным в спецификации критериям, то указанное в правиле действие на этот пакет не распространяется.
 
* <tt>'''-p'''</tt>, <tt>--protocol [!] ''протокол''</tt>
Строка 2266 ⟶ 2205 :
* <tt>'''-s'''</tt>, <tt>--src</tt>, <tt>--source [!] ''адрес''[/''маска'']</tt>
 
Ограничение отправителя. Адрес может быть {{w |IP-адрес}}ом (возможно с [[w:Маска подсети |маской]]), именем хоста, или доменным именем. Маска может быть в стандартном формате (например 255.255.255.0) или же в виде числа, указывающего число единиц с «левой стороны» маски (например 24). Знак «!» перед адресом изменяет критерий на противоположенный.
 
Настоятельно не рекомендуется использовать имена, для разрешения которых требуется удаленный запрос, например по системе {{w |DNS}}.
Строка 2308 ⟶ 2247 :
Соединением для NetFilter является закономерно оформленная последовательность обмена пакетами между хостами, с выделением роли каждого пакета в соединении. Эта особенность позволяет контролировать трафик с точки зрения транспортного уровня (модели OSI). Ядро NetFilter отслеживает соединения и ведёт активное наблюдение за открытием новых, протеканием и завершением установленных соединений. Каждый пакет может быть классифицирован по одному из следующих состояний: NEW, ESTABLISHED, RELATED и INVALID.
 
NEW  — типов пакетов, участвующих в установке нового соединения.
 
ESTABLISHED  — пакет уже установленного соединения
 
RELATED  — Соединение получает статус RELATED если оно связано с другим соединением, имеющим признак ESTABLISHED. Это означает, что соединение получает признак RELATED тогда, когда оно инициировано из уже установленного соединения, имеющего признак ESTABLISHED.
 
Состояние RELATED относится к служебному трафику, протоколу ICMP стека TCP/IP.
 
INVALID  — неправильный/ошибочный/испорченный пакет. Обычно для таких пакетов применяют действие DROP
 
ПРИМЕР:
Строка 2327 ⟶ 2266 :
Позволяет задавать возможное количество одновременных подключений к машине от заданного IP или блока адресов
 
<tt>[!] --connlimit-above n</tt>  — пакет подойдет под описание, если количество одновременных подключений на данный момент больше (меньше), чем n
 
<tt>--connlimit-mask bits</tt>  — позволяет задать маску блока адресов
 
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset
Строка 2343 ⟶ 2282 :
 
==== multiport ====
Выделяет не один порт, как <tt>--dport</tt> или <tt>--sport</tt>, а несколько по списку (до 15 штук). Можно задавать диапазоны как первый_порт: последний_порт. Может быть использовано только вместе с <tt>-p udp</tt> или <tt>-p tcp</tt>.
 
Выделяет не один порт, как <tt>--dport</tt> или <tt>--sport</tt>, а несколько по списку (до 15 штук). Можно задавать диапазоны как первый_порт:последний_порт. Может быть использовано только вместе с <tt>-p udp</tt> или <tt>-p tcp</tt>.
 
<tt>[!]--source-ports port1,port2,port3:port4</tt>
Строка 2368 ⟶ 2306 :
 
== Литература ==
 
* {{книга
|заглавие = Linux iptables. Pocket Reference
Строка 2379 ⟶ 2316 :
 
== Ссылки ==
 
* [[Настройка межсетевого экрана в Linux]]
* http://www.netfilter.org/ — Сайт проекта {{w |Netfilter}}
* [http://security.maruhn.com/iptables-manual.html Man page of iptables] {{ref-en}}
* [http://www.frozentux.net/documents/iptables-tutorial/ Frozentux Iptables Tutorial]*{{ref-en}}
* [http://www.opennet.ru/docs/RUS/iptables Руководство по iptables (Iptables Tutorial 1.1.19)]*{{ref-ru}}
* [http://wiki.archlinux.org/index.php/Simple_stateful_firewall_HOWTO#Prerequisites Простой полноценный межсетевой экран (готовый шаблон для дектопа)] {{ref-en}}
* [http://posix.ru/network/iptables Настройка межсетевого экрана Iptables (готовый шаблон для дектопа)]*{{ref-ru}}
* http://freecode.com/projects/flex-fw — гибкая надстройка над iptables для построения сервис-ориентированного statefull-фаервола с простым синтаксисом команд.
* {{Unix man |iptables|8}} {{ref-en}}
* {{Unix man |ufw|8}} {{ref-en}}
* {{Unix man |gufw|8}} {{ref-en}}
* https://help.ubuntu.com/community/IptablesHowTo {{ref-en}}
* https://help.ubuntu.com/community/UFW {{ref-en}}
* https://help.ubuntu.com/community/Gufw {{ref-en}}
* https://help.ubuntu.com/9.10/serverguide/C/firewall.html {{ref-en}}
* https://wiki.ubuntu.com/UncomplicatedFirewall {{ref-en}}
* https://help.ubuntu.com/community/Firewall {{ref-en}}
 
{{Готовность |50%}}