Общая тема: Использование iptables. Часть 2.

Анатомия iptables и команды.

Март 2002

Содержание.

1. Общий формат команд.

2. Как пакеты пересекают iptables.

3. Как пакеты пересекают цепочки.

4. Как пакет взаимодействует с rule.

5. Команды.


1. Общий формат команд.

Прохождение пакетов через iptables сопровождается сравнением с загруженными правилами. Rule это передаваемая с командной строкой инструкция, которую ядро компилирует во внутренний формат. Если match (совпадение) есть, выполняется target или jump. Формат командной строки следующий:


        iptables [table] < command > [load] < chain > < match > < target/jump >

Порядок следования блоков не строг, но для "читабельности" rules следует придерживаться общепринятого формата. Если имя таблицы пропущено, предполагается таблица по умолчанию - filter. Блок command должен стоять первым или сразу после описания таблицы. Команда сообщает iptables, что нужно сделать с командной строкой (добавить rule в конец цепочки, вставить под некоторым номером, удалить rule из цепочки и т.д.). Так как iptables инструмент, расширяемый через kernel modules, то для "нестандартных" расширений предусмотрена явная загрузка. Блок match - передаваемое ядру описание значений полей пакета (шаблон), при совпадении с которым требуется предпринять некоторые действия. Описание шаблонов, пожалуй, самая творческая работа при проектировании ruleset. Блок target/jump - исполняемая часть rule. Если пакет совпал [match] с шаблоном, ядро должно знать, что ему следует предпринять.

Определение "rule это инструкция, передаваемая с командной строкой" очень приблизительно. Можно составить командную строку, которая после загрузки "распадется" на несколько правил. Кроме того, после компиляции во внутренний формат ядра rule может оказаться "многошаговой" инструкцией.


2. Как пакеты пересекают iptables.

Идентификация правил. В iptables правила имеют иерархические имена, отражающие их локацию. Такое имя состоит из трех звеньев - имя таблицы [table] плюс имя цепочки [chain] плюс номер правила [rule] в цепочке. Сочетание имени таблицы плюс имени встроенной [built-in] цепочки дает восемь комбинаций.

В iptables код firewall по выполняемым функциям разделили на таблицы. Порядок пересечения пакетами таблиц достаточно логичен.

Таблица mangle.

Mangle (пресс, деформирование, порча) отражает выполняемые функции. В цепочках таблицы mangle происходит редактирование полей в заголовках пакетов. Отредактированные поля на работу самих iptables не влияют, это делается для внешних приложений. Типичные target для правил этой таблицы - TOS, MARK, TTL, список можно продолжить. Обратите внимание на исключение, target MARK содержимое полей не меняет, маркировка хранится в kernelspace и может использоваться смежными приложениями, работающими только на одной машине с firewall.

Таблица имеет две built-in chains - PREROUTING и OUTPUT. В первой "портятся" пакеты поступившие из вне, во второй редактируются поля локально сгенерированных пакетов.

Таблица nat.

NAT (Network Address Translation) тоже отражает выполняемые функции - редактирование полей с логическими адресами. В отличие от порчи пакетов в цепочках таблицы mangle (прокукарекал, а там хоть не рассветай), редактирование логических адресов имеет специфику. Первое, подменив адрес при прохождении пакетов в прямом направлении, следует его восстановить в обратном потоке. Второе, с правилом из цепочки таблицы nat совпадение ищется только для первого пакета потока. После первого совпадения с rule потоку присваивается идентификатор и все последующие пакеты "портятся - восстанавливаются" по образу и подобию первого.

Таблица имеет три built-in chains - PREROUTING, POSTROUTING и OUTPUT. Цепочка PREROUTING расположена за rp_filter, arp_filter и proxy_arp, но перед модулем маршрутизации. Используется для Destination Network Address Translation (target DNAT). Подмена адреса получателя пакета позволяет реализовать открытие потока между public internet и private LAN по инициативе внешних пользователей (пакет, имеющий в поле destination address IP из пула приватных адресов будет "прихлопнут" первым же router "магистрального" internet). Имеется специальный тип Destination NAT, называемый redirection (target REDIRECT). Никаких хитростей здесь нет, эквивалент DNAT с подменой порта назначения без замены логического адреса. Самая последняя цепочка из пересекаемых пакетами - POSTROUTING. Она предназначена для Source NAT (target SNAT). Подмена адреса отправителя пакета позволяет реализовать открытие потока между private LAN и public internet по инициативе внутренних пользователей. Имеется специальный тип Source NAT, еще называемый masquerading (target MASQUERADE). Необходимость его использования возникает только при использовании dynamically-assigned IP адресов (в случае со статикой строго рекомендуется облегченный SNAT). Для masquerading не требуется указывать IP адрес интерфейса, но что более важно, будут корректно обработаны обрывы связи.

