Безопасность в Linux. Фильтрация пакетов

В статье рассмотрены способы организации пакетного фильтра на основе Linux 2.4 и iptables

[X-Stranger (xstranger@tut.by)]

Безопасность в Linux. Фильтрация пакетов

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

Что же такое фильтр пакетов? Фильтр пакетов это программа которая просматривает заголовки пакетов по мере их прихода, и решает дальнейшую судьбу всего пакета. Фильтр может сбросить (DROP) пакет, т.е. как будто пакет и не приходил вовсе, принять (ACCEPT) пакет, т.е. пакет может пройти дальше, или сделать с ним что-то еще более сложное.

В Linux, фильтр пакетов встроен в ядро (как модуль, или как неотъемлемая часть ядра),

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

Почему вы должны использовать фильтр пакетов? Ответ можно дать в виде трёх аксиом:

  • когда вы используете linux для соединения вашей внутренней сети с другой сетью (скажем, с Интернетом) вы имеете возможность разрешать и запрещать отдельные типы траффика. Например, заголовок пакета содержит адрес назначения пакета, так что вы можете запретить пакеты идущие в определенные участки другой сети. Другой пример: вы используете браузер для доступа к каким-либо архивам информации. А браузер постоянно загружает рекламу какой-либо баннерной сети, баннеры которой находятся на страницах этих архивов, что отнимает мое время. Запрет через фильтр пакетов на прохождение всех пакетов к серверу баннерной сети или обратно, решает эту проблему.

  • когда ваша linux машина, единственная преграда, между хаосом Интернета и вашей классной и правильной сетью, было бы хорошо знать что вы можете запретить то, что ломиться к вам. Например, вы можете разрешить все что идет из вашей сети, и позаботиться о всем известном <<Ping of Death>> приходящего от злобных внешних пользователей. Другой пример, вы не хотите чтобы внешние пользователи соединялись с вашей машиной по telnet протоколу, даже несмотря на то что все аккаунты защищены паролями. Может быть вы хотите (как и большинство людей) быть наблюдателем в Интернете, а не сервером. Просто не позвольте никому соединяться с вашим компьютером, запретив в фильтре пакетов все входящие пакеты используемые при установке соединения.

  • временами плохо сконфигурированная машина в сети решает извергнуть во внешний мир какие-либо пакеты. Есть отличная возможность указать фильтру пакетов то чтобы он давал вам знать если что-либо ненормальное случилось; возможно, вы что-то сможете сделать, или возможно вы просто любопытны по своей природе.
Как же можно сделать фильтрование пакетов в Linux? Ядра Linux имеют способность отфильтровывать пакеты еще с версии 1.1. Первое поколение фильтров, основанное на ipfw от BSD, было спортированно Аланом Коксом в конце 1994 года. Оно было улучшено Джо Возом и другими в версии ядра 2.0; пользовательская утилита ipfwadm контролировала правила фильтра в ядре. В середине 1998, для Linux 2.2, ядро было переработано достаточно основательно, на всеобщеее обозрение была представлена новая утилита для управления фильтром - ipchains. Наконец, в середине 1999, код ядра был снова полностью преписан для версии 2.4, появилась утилита четвертого поколения "iptables". Это именна та утилита, про которую ниже пойдёт речь.

Вам необходимо ядро, которое имеет netfilter-инфраструктуру: netfilter - это основа внутри Linux ядра, в которую могут встраиваться другие компоненты (такие как модуль iptables). Это означает что вам необходимо ядро 2.3.15 или выше, и вам необходимо включить (ответить 'Y') на опцию CONFIG_NETFILTER при конфигурировании ядра. Утилита iptables взаимодействует с ядром и указывает ему какие пакеты фильтровать. Несмотря на то что вы программист или просто любопытный, но именно с помощью этой программы вы будете управлять фильтром пакетов. Iptables это заменя для ipfwadm и ipchains. Утилита iptables вставляет и удаляет правила из таблицы фильтра пакетов ядра. Это означает, что, чтобы вы не устанавливали или настраивали это будет потеряно при перезагрузке. Что исправить для того чтобы гарантировать, что правила восстановятся после перезагрузки машины? Для этого были написаны утилиты iptables-save и iptables-restore, которые занимаются тем, что сохраняют и восстанавливают правила фильтрации.

Как пакеты проходят фильтры? Ядро запускается с тремя списками правил в таблице фильтра пакетов; эти списки называются firewall chains или просто chains (цепочки). Три цепочки называются так: INPUT, OUTPUT и FORWARD. Цепочки устроены примерно так (см. рис. 1).

____________    ____________                           _____________
| Входящий | -> | Routing  |---> ( FORWARD ) --------- | Исходящий |-->
|          |    | decision |                   ^       |           |
------------    ------------                   |       ------------- 
                   |                           |
                   |                           |
		   V        ___________        |
              ( INPUT )--- |Локальные| --> ( OUTPUT )
                           | процессы|
                           -----------

                  Рис. 1.  Схема цепочек фильтра пакетов.
