Next Previous Contents

## 7. Применение iptables

iptables имеет достаточно хорошо написанную и подробную manual страницу (`man iptables`), там вы можете найти все интересующие вас моменты. Те из вас кто знаком с ipchains могут просто просмотреть Различия между iptables и ipchains; они очень похожи.

Есть несколько различных вещей которые вы можете сделать с помощью `iptables`. Вы начинаете с тремя встроенными цепочками `INPUT`, `OUTPUT` и `FORWARD`, которые вы не можете удалить. Давайте посмотрим, что мы можем делать с цепочками:

1. Создать новую цепочку (-N).
2. Удалить пустую цепочку (-X).
3. Изменить policy для встроенной цепочки (-P).
4. Просмотреть правила в цепочке (-L).
5. Очистить все правила в цепочке (-F).
6. Обнулить счетчики пакетов и байтов во всех правилах в цепочке (-Z).

Есть несколько путей управления правилами внутри цепочки:

1. Добавить новое правило к цепочке (-A).
2. Вставить новое правило в цепочку (-I).
3. заменить правило в цепочке (-R).
4. Удалить правило в цепочке (-D).
5. Удалить первое правило в цепочке соответствующее указанному (-D).

## 7.1 Что вы видите когда ваш компьютер грузится

iptables может быть модулем (называется "iptable_filter.o"), который должен быть автоматически загружен когда вы впервые запускаете `iptables`. Он может быть также встроен в ядро постоянно.

До того как будет выполнена любая команда iptables (будьте осторожны: некоторые дистрибьютивы выполняют iptables в инициализирующих систему скриптах), во встроенных цепочках не находиться ни одно правило (`INPUT', `FORWARD' и `OUTPUT'), все встроенные цепочки имеют policy по умолчанию ACCEPT. Вы можете изменить policy по умолчанию в цепочке FORWARD указав ключ "forward=0" для iptable_filter модуля.

## 7.2 Работа с одним правилом

Это вода и хлеб или основа работы фильтра пакетов; управление правилами. Наиболее часто вы, вероятно, будете использовать команды добавления (-A) и удаления (-D). Другие команды (-I для вставки и -R для замены) просто являются расширенными вариантами первых.

Каждое правило указывает набор условий, которым пакет должен соответствовать, и что с таким пакетом делать (цель). Пример, вы хотите сбрасывать все ICMP пакеты приходящие с адреса 127.0.0.1. В этом случае условия должны быть такими: протокол ICMP и исходный адрес 127.0.0.1. Наша цель - "DROP".

127.0.0.1 это так называемый `loopback' интерфейс, который есть у вас, даже если не подключены в реальную сеть. Вы можете использовать "ping" чтобы сгенерировать такие пакеты (ping посылает ICMP пакет 8 типа (echo request) на который получатель должен ответить ICMP пакетом типа 0 (echo reply)). Это делает ping полезным для тестирования.

> ``

>     # ping -c 1 127.0.0.1
>     PING 127.0.0.1 (127.0.0.1): 56 data bytes
>     64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

>     --- 127.0.0.1 ping statistics ---
>     1 packets transmitted, 1 packets received, 0% packet loss
>     round-trip min/avg/max = 0.2/0.2/0.2 ms
>     # iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
>     # ping -c 1 127.0.0.1
>     PING 127.0.0.1 (127.0.0.1): 56 data bytes

>     --- 127.0.0.1 ping statistics ---
>     1 packets transmitted, 0 packets received, 100% packet loss
>     #

Вы видите что первый ping был успешен ("-c 1" указывает команде ping послать только один пакет).

затем мы добавили (-A) в цепочку "INPUT", правило указывающее что пакеты с адреса 127.0.0.1 ("-s 127.0.0.1") использующие ICMP протокол ("-p icmp") мы должны сбрасывать DROP ("-j DROP").

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

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

> `

>             # iptables -D INPUT 1
>             #

> `

Эта команда удалит правило номер 1 в INPUT цепочке.

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

> `

>             # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
>             #