Таблица filter.

Все фильтрующие rules сосредоточены в цепочках таблицы filter. Обычными target для таких правил являются ACCEPT, DROP, REJECT. Обратите внимание, в предыдущей реализации firewall - ipchains аналогичные target были поддержаны "симметрично". В iptables "равноправно" поддержаны наиболее используемые ACCEPT и DROP, а REJECT (или "вежливый" DROP) требует загрузки отдельного модуля.

Таблица имеет три built-in chains - INPUT, OUTPUT и FORWARD. Локация цепочек более логична, чем у предшественника ipchains. Особенностью этих цепочек является наличие police. Если пакет пересекает всю built-in chains из таблицы filter не получив "вердикта" - его судьбу определяет police.

Обратите внимание. Для того, чтобы пакеты между сетевыми интерфейсами могли ходить транзитом, т.е. "не поднимаясь до 5 level ISO OSI" машины с firewall (через цепочку FORWARD), необходимо вкючить forwarding. Иначе они будут DROP на Routing Decision.

Routing Decision и Class Based Queuing.

На рисунке отведено место под Routing Decision и Class Based Queuing. Они не имеют прямого отношения к iptables (инструменты по их настройке в пакете iproute2). Однако, взаимодействие между iptables и iproute2 очень тесное, о чем следует постоянно помнить.


3. Как пакеты пересекают цепочки.

Правила обработки собраны в цепочки, и поступающие пакеты последовательно сравниваются с ними в поисках совпадений со значениями полей headers уровней IP, TCP, UDP и некоторыми другими доступными характеристиками. Цепочки built-in из таблицы filter особенные. Прежде всего, они имеют police, которая решает судьбу пакетов, достигших конца такой цепочки. В строгом ruleset ее устанавливают в значение DROP. Так реализуется общее правило "запрещено все, что явно не разрешено". Политику можно установить в значение ACCEPT и общее правило примет вид "разрешено все, что явно не запрещено". В хорошо написанном ruleset судьба лишь немногих пакетов решается police. Вторая особенность цепочек таблицы filter (в равной степени относится к built-in и user-defined цепочкам) наличие специальных target, решающих судьбу пакета еще до сравнения со всеми правилами. Target DROP (уничтожение пакета) и ACCEPT (принятие пакета) наиболее общие. Для совместимости с кодом ipchais через отдельный модуль доступна target REJECT. REJECT во многом аналог DROP но, после уничтожения пакета его отправителю передается IСMP сообщение.

Код firewall с натяжкой можно было бы назвать программой, если бы отсутствовала возможность его структурирования. "Подпрограммы" оформляются в виде user-defined chains, а их "вызов" реализуется через jump. Если администратором создана цепочка (цепочке при создании присваивается имя) и при прохождении пакета через built-in встречается совпавшее rule с "не служебной" целью (но совпавшей с именем существующей user-defined), происходит jump (переключение) на проход новой цепочки. Если судьба пакета в этой цепочке не решится, произойдет возврат к следующему rule в родительской цепочке (обратите внимание, police для user-defined chains не существует). Вызов дополнительных цепочек возможен не только из main (built-in) цепочки, но и из дочерних.


          built-in                              user-defined
  |-----------------------|     |----------------------------------------------------|

                                   name = test1                   name = test2
    --------------------          ---------------------         ---------------------
    | rule-1: -j target |  |----> | rule-1: -j target |  |----> | rule-1: -j target |
    --------------------   |      ---------------------  |      ---------------------
    | rule-2: -j test1  |--|      | rule-2: -j test2  |--|   |--| rule-2: -j target |
    ---------------------         ---------------------      |  ---------------------
    | rule-3: -j target | <-------| rule-3: -j target | <----|
    ---------------------         ---------------------
    | police            |
    ---------------------

Возможность ветвления кода делает его более структурированным и понятным для чтения. Но все же основное преимущество такого подхода - возможность оптимизации. Следует учитывать, что сравнение пакета с каждым правилом это дополнительный расход ресурсов. Для оптимизации кода следует располагать правила так, чтобы судьба как можно большего числа пакетов решалась за наименьшее число шагов. Оптимизация не должна пасть жертвой безопасности. Порядок, в котором rules размещаются в chains, и точки ветвления критичны для общей логики фильтрации. Оптимизация кода производится на основании собираемой статистики. Про статистику можно сказать так - iptables имеют все для самосовершенствования кода. Имеется даже соблазн использовать эту feature для сбора общесетевой статистики. Идея хорошая, но все же не следует забывать - первичным для firewall является обеспечение безопасности. Кроме того, есть "особенность", описанная в FAQ следующей секции.