Три овала представляют три цепочки. Когда пакет приходит в определенный овал, цепочка исследуется для того, чтобы определить, что делать с пакетом в дальнейшем. Если цепь говорит что надо сбросить (DROP) пакет, пакет разрушается, если цепь разрешает прохождение пакета (ACCEPT), пакет проходит к следующему шагу по схеме. Цепочка - это набор определенных правил. Каждое правило говорит "если заголовок пакета выглядит так, значит надо делать с пакетом то-то". Если правило не совпадает с пакетом, пакет переходит к следующему правилу в данной цепочке. Наконец, если в цепочке не осталось больше правил совсем, ядро проверяет установленный policy (правило действующее по умолчанию для всей цепочки) для данной цепочки, чтобы решить что делать с пакетом дальше. В защищенных системах, policy обычно говорит ядру - разрушить пакет (DROP).
  1. Когда пакет приходит (скажем, через Ethernet карту) ядро сперва просматривает адрес назначения пакета: это называется "маршрутизацией".
  2. Если пакет предназначен для этой машины, пакет проходит через диаграмму в цепочку INPUT. Если это так то любой процесс ожидающий данный пакет получит его.
  3. Иначе, если в ядре отключена возможность маршрутизации, или если ядро не знает как этот пакет маршрутизировать, пакет разрушается. Если маршрутизация разрешена, и пакет предназначен для другого сетевого интерфейса (если вы имеете его), пакет идет по нашей диаграмме прямо в цепочку FORWARD; если он разрешен (ACCEPT), он будет маршрутизирован.
  4. Наконец, программа работающая на самой машине может посылать пакеты. Такие пакеты будут проходить через цепочку OUTPUT: если цепочка разрешает (ACCEPT) их, значит пакет продолжает свой путь на интерфейс для которого он предназначен.

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

Iptables имеет достаточно хорошо написанную и подробную manual-страницу (man iptables), там вы можете найти все интересующие вас моменты.

Есть несколько различных вещей которые вы можете сделать с помощью 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).

Часть 2.

Сегодня мы переходим к непосредственному использованию iptables.

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

Итак, для начала рассмотрим работу фильтра с одним правилом. Замечание: для управления правилами наиболее часто вы, вероятно, будете использовать команды добавления (-A) и удаления (-D). Другие команды (-I для вставки и -R для замены) просто являются расширенными вариантами первых. Каждое правило указывает набор условий, которым пакет должен соответствовать, и что с таким пакетом делать (цель). Пример: вы хотите сбрасывать все ICMP пакеты приходящие с адреса 127.0.0.1. В этом случае условия должны быть такими: протокол ICMP и исходный адрес 127.0.0.1. Наша цель - "DROP" (сбросить). 127.0.0.1 это так называемый loopback-интерфейс, который есть в любом Linux, даже неподключенном в сеть. Вы можете использовать утилиту ping чтобы сгенерировать пакеты типа ICMP (для справки: ping посылает ICMP-пакет 8го типа (echo request) на который получатель должен ответить ICMP-пакетом 0го типа (echo reply)). Т.е. мы используем ping для тестирования нашего правила, которое запрещает "пинговать". Если теперь без установленного правила дать команду

   ping -c 1 127.0.0.1
(послать один ICMP-пакет на наш адрес), то утилита скажет, что ответ был успешно получен. Теперь, для установки правила, используя ранее описанные ключи, даём команду следующего вида:
   iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
Теперь, если дать повторную команду ping, то ответ от хоста получен не будет. Таким образом можно защититься от пингования. Строка команды добавления правила расшифровывается так: добавляем (-A) в цепочку "INPUT" правило, указывающее, что пакеты с адреса 127.0.0.1 ("-s 127.0.0.1") использующие ICMP протокол ("-p icmp") мы должны сбрасывать DROP ("-j DROP"). Теперь, как же удалить правило? Мы можем удалить правило двумя путями. Первый способ, так как мы знаем что это правило единственное в INPUT цепочке мы можем удалить его по номеру:iptables -D INPUT 1

Эта команда удалит правило номер 1 в INPUT цепочке. Второй способ, состоит в том чтобы повторить полностью введенную команду добавления, заменив при этом ключ "-A" на "-D". Это удобно когда вы имеете дело со сложной цепочкой правил и вам некогда пересчитывать их, чтобы выяснить в конце, что правило номер 45 именно то, от которого надо избавиться. Для нашего примера команда выглядит так:iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP

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