> `

Синтаксис команды -D должен повторить в точности те же ключи что были указаны с командой -A (или -I или -R). Если в цепочке несколько одинаковых правил, то будет удалено только первое из них.

## 7.3 Спецификации фильтра

Мы знаем что с помощью ключа "-p" мы указываем протокол, и с помощью "-s" исходящий адрес, но есть также и другие ключи с помощью которых мы можем указывать характеристики пакета. Ниже дана исчерпывающая информация.

### Указываем исходящий IP адрес и IP адрес назначения

Исходящий IP адрес (`-s', `--source' или `--src') и IP адрес назначения (`-d', `--destination' или `--dst') может быть указан четырмя способами. Наиболее обычный путь - использовать полное имя, такое как "localhost" или " www.linuxhq.com". Второй путь - указать явный IP адрес "127.0.0.1".

Третий и четвертый пути разрешают нам указать группу IP адресов "199.95.207.0/24" или "199.95.207.0/255.255.255.0". Оба эти варианта указывают на любые IP адреса от 199.95.207.0 до 199.95.207.255 включительно; цифры после "/" указывают какая часть IP адресов должна учитываться. "/32" или "/255.255.255.255" используется по умолчанию (совпадает с указанным IP адресом полностью). Чтобы указать любой IP адрес надо использовать "/0":

> `