4. Как пакет взаимодействует с rule.

В каждом правиле содержится шаблон, на совпадение [match] с которым проверяются поля поступающих пакетов. Если пакет match для rule, происходит следующее:

  1. Счетчик [counter] байтов для rule увеличивается на размер пакета (заголовок плюс данные).
  2. Counter пакетов для rule увеличивается на 1 [incremented].
  3. Исследуется rule target (цель правила) и решается, что делать с пакетом и продолжать ли поиск совпадений в других правилах.

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

Вопрос, ответ и комментарий.

Q: Почему статистика, собираемая iptables, "неправильная"?
A: И в самом деле. Посмотрите на "маршрут" пакетов. Если пакет получил ACCEPT в цепочках filter.FORWARD или filter.OUTPUT (и "попал" в статистику, как "допущенный") это еще не означает, что он покинет firewall box. DROP пакетов из CBQ - "стандартная" практика управления полосой пропускания канала. "Дисциплина очереди", по большому счету, определяет, по какому алгоритму "сверхлимитные" пакеты будут удаляться из очередей. Обратите внимание, статистика от приложений, стоящих над iptables по уровню OSI, тоже страдает погрешностью, но "в другую сторону". Подскажите, как на уровне приложения учесть "служебный" трафик или повторную передачу из-за "перелива" буферов на соседних routers.
C: Погрешность подсчета (по отношению к тому, что вышло из сетевого интерфейса) параметр трудно прогнозируемый. Что касается прохождения пакетов из узкого "горла" в широкое - здесь о погрешности можно не говорить. В обратном направлении она возникает только в "переходных" процессах и при грамотной настройке CBQ не столь высока, как могло бы показаться на первый взгляд. Второй вопрос, а у кого есть время заниматься "ювелирной" настройкой CBQ? Кстати, дисциплины очередей, имеющиеся в распоряжении администраторов Linux 2.4.x, более "продвинутые", чем у аппаратных Cisco.


5. Команды.

Теперь имеются все предпосылки для перехода к практическим вещам. Поговорим о командах и о том, что с их помощью можно делать. Присмотритесь к возможности интерактивной загрузки правил. Только на первый взгляд это кажется сложным. Однако, получив навыки такого стиля работы, вы найдете его очень удобным. Фиксируйте удачный вариант правил командой service iptables save или делайте "откат" к старому варианту командой service iptables restart.

Наиболее обычным действием при работе с firewall является добавление или удаление правила из цепочки в некоторой таблице. Начнем с команды -A (или иначе --append). Команда добавит переданное ей rule в конец цепочки. Пожалуй, самая распространенная команда, тем более в shell script (когда есть возможность без спешки записать rule в нужном порядке). Например:


#/sbin/iptables -t filter -A tcp_in_ppp -p TCP -j DROP

Раз есть возможность добавить, должна быть возможность и удалить rule из chain. Для этого существует команда -D (или иначе --delete). Имеется два способа удаления не нужных rule - удаление по порядковому номеру правила в цепочке (обратите внимание на порядок следования аргументов) и через спецификацию удаляемого правила. В первом случае перед удалением следует воспользоваться командой -L для вывода полного списка правил в цепочке (заметим, опции должны предшествовать команде -L). Примеры:


#/sbin/iptables -t filter --line-numbers -L tcp_in_ppp
 Chain tcp_in_ppp (1 references)
 num  target     prot opt source               destination
 1    ACCEPT     tcp  --  anywhere             anywhere           state RELATED,ESTABLISHED
 2    LOG        all  --  anywhere             anywhere           limit: avg 2/min burst 4 LOG level warning prefix `TCP in 
ppp died: '
 3    DROP       tcp  --  anywhere             anywhere
 4    DROP       tcp  --  anywhere             anywhere
#/sbin/iptables -D tcp_in_ppp 4
#/sbin/iptables --line-numbers -L tcp_in_ppp
 Chain tcp_in_ppp (1 references)
 num  target     prot opt source               destination
 1    ACCEPT     tcp  --  anywhere             anywhere           state RELATED,ESTABLISHED
 2    LOG        all  --  anywhere             anywhere           limit: avg 2/min burst 4 LOG level warning prefix `TCP in 
ppp died: '
 3    DROP       tcp  --  anywhere             anywhere

Добавление правил в интерактивном режиме (и не только) может потребовать дополнительной гибкости - вставить правило в цепочку в требуемой позиции. Для этого существует команда -I (или иначе --insert). Опять же, "не слепое" использование команды -I предполагает команду -L. Пример:


# /sbin/iptables -I tcp_in_ppp 2 -p TCP --syn --dport 113 -j ACCEPT
# /sbin/iptables --line-numbers -L tcp_in_ppp | grep ^2
 2    ACCEPT     tcp  --  anywhere             anywhere           tcp dpt:auth flags:SYN,RST,ACK/SYN