Мы знаем что с помощью ключа "-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" (или "--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.4.8/net. Они будут загружены по требованию, если ваше ядро было скомпилированно с опцией CONFIG_KMOD, поэтому у вас нет необходимости вручную загружать их. Расширения для утилиты iptables являются разделяемыми библиотеками, и обычно находятся в /usr/local/lib/ iptables/, хотя в некоторых дистрибутивах их могут разместить в /lib/iptables или /usr/lib/iptables. Существуют расширения двух типов: новые цели, и новые ключи. Некоторые протоколы автоматически предлагают новые ключи: сейчас это TCP, UDP и ICMP как показано ниже. Вы можете указывать новые ключи в командной строке после ключа "-p", который загружает указанное расширение. Чтобы получить помощь по определенному расширению, используйте ключи "-p" или "-j" с последующим ключом "-h" или "--help", пример: iptables -p tcp --help
Поговорим подробнее про расширения предоставляемые протоколами.

TCP-расширение.

TCP расширение автоматически загружается если указан ключ "-p tcp". Оно обеспечивает следующие возможности (ни одно из них не работает с фрагментами):
  • --tcp-flags После может следовать "!", затем две строки флагов, этот ключ позволяет вам фильтровать пакеты по специфичным TCP флагам. Первая строка флагов - это маска: список флагов которые вы хотите исследовать. Вторая строка флагов, говорит какие флаг(и) должны быть установлены. Можно использовать также аргумент "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".

Стоит упомянуть, что есть ещё и другие расширения, подробнее о них можно прочитать в документации к iptables.


Часть 3.

Сегодня мы поговорим о спецификации целей.

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

Когда пакет совпадает с правилом, цель которого пользовательская цепочка, он пренаправляется на правила определенные в этой пользовательской цепочке. Если, пользовательская цепочка не разрешила дальнейшую судьбу пакета, то по завершении этой цепочки, пакет возвращается на следующее правило в текущей цепочке. Представте две простые цепочки (см. рис.): 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, которое также не совпадает. Пользовательские цепочки могут иметь в качестве цели другие пользовательские цепочки. Но никогда не создавайте замкнутых циклов: выши пакеты будут сброшены, если фильтр определит что они зациклены. Расширения iptables: новые цели. Другой тип цели - это расширение цели. Расширение цели состоит из модуля ядра, и необязательного расширения в iptables для обеспечения новых ключей командной строки. Есть несколько устанавливаемых по умолчанию в пакете netfilter расширений: LOG, REJECT.

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

  • --log-level [x]. Этот ключ указывает уровень ведения логов. Вместо x подставляется имя уровня (это "debug", "info", "notice", "warning", "err", "crit", "alert" and "emerg") или соответствующие числа от "7" до "0". Вы можете ознакомиться с информацией по данным уровням в manual для 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.

Статус ip_queue можно проверить с помощью команды /proc/net/ip_queue

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

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

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

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

Создание новой цепочки. Давайте создадим новую цепочку. Назовём её test. Используем ключи "-N" или "--new-chain":iptables -N test

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

   iptables -X test
   
Есть пара ограничений, при удалении цепочек: они должны быть пустыми (смотри очистку цепочек ниже) и они не должны использоваться как цель в любом из правил. Вы не сможете удалить ни одну из трех встроенных цепочек. Если вы не укажете имя удаляемой цепочки, то, если это возможно, все пользовательские цепочки будут удалены. Очистка цепочек. Есть простой путь очистки всех правил из цепочки, используя ключ "-F" (или "--flush").iptables -F FORWARD

Если вы не укажете имя цепочки, то все цепочки будут очищены. Просмотр цепочек. Вы можете просмотреть все правила в цепочке используя ключ "-L" (или "--list"). Значение "refcnt" (счетчик) для каждой пользовательской цепочки - это число правил ссылающихся на данную цепочку, как на цель. Он должен быть равен нулю (и цепочка должна быть пустой) прежде чем цепочку можно будет удалить. Если имя цепочки не указано, все цепочки будут показаны, даже пустые. Есть три параметра которые могут быть использованы с ключом "-L". Это числовой параметр "-n", уберегающий iptables от преобразования IP адресов в доменные имена, что вызовет значительные задержки, если ваша 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 данной цепочки будет определять судьбу пакета. Только встроенные цепочки имеют policy, так как если пакет достигнет конца пользовательской цепочки, то он продолжит свой путь в предыдущей цепочке. Policy может быть или ACCEPT или DROP, например:iptables -P FORWARD DROP

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

Материал подготовлен с использованием "Linux 2.4 Packet Filtering HOWTO by Rusty Russell".

X-Stranger
xstranger@tut.by

Использование материалов сайта Linux.BY разрешено со ссылкой на первоисточник. Материалы распространяются под GNU/GPL.

Опубликовано: 2002-11-05

Статья взята с сайта OpenNet.

Оригинал:

[ опубликовано 12/03/2004 ]

X-Stranger (xstranger@tut.by) - Безопасность в Linux. Фильтрация пакетов   Версия для печати