>             [ зАМЕТКА: `-s 0/0' здесь лишнее. ]
>             # iptables -A INPUT -s 0/0 -j DROP
>             #

> `

Такая запись редко используется, так как она соответствует установке по умолчанию, то есть если мы не укажем "-s" совсем.

### Указываем инверсию

Многие ключи, включая "-s" (или "--source") и "-d" ("--destination") могут использовать аргументы с предшествующим знаком "!" (произноситься как "не") это означает все КРОМЕ указанного. Пример. "-s ! localhost" совпадает с любым пакетом не идущем с localhost.

### Указываем протокол

Протокол можно указать с помощью ключа "-p" (или "--protocol"). Протокол может быть номером (если вы знаете цифровые значения протоколов для IP) или имя протокола "TCP", "UDP" или "ICMP". Регистр не имеет значения, так что "tcp" будет понято так же как и "TCP".

Имя протокола может иметь префикс "!", что инвертирует его, так "-p ! TCP" означает все пакето которые не TCP.

### Указываем интерфейс

Ключи "-i" (или "--in-interface") и "-o" (или "--out-interface") указывают имя интерфейса который должен совпасть. Интерфейс - это физическое устройство на которое пакет приходит ("-i") или с которого пакет уходит ("-o"). Вы можете использовать команду `ifconfig` чтобы просмотреть какие устройства в данный момент "подняты" (т.е., работают в данный момент).

Пакеты проходящие цепочку `INPUT` не имеют исходящего интерфейса, соответственно, любое правило использующее "-o" в этой цепочке никогда не сработает. Также, пакеты проходящие через цепочку`OUTPUT` не имеют входящего интерфейса, поэтому любое правило использующее "-i" в этой цепочке никогда не сработает.

Только пакеты проходящие через цепочку `FORWARD` имеют и входящий и исходящий интерфейс.

Вы можете указать интерфейс который в данный момент не существует; такое правило не будет работать до тех пор пока соответствующий интерфейс не "поднимется". Это очень удобно когда используется PPP соединения по дозвонке (обычно интерфейс `ppp0`) и им подобные.

Имя интерфейса заканчивающееся на "+" означает совпадение всех интерфейсов, начинающихся на указанную строку (независимо от того существуют они или нет). Например, чтобы создать правило совпадающее со всеми PPP интерфейсами, следует использовать ключ `-i ppp+`.

Имя интерфейса может иметь префикс "!" что будет совпадать со всеми интерфейсами не совпадающими с указанным(и).

### Указываем фрагменты

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

Проблема заключается в том, что только начальный фрагмент сожержит полный набор заголовочных полей (IP + TCP, UDP и ICMP) которые можно изучить, последующие же имеют только ограниченный набор полей из первоначального заголовка (IP без дополнительных полей протокола). Поэтому получение содержимого полей протокола (что делается TCP, UDP и ICMP расширениями) из последующих фрагментов невозможно.

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

Иначе, очень важно понимать как фрагменты проходят через правила фильтра пакетов. Любое правило, которое требует информацию, которую мы не будем иметь не сработает. Это означает, что первый фрагмент будет обрабатываться как и любой другой пакет. Второй и последующие фрагменты не будут. Так, правило: `-p TCP --sport www` (указывающее исходящий порт "www") никогда не сработает с фрагментом (кроме первого). Так же не будет работать и `-p TCP --sport ! www`.

Однако, вы можете создать правило специально для второго и последующих фрагментов, используя ключ "-f" (или "--fragment"). Так же можно указать и инверсное правило, которое будет не применяться для второго и последующих пакетов, указав в качестве префикса "!" ("! -f").

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

Информация для сетевых-голов: неправильные пакеты (TCP, UDP и ICMP пакеты слишком малые для получения информации о портах или ICMP код и тип) при подобных атаках уничтожаются. Итак TCP фрагменты считаются ими если они не меньше 8 байтов.

Пример, следующее правило будет уничтожать любые фрагменты идущие на 192.168.1.1:

> `

>     # iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
>     #

> `

### Расширения в iptables: Новые соответствия (ключи, прим. перевод.)

`iptables` является расширяемым инструментом, что означает что ядро и утилита iptables могут быть расширены для добавления новых возможностей.

Некоторые из этих расширений стандартны, другие более экзотичны. Расширения могут делать другие люди и распространять отдельно для определенных людей.

Расширения ядра обычно находятся в директории содержащей модули ядра, такой как /lib/modules/2.3.15/net. Они будут загружены по требованию, если ваше ядро было скомпилированно с опцией CONFIG_KMOD, поэтому у вас нет необходимости вручную загружать их.

Расширения для утилиты iptables являются разделяемыми библиотеками, и обычно находятся в /usr/local/lib/iptables/, хотя в некоторых дистрибьютивах их могут разместить в /lib/iptables или /usr/lib/iptables.

Существуют расширения двух типов: новые цели, и новые соответствия (мы поговорим о новых целях немного позднее). Некоторые протоколы автоматически предлагают новые соответствия: сейчас это TCP, UDP и ICMP как показано ниже.

Для них вы можете указывать новые соответствия в командной строке после ключа "-p", который загружает указанное расширение. Для совершенно новых условий, используйте ключ "-m" чтобы загрузить соответствующее расширение, после которого новые соответствия можно использовать.

Чтобы получить помощь по определенному расширению, используйте следующие ключи ("-p", "-j" или "-m") с последующим ключом "-h" или "--help", пример:

> `

>     # iptables -p tcp --help
>     #

> `

### TCP расширение

TCP расширение автоматически загружаются если указан ключ "-p tcp". Оно обеспечивает следующие возможности (ни одно из них не работает с фрагментами).

--tcp-flags

  После может следовать "!", затем две строки флагов, этот ключ позволяет вам фильтровать пакеты по специфичным TCP флагам. Первая строка флагов - это маска: список флагов которые вы хотите исследовать. Вторая строка флагов, говорит какие флаг(и) должны быть установлены. Пример,

  > `

  >     # iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY

  > `

  Это означает что все флаги должны быть проверены ("ALL" это синоним "SYN,ACK,FIN,RST,URG,PSH"), но только SYN и ACK должны быть установлены. Можно использовать также аргумент "NONE", что значит никакие флаги не подняты.

--syn

  Может быть с префиксом "!", это сокращение для "--tcp-flags SYN,RST,ACK SYN".

--source-port

  может быть с последующим "!", затем с одним TCP портом, или с диапазоном портов. Можно использовать имена портов соответствующие /etc/services или цифры. Диапазоны это или два имени порта разделенные ":", или (чтобы указать больше либо равный чем данный порт), порт с добавленным ":", или (чтобы указать меньше либо равный чем данный порт), порт с префиксом ":".

--sport

  это синоним "--source-port".

--destination-port

  и

--dport

  это то же самое что и выше, только указывает порт на пункте назначения пакета.

--tcp-option

  с последующим необязательным "!" и числом, будет совпадать с пакетом TCP параметр, которого равен заданному числу. Пакет, который не будет иметь полного TCP заголовка, будет сброшен автоматически при попытке изучения его TCP параметра.

### Расшифровка TCP флагов

Иногда бывает полезно разрешить TCP соединения в одном направлении, и запретить в противоположном. Например, вам необходимо разрешить соединения на внешний WWW сервер, но запретить соединения с него.

Первой мыслью приходит в голову - запретить TCP пакеты приходящие с того сервера. К сожалению, TCP соединения для работы требуют прохождения пакетов в обоих направлениях.

Решение проблемы в том, чтобы блокировать только пакеты, используемые для установки соединения. Такие пакеты называются SYN пакетами (если быть точными то это пакеты с установленным SYN флагом, а FIN и ACK флаги должны быть чистыми, мы называем такие пакеты SYN пакетами для краткости). запретив только эти пакеты, мы сможем прекратить установку соединений в самом начале.

Ключ "--syn" используется именно для таких случаев: он действителен только для правил, которые указали протокол TCP как используемый протокол. Например, следущее правило соответствует попытке установки соединения с узла 192.168.1.1:

> `

>     -p TCP -s 192.168.1.1 --syn

> `

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

### UDP расширение

UDP расширение автоматически загружается при указании ключа "-p udp". Оно обеспечивает следующие возможности "--source-port", "--sport", "--destination-port" и "--dport" с тем же синтаксисом что и для TCP расширения.

### ICMP расширение

ICMP расширение автоматически загружается при указании ключа "-p icmp". И обеспечивает только одной новой возможностью:

--icmp-type

  с последующим необязательным "!", затем идет или тип icmp пакета (пример "host-unreachable"), или цифра (номер типа, пример. "3"), или номер типа и код разделенные "/" (пример "3/3"). Список icmp типов можно получить при помощи команды "-p icmp --help".

### Другие расширения условий

Другие расширения в netfilter пакете даны как демонстрационные расширения, которые (если установленны) могут быть вызваны с помощью ключа "-m".

mac

  Этот модуль может быть вызван с помощью ключа "-m mac" или "--match mac". Он используется для проверки исходного Ethernet (MAC) адреса входящего пакета, и поэтому полезен только при использовании в цепочках PREROUTING и INPUT. Модуль обеспечивает только одну опцию:

--mac-source

  с последующим необязательным "!", затем указывается ethernet адрес в виде разделенных ":" шестнадцетеричных чисел, пример "--mac-source 00:60:08:91:CC:B7".

limit

  Этот модуль может быть вызван с помощью ключа "-m limit" или "--match limit". И используется для ограничения скорости срабатывания правил, например для ограничения записи логов. Только ограниченное число раз в секунду, правило будет срабатывать (по умолчанию, три элемента в час, с очередью из 5 элементов). Модуль имеет два необязательных аргумента:

--limit

  с последующим числом; указывает максимальное среднее число элементов срабатывающих в секунду. После числа можно указать временную единицу, используя "/second", "/minute", "/hour" или "/day", или сокращение ( "5/second" то же самое что и "5/s").

--limit-burst

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

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

> `

>     # iptables -A FORWARD -m limit -j LOG

> `

Когда это правило сработает впервые - информация о пакете попадет в лог; так как очередь по умолчанию равна 5, первые пять пакетов будут записаны. После этого, только по истечении двадцати минут, будет занесена новая информация о последующем пакете, независимо от того сколько пакетов уже прошло через это правило. Также, каждые двадцать минут, во время которых ни один пакет не подходит под это правило, один из элементов очереди освобождается; если в течении 100 минут ни один из пакетов не попал под это правило, то очередь полностью освободиться; и мы вернемся к тому с чего начали.

Информация: в данный момент вы не можете создать правило с временем освобождения очереди большим чем 59 часов, поэтому если вы установите среднюю величину восстановления в один в день, то ваша очередь должна быть меньше чем 3.

Вы можете также использовать этот модуль для того чтобы избежать различного рода (DoS) атаки.

защита от Syn-flood:

> `

>     # iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT

> `

защита от скрытого сканирования портов:

> `

>     # iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

> `

всем известный Ping of death:

> `

>     # iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

> `

Этот модуль работает как "hysteresis door" (дверь с запаздыванием), как показано ниже на графике.

> ``

>            rate (pkt/s)
>                  ^        .---.
>                  |       / DoS \
>                  |      /       \
>     Edge of DoS -|.....:.........\.......................
>      = (limit *  |    /:          \
>     limit-burst) |   / :           \         .-.
>                  |  /  :            \       /   \
>                  | /   :             \     /     \
>     End of DoS  -|/....:..............:.../.......\..../.
>      = limit     |     :              :`-'         `--'
>     -------------+-----+--------------+------------------> time (s)
>        LOGIC =>  Match | Didn't Match |    Match

Скажем, мы говорим - в одну секунду должен проходить один пакет, с очередью в 5 пакетов, но приходит 4 пакета в секунду в течении трех следующих секунд, затем происходит то же самое опять в течении трех секунд.

> `

>             <--Flood 1-->           <---Flood 2--->

>     Total  ^                   Line  __--      YNNN
>     Packets|               Rate  __--      YNNN
>            |            mum  __--      YNNN
>         10 |        Maxi __--         Y
>            |         __--            Y
>            |     __--               Y
>            | __--    YNNN
>            |-    YNNN
>          5 |    Y
>            |   Y                                Key:  Y -> Сработавшее правило
>            |  Y                                       N -> Несработавшее правило
>            | Y
>            |Y
>          0 +-------------------------------------------------->  Time (seconds)
>             0   1   2   3   4   5   6   7   8   9  10  11  12

> `

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

owner

  Этот модуль пытается сравнить различные характеристики пакета и его создателя, для локально сгенерированных пакетов. Модуль работает только с цепочкой OUTPUT, и даже тогда, есть некоторые типы пакетов (такие как ICMP ответы на пинг) могут не иметь создателя, и соответственно такое правило с ними не сработает.

--uid-owner userid

  Правило срабатывает, если пакет был создан процессом с указанным действительным (цифровым) user id.

--uid-owner groupid

  Правило срабатывает, если пакет был создан процессом с указанным действительным (цифровым) group id.

--pid-owner processid

  Правило срабатывает, если пакет был создан процессом с указанным process id.

--sid-owner sessionid

  Правило срабатывает, если пакет был создан процессом с указанным session id.

unclean

  Этот экспериментальный модуль может быть загружен с помощью ключей "-m unclean" или "--match unclean". Он производит различные проверки пакета на правильность. Этот модуль еще недостаточно отлажен, и не должен использоваться для обеспечения безопасности. (он вероятно может наделать много бед, так как сам может содержать дыры). В нем нет дополнительных ключей.

### State расширение

Наиболее полезный критерий соответствия обеспечивается "state" расширением, которое интерпретирует выводы сделанные модулем отслеживания соединений "ip_conntrack". Это расширение крайне рекомендовано к использованию.

Указывая ключ "-m state" дает нам возможность использовать дополнительный ключ "--state", со списком аргументов разделенных запятой (знак "!" указывает, что пакет не совпадает с указанным набором аргументов). Аргументы таковы:

NEW

  Пакет, который создает соединение.

ESTABLISHED

  Пакет, который принадлежит уже установленному соединению (например, соединению которое получало ответные пакеты).

RELATED

  Пакет, который относиться к, но не часть существующего соединения, такой как ICMP сообщение об ошибке, или (с загруженным FTP модулем), пакет устанавливающий ftp соединение для данных.

INVALID

  Пакет, который не был идентифицирован по какой-либо причине: что включает в себя, нехватку памяти и ICMP ошибки, которые не соответствуют ни одному из известных соединений. Обычно такие пакеты должны быть сброшены.

## 7.4 Спецификация целей

Теперь, зная какие соответствия мы можем поставить пакету, мы бы хотели иметь путь, который бы указывал ядру что делать с пакетом совпадающим с нашими условиями. Такой путь называется - целью правила.

Есть два очень простых встроенных правила: DROP и ACCEPT. Мы уже встречали с ними. Если правило совпадает с пакетом и цель правило соответствует одной из этих двух целей, то больше никакие правила не просматриваются: судьба пакета уже решена.

Есть два типа целей отличающихся от встроенных: расширения и пользовательские цепочки.

### Пользовательские цепочки

Одна из мощных возможностей `iptables` наследованная от `ipchains` - это возможность создавать пользовательские цепочки, в дополнение к встроенным (INPUT, FORWARD и OUTPUT). По общему согласию, пользовательские цепочки всегда создаються в малом регистре, чтобы их можно было легче различать. (Мы опишем как создавать такие цепочки ниже в Операции над целой цепочкой).

Когда пакет совпадает с правилом, цель которого пользовательская цепочка, он пренаправляется на правила определенные в этой пользовательской цепочке. Если, пользовательская цепочка не разрешила дальнейшую судьбу пакета, то по завершении этой цепочки, пакет возвращается на следующее правило в текущей цепочке.

Снова пришло время для ASCII художеств. Представте две (простые) цепочки: `INPUT` (встроенная цепочка) и `test` ( пользовательская цепочка).

> ``

>              `INPUT'                         `test'
>             ----------------------------    ----------------------------
>             | Правило1: -p ICMP -j DROP|    | Правило1: -s 192.168.1.1 |
>             |--------------------------|    |--------------------------|
>             | Правило2: -p TCP -j test |    | Правило2: -d 192.168.1.1 |
>             |--------------------------|    ----------------------------
>             | Правило3: -p UDP -j DROP |
>             ----------------------------

Представте TCP пакет приходящий с 192.168.1.1, и идущий к 1.2.3.4. Он попадает в `INPUT` цепочку, и проходит проверку в Правиле1 - не совпадает. Правило2 совпадает, и его цель - `test`, поэтому следующее правило, которое сработает - это Правило1 в `test` цепочке. Это правило в `test` совпадает - но не имеет цели, поэтому пакет перемещается к следующему правилу - Правилу2. Оно не совпадает, итак мы достигли конца цепочки. Мы возвращаемся в цепочку `INPUT`, где мы только что закончили обработку Правила2, так что теперь мы переходим к Правилу3, которое также не совпадает.

Итак путь пакето можно отобразить так:

> ``

>                                     v    __________________________
>              `INPUT'                |   /    `test'                v
>             ------------------------|--/    -----------------------|----
>             | Правило1              | /|    | Правило1             |   |
>             |-----------------------|/-|    |----------------------|---|
>             | Правило2              /  |    | Правило2             |   |
>             |--------------------------|    -----------------------v----
>             | Правило3             /--+___________________________/
>             ------------------------|---
>                                     v

Пользовательские цепочки могут иметь в качестве цели другие пользовательские цепочки (но не создавайте замкнутых циклов: выши пакеты будут сброшены, если фильтр определит что они зациклены).

### Расширения к iptables: Новые цели

Другой тип цели - это расширение цели. Расширение цели состоит из модуля ядра, и необязательного расширения в `iptables` для обеспечения новых ключей командной строки. Есть несколько устанавливаемых по умолчанию в пакете netfilter расширений:

LOG

  Этот модуль обеспечивает ведения лога для совпавших с правилом пакетов. Он имеет дополнительные ключи:

--log-level

  С последующим числом или именем уровня. Правильные имена это "debug", "info", "notice", "warning", "err", "crit", "alert" and "emerg", соответствующие числам от "7" до "0". Вы можете ознакомиться с информацией по данным уровням в man странице для syslog.conf.

--log-prefix

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

Этот модуль наиболее полезен в совокупности с расширением limit, так вы не позволите переполнить ваши лог-файлы.

REJECT

  Этот модуль создает тот же эффект что и цель "DROP", с одним исключением - отправителю пакета посылается ICMP пакет с сообщением об ошибке "port unreachable". заметьте, что ICMP сообщение не будет послано, если (смотрите RFC 1122):

  - Пакет был отфильтрован как ICMP пакет с сообщением об ошибке, или как ICMP пакет неизвестного типа.
  - Пакет был отфильтрован как фрагмент какого-либо пакета (не первый фрагмент).
  - И если мы уже посылали слишком много ICMP пакетов с сообщением об ошибке отправителю.

  REJECT имеет необязательный аргумент `--reject-with' который изменяет ответный пакет: смотри man страницу.

### Специальные встроенные цели

Есть две специальные встроенные цели: `RETURN` и `QUEUE`.

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

`QUEUE` - это специальная цель, которая ставит пакет в очередь на обработку пользовательскому процессу. Для того чтобы эта цель была полезна, необходимы еще два компонента:

- "queue handler" - обработчик очереди, который выполняет работу по передаче пакетов между ядром и пользовательским приложением; и
- пользовательское приложение которое будет получать, возможно обрабатывать, и решать судьбу пакетов.

Стандартный обработчик очереди для IPv4 - это модуль ip-queue, который распространяется с ядром и помечен как экспериментальный.

Ниже дан пример, как можно использовать iptables для передачи пакетов в пользовательское приложение:

> `

>     # modprobe iptable_filter
>     # modprobe ip_queue
>     # iptables -A OUTPUT -p icmp -j QUEUE

> `

С этим правилом, созданные локально пакеты ICMP типа (такие, что создаются скажем при помощи команды ping) попадают в модуль ip_queue, который затем пытается передать их в пользовательское приложение. Если ни одно из таких приложений не найдено, пакеты сбрасываются.

Чтобы написать пользовательскую программу обработки пакетов, используйте libipq API. Оно распространяется с пакетом iptables. Примеры можно найти в testsuite tools (например redirect.c) на CVS.

Статус ip_queue можно проверить с помощью:

> `

>     /proc/net/ip_queue

> `

Максимальную длинну очереди (то есть, число пакетов передаваемых в пользовательское приложение без подтверждения обработки) можно контролировать с помощью:

> `

>     /proc/sys/net/ipv4/ip_queue_maxlen

> `

По умолчанию - максимальная длинна очереди равна 1024. Как только этот предел достигается, новые пакеты будут сбрасываться, пока очередь не снизиться ниже данного предела. Хорошие протоколы, такие как TCP интерпретируют сброшенные пакеты как перегруженность канала передачи, и успешно с этим справляются (насколько я помню, пакет будет просто переслан заново удаленной стороной, прим. перевод.). Однако, может потребоваться некоторого рода эксперементирование, чтобы определить оптимальную длинну очереди в каждом конкретном случае, если по умолчанию очередь слишком мала.

## 7.5 Операции над целой цепочкой

Очень полезное свойство `iptables` это возможность группировать взаимозависимые правила в цепочки. Вы можете называть ваши цепочки как вам удобнее, но я рекомендую вам использовать буквы малого регистра, чтобы избежать путаницы со встроенными цепочками и целями. Имена цепочек могут быть длинной до 31 символа.

### Создание новой цепочки

Давайте создадим новую цепочку. Так как я парень с развитым воображением, я назову ее `test`. Используем ключи "-N" или "--new-chain":

> `

>     # iptables -N test
>     #

> `

Это просто. Теперь вы можете создавать правила как указано выше.

### Удаление цепочки

Удалить цепочку так же просто, как и создать ее, используем ключи "-X" или "--delete-chain". Почему "-X"? Да потому что все хорошие буквы мы уже использовали.

> `

>     # iptables -X test
>     #

> `

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

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

### Очистка цепочек

Есть простой путь очистки всех правил из цепочки, используя ключ "-F" (или "--flush").

> `

>     # iptables -F FORWARD
>     #

> `

Если вы не укажете имя цепочки, то все цепочки будут очищены.

### Просмотр цепочек

Вы можете просмотреть все правила в цепочке используя ключ "-L" (или "--list").

значение "refcnt" (счетчик) показанный для каждой пользовательской цепочки это число правил ссылающихся на данную цепочку, как на цель. Он должен быть равен нулю (и цепочка должна быть пустой) прежде чем цепочку можно будет удалить.

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

Есть три параметра которые могут быть использованы с ключом "-L". Это "-n" (числа только) - полезен, так как предотвращает `iptables` от преобразования IP адресов в доменные имена, что (если вы используете DNS как большинство людей) вызовет значительные задержки, если ваша DNS служба, не настроена корректно, или если вы отфильтровываете DNS запросы. Также с этим параметром, TCP и UDP порты отображаются в цифровом виде, а не как имена сервисов, которые на них обычно запущены.

Параметр "-v" выдаст детальную информацию по каждой цепочке, такую как счетчик пакетов и байт, сравнение TOS, и интерфейсы. Иначе все эти значение не выдаются.

Счетчики пакетов и байт, печатаются с использованием суффиксов "K", "M" или "G" для 1000, 1,000,000 и 1,000,000,000 соответственно. Используя "-x" (расширенные числа) можно вывести полное числа, независимо от их величин.

### Сбрасывание (Обнуление) счетчиков

Полезно иметь возможность сбрасывать счетчики. Это можно сделать с помощью ключа "-Z" (или "--zero").

Выполним следующее:

> `

>     # iptables -L FORWARD
>     # iptables -Z FORWARD
>     #

> `

В вышеприведенном примере, некоторые пакеты могли пройти во время интервала, между выполнением первой "-L" и второй команды "-Z". По этой причине, вы можете использовать эти две команды совместно, чтобы сбросить счетчики, во время просмотра.

### Установка policy(политики по умолчанию)

Мы умолчали о том что случиться с пакетом, при достижении конца встроенной цепочки, когда ранее обсуждали как пакет проходит через цепочки. В этом случае policy данной цепочки будет определять судьбу пакета. Только встроенные (`INPUT`, `OUTPUT` и `FORWARD`) цепочки имеют policy, так как если пакет достигнет конца пользовательской цепочки, то он продолжит свой путь в предыдущей цепочке.

policy может быть или `ACCEPT` или `DROP`, например:

> `

>     # iptables -P FORWARD DROP
>     #

> `

Next Previous Contents