# /sbin/iptables -D tcp_in_ppp -p TCP --syn --dport 113 -j ACCEPT
# /sbin/iptables --line-numbers -L tcp_in_ppp
Chain tcp_in_ppp (1 references)
num  target     prot opt source               destination
1    ACCEPT     tcp  --  anywhere             anywhere           state RELATED,ESTABLISHED
2    LOG        all  --  anywhere             anywhere           limit: avg 2/min burst 4 LOG level warning prefix `TCP in ppp 
died: '
3    DROP       tcp  --  anywhere             anywhere

Последней из команд для работы с отдельным rule назовем -R (или иначе --replace). Команда позволяет отредактировать имеющееся правило.

На команду -L (или иначе --list) уже ссылались. В качестве параметра ей передается имя chain. Без спецификации chain будет выведен листинг правил для всех цепочек. Имеются широко используемые ключики. Для интерактивной работы очень полезен --line-numbers, позволяющий не считать номера правил в цепочке "вручную". Ключик -n подавляет разрешение имен (DNS lookup), что бывает полезным во многих случаях. Ключик -v имеет следствием "многословный" вывод (с показаниями счетчиков статистики и прочего). Обратите внимание, вводить следует скорее iptables -vnL.

Создать новую (user-defined) chain можно командой -N (или иначе --new-chain). При этом необходимо сообщить имя таблицы (если пропущено - по умолчанию filter) и имя новой цепочки. Обратите внимание, имя не должно совпадать ни с одним из служебных target (иначе target невозможно будет отличить от jump). Пример:


# iptables -N test
# iptables -A test -p UTP -j DROP
# iptables -A test -p TCP -j DROP
# iptables -A test -p ICMP -j DROP
# iptables -L test
 Chain test (0 references)
 target     prot opt source               destination
 DROP       udp  --  anywhere             anywhere
 DROP       tcp  --  anywhere             anywhere
 DROP       icmp --  anywhere             anywhere

Команда -F (или иначе --flush) применяется для быстрого удаления всех правил из цепочки. Если в качестве параметра указать только имя таблицы - будут удалены все правила из всех цепочек указанной таблицы. Команда -F без параметров удалит все правила из всех цепочек всех таблиц. Пример:


# iptables -F test
# iptables -L test
 Chain test (0 references)
 target     prot opt source               destination

Команда -X (или иначе --delete-chain) удалит указанную ей chain. Имеются ограничения. Во первых, невозможно удалить ни одну из built-in chains (только user-defined). Во вторых, в ruleset перед удалением должны быть удалены все jump со ссылкой на нее. В третьих, сама chain в момент удаления не должна содержать rules (то есть, предварительно необходимо выполнить команду -F).

Обнуление счетчиков статистики производится командой -Z (или иначе --zero). Можно сбрасывать счетчики в отдельной цепочке, во всех цепочках указанной таблицы или во всех цепочках всех таблиц. В последнем случае команда -Z неплохо сочетается с командой -L и обнуляет счетчики "атомарно" с выводом статистики (iptables -vnL -Z).

Команда -P (или иначе --policy) имеет силу и практический смысл только для built-in цепочек (FORWARD, INPUT, OUTPUT) таблицы filter. Она устанавливает политику в указанное значение (обычно DROP, реже ACCEPT). Пример:


# iptables -P FORWARD DROP

Еще одна команда, которую осталось назвать, это -E (или иначе --rename-chain). Назначение очевидно. Очевидно и ограничение - невозможно переименовать любую built-in цепочку.

Последнее замечание.

Имеется ключик, используемый с командами -A и -I и выделенный в начале статьи в отдельный блок. Это --modprobe= < command > (или -m) - он используется для явной загрузки "экспериментальных" kernel modules. Заметим, iptables достаточно "интеллектуальны" и, в большинстве случаев, неявно подставят -m при вашей забывчивости. Какие модули в используемой вами версии iptables относятся к "нестандарту" и требуют явного указания --modprobe= можно узнать практически, выполнив команду lsmod после загрузки "подозрительного" правила.

Обратите внимание, имеется несколько вспомогательных модулей для ip_conntrack, например, ip_conntrack_ftp, ip_conntrack_irc и т.п. Если ядро собрано с поддержкой автозагрузки kernel modules, они окажутся в памяти при открытии соответствующих RELATED соединений (например, ftp data из под ftp control, ftp data из под irc stream). Не пытайтесь воздействовать на них ключиком -m.



Vladimir Kholmanov.

Наш баннер
Вы можете установить наш баннер на своем сайте или блоге, скопировав этот код:
RSS новости