В начало → Linux не для идиотов → Фильтры пакетов |
Возможность инсталляции фильтров пакетов является очень интересной возможностью, предоставляемой стеком TCP/IP ядра Linux. Не углубляясь в детали просто отметим, что IP-стек Linux позволяет различным модулям установить “ловушки” (hooks) для пакетов. При этом каждый пакет, попадающий в такую ловушку, передается для обработки драйверу, установившему эту ловушку. Драйвер, в свою очередь, может проанализировать пакет, проделать какие-либо действия с пакетом, после чего вернуть код обработки, инструктируя таким образом ядро о том, что следует делать с пакетом дальше – вернуть ли отправителю сообщение об ошибке, прервать ли обработку и уничтожить пакет, либо продолжать обработку пакета обычным образом.
В настоящее время для фильтрации пакетов наиболее часто используются средства iptables. iptables – это название утилиты, которая позволяет настроить множество драйверов сетевой подсистемы NETFILTER ядра Linux, позволяющих осуществить анализ, произвести преобразование, или изменить обработку IP-пакетов. Основным объектом в iptables является цепочка правил (chain). Каждое правило в цепочке содержит набор условий совпадения (condition matches) и действие (action). Цепочки сгруппированы в таблицы (tables).
Действий есть две разновидности – прерывающие обработку пакета в цепочке, например действия DROP или ACCEPT, и не прерывающие обработку пакета цепочкой – например, LOG или MARK.
Цепочки используются для проверки пакетов – то есть пакет поочередно последовательно сравнивается с каждым из правил цепочки, и если он удовлетворяет всем условиям в правиле, к пакету применяется действие, указанное в этом правиле. Если действие является прерывающем, то на этом обработка пакета этой цепочкой заканчивается, если действие не прерывающее, то пакет продолжает проверяться этой же цепочкой.
Стандартные цепочки также содержат специальное неявное действие по умолчанию, называемое политикой цепочки (chain policy). Действие, указанное как политика цепочки, применяется ко всем пакетам, которые не попали ни под одно правило с “прерывающим” действием.
Подсистема пакетного фильтра содержит три таблицы, в каждой из которых содержатся несколько цепочек (наборов правил). Кроме того, администратор может создавать собственные цепочки правил. Ниже перечисляются стандартные таблицы и цепочки:
Таблица |
Назначение |
Цепочки |
Назначение |
---|---|---|---|
mangle | Модификация пакетов | PREROUTING | Модификация всех пришедших пакетов |
INPUT | Модификация пакетов, пришедших на адрес компьютера | ||
FORWARD | Модификация пакетов, которые должны быть отмаршрутизированы (пересланы на другой хост) | ||
OUTPUT | Модификация пакетов, сгенерированных процессами данного хоста | ||
POSTROUTING | Модификация всех переданных пакетов | ||
filter | Фильтрация пакетов – принятие решения об их дальнейшей обработке или отказе от обработки) | INPUT | Фильтрация адресованных этому компьютеру пакетов |
OUTPUT | Фильтрация сгенерированных этим компьютером пакетов | ||
FORWARD | Фильтрация маршрутизируемых (транзитных) пакетов | ||
nat | Трансляция адресов | PREROUTING | Трансляция адресов всех принимаемых пакетов |
FORWARD | Трансляция адресов транзитных пакетов | ||
POSTROUTING | Трансляция адресов всех передаваемых пакетов |
Таблица nat обладает “двойственным” действием, т.е. если вы включите преобразование для входящих пакетов, исходящие пакеты также будут модифицироваться, и наоборот. Таблицы mangle и nat изменяют пакеты, но mangle не ведет список изменений, т.е. является “однонаправленной” таблицей.
Рассмотрим, какой путь проходит пакет в цепочках и таблицах iptables. Для входящих пакетов (адресованных компьютеру, на котором активизирована поддержка iptables) верна следующая последовательность применения цепочек:
mangle.PREROUTING
nat.PREROUTING
mangle.INPUT
filter.INPUT
Для пакетов, отправляемых с компьютера, реализуется следующая цепочка обработки:
filter.OUTPUT
mangle.OUTPUT
nat.POSTROUTING
mangle.POSTROUTING
Пакеты, являющиеся транзитными (маршрутизируемыми), т.е. не адресованные фильтрующему компьютеру и не сгенерированные фильтрующим компьютером, проходят по следующей последовательности цепочек и таблиц:
mangle.PREROUTING
nat.PREROUTING
mangle.FORWARD
filter.FORWARD
nat.FORWARD
nat.POSTROUTING
mangle.POSTROUTING
Каждое правило в любой цепочке может ссылаться на одно из стандартных или дополнительных действий, либо на какую-либо пользовательскую цепочку. Основное различие между стандартными и дополнительными действиями в том, что стандартные действия могут указываться в правилах любых цепочек любых таблиц, а дополнительные действия можно указывать только для некоторых цепочек некоторых таблиц. Перечислим стандартные действия:
ACCEPT |
Прервать проверку пакета цепочкой и перейти к следующей в порядке обработки пакета стандартной цепочке |
---|---|
DROP |
Прервать обработку пакета, сам пакет удалить |
RETURN |
Прервать проверку пакета цепочкой и вернуться к проверке вышестоящей цепочкой, а если действие встретилось в одно из стандартных цепочек, поступить с пакетом так, как предписано в политике цепочки (chain policy) |
QUEUE |
Передать пакет некоторому процессу для дальнейшей обработки |
Интересной особенностью также является то, что существуют так называемые target extensions, которые реализованы как модули и также могут использоваться для указания проводимого над пакетом действия. В частности, к таким действиям, например, относятся действия LOG – запротоколировать факт получения пакета, MASQUERADE – подменить IP-адрес отправителя пакета, MARK – пометить пакет и многие другие. Некоторые действия могут встречаться не во всех цепочках, а только в некоторых цепочках некоторых таблиц.
Еще одним специфическим действием можно назвать переход к пользовательской цепочке. При этом, если пакет в процессе обработки попадает под действие правила, у которого в качестве действия указан переход к другой цепочке, то пакет начинает проверяться ее правилами. Это часто используется, чтобы сходным образом обрабатывать некоторые виды пакетов.
Условия отбора делятся на две группы – стандартные условия, которые применимы ко всем пакетам, и расширенные условия, называемые также match extensions. Расширенные условия могут применяться не для всех пакетов, а только для некоторых из них – например, дополниетельные условия для протокола UDP включают в себя адреса портов отправителя и получателя, а для ICMP – тип и код ICMP-сообщения.
Попробуем рассмотреть несколько простых примеров, достаточно часто используемых в реальных конфигурациях. Стоит заметить, что самостоятельная конфигурация пакетного фильтра требует некоторых (точнее, достаточно значительных) знаний сетевых протоколов, поскольку в конфигурации необходимо задавать множество критериев, которые сильно зависят от ситуации и от используемых сервисов.
Пример 1: простейшая конфигурация iptables для домашнего компьютера, подключенного к Internet. В этой конфигурации мы запретим все входящие соединения, а также все исходящие пакеты UDP кроме тех, которые необходимы для нормальной работы в Internet с использованием PPP-соединения. В этой конфигурации мы разрешаем передачу всех пакетов в рамках локальной машины, разрешаем исходящие TCP-пакеты, разрешаем входящие пакеты TCP для уже установленных соединений, и разрешаем передачу и прием UDP-пакетов для службы DNS и пакетов автоматической конфигурации соединения PPP (пакетов DHCP). Кроме того, следует разрешить прием управляющих пакетов ICMP и отправку запросов и прием ответов PING:
#
iptables -P INPUT DROP
#
iptables -A INPUT -j ACCEPT -i lo
#
iptables -A INPUT -j ACCEP -p tcp ! --syn
#
iptables -A INPUT -j ACCEPT -p udp --source-port 53
#
iptables -A INPUT -j ACCEPT -p udp --source-port 67 --destination-port 68
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type destination-unreachable
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type time-exceeded
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type parameter-problem
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type echo-reply
#
iptables -P OUTPUT DROP
#
iptables -A OUTPUT -j ACCEPT -p tcp
#
iptables -A OUTPUT -j ACCEPT -p udp --destination-port 53
#
iptables -A OUTPUT -j ACCEPT -p udp --destination-port 67 --source-port 68
#
iptables -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-request
Пример 2: то же самое, что в примере 1, но все “отбитые” пакеты протоколируются. Для того, чтобы добиться такого эффекта, нужно создать дополнительную цепочку, которая будет протоколировать и удалять пакеты. Эту цепочку мы назовем KILLER – вполне обоснованно, не так ли? Кроме того, мы исправим политики стандартных цепочек так, чтобы запрещенные пакеты не удалялись, а “забрасывались” в созданную нами цепочку KILLER, а нашей основной цели (сначала протоколировать, потом удалить пакет) можно добиться просто указав два действия – сначала LOG, затем DROP. Поскольку действие LOG не является прерывающим обработку, мы получим требуемый нам эффект:
#
iptables -N KILLER
#
iptables -A KILLER -j LOG
#
iptables -A KILLER -j DROP
#
iptables -P INPUT KILLER
#
iptables -A INPUT -j ACCEPT -i lo
#
iptables -A INPUT -j ACCEP -p tcp ! --syn
#
iptables -A INPUT -j ACCEPT -p udp --source-port 53
#
iptables -A INPUT -j ACCEPT -p udp --source-port 67 --destination-port 68
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type destination-unreachable
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type time-exceeded
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type parameter-problem
#
iptables -A INPUT -j ACCEPT -p icmp --icmp-type echo-reply
#
iptables -P OUTPUT KILLER
#
iptables -A OUTPUT -j ACCEPT -p tcp
#
iptables -A OUTPUT -j ACCEPT -p udp --destination-port 53
#
iptables -A OUTPUT -j ACCEPT -p udp --destination-port 67 --source-port 68
#
iptables -A OUTPUT -j ACCEPT -p icmp --icmp-type echo-request
Пример 3: маскарад пакетов. Маскарадом называют преобразование IP-адресов проходящих пакетов так, чтобы они выглядели как отправленные с системы-маршрутизатора, а не с какого-либо узла “за” маршрутизатором. Достигается это путем изменения IP-адреса (и, возможно, номера порта) в “транзитных” пакетах. Собственно преобразование задается путем указания действий SNAT – замена адреса отправителя, DNAT – замена адреса получателя, или MASQUERADE – функционально аналогично SNAT, но без указания конкретного IP-адреса (IP-адресом для замены назначается IP-адрес интерфейса через который уходит пакет, со всеми отсюда вытекающими – например, если интерфейс меняет IP-адрес или просто деактивируется все «маскированные» через него соединения сбрасываются). Предположим, что наш “внешний” интерфейс имеет адрес 193.267.14.6, а внутренняя сеть имеет адрес 192.168.0.0/24. Тогда для того, чтобы дать всем компьютерам нашей сети доступ по протоколу TCP “наружу”, мы должны подать примерно следующую команду:
#
iptables -A POSTROUTING -t nat -j SNAT -o ppp0 \ > --to-source 193.267.14.6 -p tcp \ > --source 192.168.0.0/24 \ > --destination ! 192.168.0.0/24
Если у нас внешний адрес динамический, а не статический (мы работаем по dialup-соединению), то мы можем использовать динамический маскарад без привязки к внешнему адресу – ну или с использованием динамической привязки, кому как больше нравится:
#
iptables -A POSTROUTING -t nat -j MASQUERADE -o ppp0 \ > --source 192.168.0.0/24 \ > --destination ! 192.168.0.0/24
Действие SNAT более эффективно, MASQUERADE проще в использовании, но обладает рядом существенных недостатков (не вдаваясь
в подробности, просто заметим, что на системе с несколькими интерфейсами и сложной таблицей маршрутизации проблемы почти наверняка
будут). Особое внимание нужно обратить на указание -o ppp0
, то есть действие применяется ТОЛЬКО для пакетов, отправляемых через интерфейс ppp0. Еще вы можете увидеть, что мы указываем
это правило только один раз, и обратного к нему правила не строим – об этом позаботится функция connection tracking (отслеживание
состояния соединений), и обратная замена адресов в отправляемых в ответ на наши запросы пакетах будет произведена системой
автоматически.
Пример 4: “проброс” пакетов во внутреннюю сеть. Обычно это используется, если мы хотим перебросить пакеты, пришедшие на адрес маршрутизатора, на какую-либо из машин внутренней сети (например, так можно предоставить доступ ко внутреннему WWW-серверу). Достигается это использованием действия DNAT (destination NAT). В нашем случае мы перебрасываем все TCP-пакеты, пришедшие на интерфейс маршрутизатора ppp0 на порт 80, на порт 85 компьютера с адресом 192.168.0.6:
#
iptables -A PREROUTING -t nat -j DNAT -i ppp0 \ > --to-destination 192.168.0.6:85 -p tcp --destination-ports 80
Конечно, приведенными примерами возможности iptables не исчерпываются, скорее даже наоборот – это лишь малая часть того, что умеет эта подсистема. Приведенные же примеры демонстрируют наиболее простые случаи, позволяющие составить некоторое представление об iptables и возможностях этой технологии.
В системах, основанных на RedHat Linux и его вариациях, есть специальный стартовый сценарий загрузки, также называемый iptables.
Расположен он как правило в каталоге /etc/rc.d/init.d/. Этот сценарий при загрузке системы инсталлирует правила, созданные
администратором, и его можно использовать для сохранения конфигурации iptables. В процессе конфигурации системный администратор
задает конфигурацию подсистемы iptables, используя утилиту /sbin/iptables
, а после окончания настройки дает команду /etc/rc.d/init.d/iptables save, после чего текущая конфигурация сохраняется в файл
/etc/sysconfig/iptables
. Существует также множество “фронтендов” для настройки iptables, которые могут использоваться начинающими пользователями
и не слишком опытными администраторами, но “ручной” способ настройки все-таки предпочтительней, поскольку позволяет очень
точно настроить подсистему iptables.
В начало → Linux не для идиотов → Фильтры пакетов |