iptables - Учим правила.

В iptables правило фильтрации определяет, как из общего потока данных отбирать определенные пакеты и что с ними делать. С приходящим или уходящим пакетом ты можешь сделать не очень много, но этого вполне достаточно, чтобы создать довольно мощную защиту.
Пакет мы может принять, отбросить с уведомлением отправителя пакета, уничтожить или переслать на другое правило или куда-то еще. Несколько правил составляют цепочку. Фильтр просматривает правила в цепочке одно за другим и выполняет предписанные действия.
Есть стандартные цепочки, но можно намутить и пользовательские, их может быть сколько угодно и каждая из них может иметь свое имя. Теперь немного о стандартных цепочках. Стандартная цепочка INPUT. В нее попадают все ВХОДЯЩИЕ в фильтр пакеты.
Цепочку INPUT проходят пакеты, которые предназначены локальным приложениям (самому firewall'у).

Стандартная цепочка OUTPUT. В нее попадают все ВЫХОДЯЩИЕ из фильтра пакеты. Цепочка OUTPUT используется для фильтрации исходящих пакетов, сгенерированных приложениями на самом firewall'е.
Стандартная цепочка FORWARD. Используется для фильтрации пакетов, идущих транзитом через firewall (во внутреннюю сеть).
Так как ты защищаешь свой компьютер, то можно обойтись первыми двумя.
Пакетный фильтр iptables может работать с тремя таблицами правил. Таблица для фильтрации filter (она ставится по умолчанию, если явно ничего не указано), таблица для nat-маскарадинга и трансляции адресов (очень полезно для вывода локалки в Инет). И, наконец, таблица mangle для редактирования пакетов.
В каждую таблицу заносятся цепочки правил фильтрации. Они последовательно просматриваются и исполняются фильтром. Цепочки ты либо заносишь сам из командной строки, либо пишешь сценарий на shell.
Хочу сказать, что скриптовые языки вроде perl и php для такого дела не подходят, хотя на них и можно написать системы, облегчающие составление правил и цепочек. Зайди на www.freshmeat.net и поищи по слову firewall или по слову iptables - увидишь массу ссылок на программы для быстрого и удобного составления правил фильтрации пакетов.

Правила по косточкам.
Правило состоит из нескольких элементов - команды, опции, критерия отбора и действия. Элементы могут в принципе располагаться как угодно, но лучше придерживаться указанного порядка - так будет потом понятнее самому.
Команды предназначены для того, чтобы сказать фильтру, что мы будем делать. Например, добавить правило в цепочку, удалить правило, очистить цепочку, вывести список правил в цепочке и тому подобное.
Опции нужны, чтобы определенным образом модифицировать выводимую на экран информацию или выполнять добавочные, не присущие самому фильтру действия (например, округлять числовые показатели или подгружать модуль ядра).
Критерий отбора. Это самая важная часть правила. Пакетный фильтр при разборках с пакетом смотрит именно на них. В качестве критериев отбора может выступать интерфейс, с которого пришел пакет, адрес отправителя или адрес получателя, порт отправителя или порт получателя, тип протокола.
Действие. Действие определяет, что именно нам делать с пакетом, который удовлетворяет заданному тобой критерию.
Самый полный список команд, опций, критериев и действий ты найдешь в доке Iptables-tutorial. Там все по-русски, поэтому тебе много не придется ломать голову. К тому же там есть просто шикарные примеры.

Разберем правило:

iptables -A INPUT -i eth0 -p tcp -s 0/0 -d 192.168.1.1 --dport 53 -j DROP


Вот его части:
* iptables - системная программа для вызова утилиты управления пакетным фильтром;
* -A INPUT - команда iptables, означающая "добавить (-A) новое правило в цепочку INPUT";
* критерий -i eth0, говорит, что нам нужен пакет, приходящий с интерфейса (-i) eth0 (сетевуха), если у тебя диал-ап, то интерфейс, скорее всего, будет ppp0;
* критерий -p говорит, что нам нужен пакет протокола (-p) tcp;
* критерий -s 0/0 говорит, что нам нужен пакет с адресом отправителя (-s) любым, то есть 0.0.0.0 с маской подсети 0.0.0.0 или в краткой записи 0/0;
* критерий -d 192.168.1.1 говорит, что нам нужен пакет, который получает (-d) машина с адресом 192.168.1.1;
* критерий --dport 53 говорит, что номер порта принимающей (--dport) машины должен быть равен 53;
* действие -j DROP означает, что если пакет удовлетворяет ВСЕМ перечисленным критериям, то есть если все критерии присутствуют, то этот пакет прыгнет (-j) на цепочку DROP. Проще говоря, он будет уничтожен.
В результате выполнения этого правила на защищаемой машине получим вот такую картину после сканирования портов:
[vitls@zeelog:~]# nmap 192.168.1.1
Starting nmap V. 2.54BETA37 (www.insecure.org/nmap/)
Interesting ports on 192.168.1.1 (192.168.1.1):
(The 1597 ports scanned but not shown below are in state: closed)
Port State Service
21/tcp open ftp
25/tcp open smtp
53/tcp filtered domain
110/tcp open pop-3
Nmap run completed -- 1 IP address (1 host up) scanned in 2 seconds
[vitls@zeelog:~]#
Куем цепи.
Как я уже успел упомянуть, правила могут быть объединены в цепочки. В твоей системе защиты может быть несколько независимых друг от друга цепей.
Про стандартные цепочки ты уже знаешь, а любая нестандартная цепочка, то есть твоя собственная, может взаимодействовать со стандартной. Например, можно принять пакет из цепочки INPUT, проверить его на соответствие какому-то критерию отбора и отправить на твою собственную цепочку для дальнейшей экзекуции. Основываясь на этих возможностях можно построить очень сложную систему распределения и фильтрации входящего к тебе или исходящего от тебя трафика.
Самое главное заключается в мудрости построения последовательности правил в цепочке. Пакетный фильтр просматривает правила исключительно в том порядке, в которым ты их задаешь. Он тупой и исполнительный.
Если ты в первом правиле скажешь, что такой-то пакет отправить на уничтожение, а затем вторым правилом скажешь, что такой же пакет принимать для пересылки, в ответ на это я тебе отвечу, что до второго правила твой пакет просто не доживет, и вся работа пойдет псу под хвост. Так что всегда анализируй то, что уже написал.

Как это делается.
Цепочки ты можешь вводить либо напрямую из командной оболочки (shell), в качестве которой у тебя могут быть sh, bash, ash, zsh, tcsh или что-то еще твое любимое. Я все примеры буду приводить для стандартного sh, так как он есть практически в любом дистрибутиве.
Вводя правила непосредственно из shell, ты должен их набирать последовательно и быть осторожным, любая ошибка и тебе придется вводить: iptables -F имя_цепочки, чтобы ее очистить.
Для устранения этих проблем лучше написать сценарий, который можно будет легко отредактировать в любой момент и выполнить только тогда, когда он будет полностью готов. Сгодится любой текстовый редактор. Все равно текст будет обычный, посему навороты, вроде word, на фиг не нужны.
Для примера я наведу разборки с простым сценарием.

Простой сценарий.
Задача - с помощью iptables закрыть на ppp0 все порты с 1 по 1024 и оставить открытыми только некоторые, например 53 и 80. Что бы кто-то из внешней сети мог воспользоваться только нашим dns сервером и www сервером.
Внутренности файла сценария выглядят примерно так:

#!/bin/sh
IPT=/usr/sbin/iptables
$IPT -F INPUT
$IPT -A INPUT -i ppp0 -p tcp -s 0/0 --sport 0:65535 -d 0/0 --dport 80 -j ACCEPT
$IPT -A INPUT -i ppp0 -p tcp -s 0/0 --sport 0:65535 -d 0/0 --dport 1:1024 -j DROP
$IPT -A INPUT -i ppp0 -p udp -s 0/0 --sport 0:65535 -d 0/0 --dport 53 -j ACCEPT
$IPT -A INPUT -i ppp0 -p udp -s 0/0 --sport 0:65535 -d 0/0 --dport 1:1024 -j DROP

Теперь построчно:

#!/bin/sh


В этой строке мы говорим командной оболочке, что данный сценарий будет выполняться программой /bin/sh.
IPT=/usr/sbin/iptables

Объявляем переменную IPT, куда заносим стоку, содержащую путь к тому месту, где находится утилита iptables. В данном случае /usr/sbin/iptables. В своей системе ты этот путь можешь узнать, выполнив в командной строке команду whiсh iptables.
$IPT -F INPUT


В результате выполнения сценария $ITP будет заменена на /usr/sbin/iptables, то есть мы обозначаем саму утилиту iptables. Это нужно для удобства, чтобы по десять раз не писать одно и то же. Команда -F INPUT приказывает очистить цепочку INPUT.
$IPT -A INPUT -i ppp0 -p tcp -s 0/0 --sport 0:65535 -d 0/0 --dport 80 -j ACCEPT

Данная строка добавляет в цепочку INPUT фильтр по критериям: пакет должен прийти с интерфейса ppp0 (-i ppp0), пакет должен быть по протоколу tcp (-p tcp), прийти с любого адреса (-s 0/0), с любого из портов, указанных в диапазоне (--sport 0:65535), пакет должен быть адресован любому адресу (-d 0/0), и прийти на порт 80 (--dport 80). Если пакет подходит под ВСЕ условия он направляется в цепочку ACCEPT (-j ACCEPT). То есть принимается системой. Если пакет не подходит под данное правило фильтрации, то он переходит к следующему правилу в цепочке:
$IPT -A INPUT -i ppp0 -p tcp -s 0/0 --sport 0:65535 -d 0/0 --dport 1:1024 -j DROP


Данная строка добавляет в цепочку INPUT фильтр по критериям: пакет должен прийти с интерфейса ppp0 (-i ppp0), пакет должен быть по протоколу tcp (-p tcp), прийти с любого адреса (-s 0/0), с любого из портов, указанных в диапазоне (--sport 0:65535), пакет должен быть адресован любому адресу (-d 0/0), и прийти на любой порт в указанном диапазоне (--dport 1:1024). Если пакет подходит под ВСЕ условия он направляется в цепочку DROP (-j DROP). То есть уничтожается системой.
Короче, в этом правиле уничножаются все пакеты на порты от 1 до 1024, которые не попадают под предыдущее правило. Задача же стояла закрыть все, кроме 80-го порта, вот мы и сделали это.
Далее:

$IPT -A INPUT -i ppp0 -p udp -s 0/0 --sport 0:65535 -d 0/0 --dport 53 -j ACCEPT


Данная строка добавляет в цепочку INPUT фильтр по критериям: пакет должен прийти с интерфейса ppp0 (-i ppp0), пакет должен быть по протоколу udp (-p udp), прийти с любого адреса (-s 0/0), с любого из портов, указанных в диапазоне (--sport 0:65535), пакет должен быть адресован любому адресу (-d 0/0), и прийти на порт 53 (--dport 53). Если пакет подходит под ВСЕ условия он направляется в цепочку ACCEPT (-j ACCEPT). То есть принимается системой.
И наконец:

$IPT -A INPUT -i ppp0 -p udp -s 0/0 --sport 0:65535 -d 0/0 --dport 1:1024 -j DROP


Данная строка добавляет в цепочку INPUT фильтр по критериям: пакет должен прийти с интерфейса ppp0 (-i ppp0), пакет должен быть по протоколу udp (-p udp), прийти с любого адреса (-s 0/0), с любого из портов, указанных в диапазоне (--sport 0:65535), пакет должен быть адресован любому адресу (-d 0/0), и прийти на любой порт в указанном диапазоне (--dport 1:1024). Если пакет подходит под ВСЕ условия он направляется в цепочку DROP (-j DROP). То есть уничтожается системой.
Сохраняем и восстанавливаем правила.
Iptables хранит все таблицы и цепочки в оперативной памяти компьютера. Но, авторы были не идиотами и сделали возможность сохранения настроек и их последующего восстановления. Для этого в природе существуют утилиты iptables-save и iptables-restore. Их использовать ну очень просто.
Для сохранения:

iptables-save > filename


(надо указать имя файла с сохраненными цепочками).
Для восстановления:
iptables-restore < filename


(надо указать имя файла с сохраненными цепочками).
Iptables-save cохранит все твои цепочки в специальном файле. А iptables-restore их потом так же хорошо восстановит.
Если ты намерен пользоваться iptables постоянно лучше всего один раз написать и отладить набор нужных тебе правил. Затем дать сохранить при помощи iptables-save.
Для восстановления же при включении компьютера нужно в конец одного из стартовых сценариев (рекомендуется /etc/rc.d/rc.local) добавить строку

iptables-restore < filename


где filename - имя файла с правилами сохраненными при помои iptables-save.
Полезные примеры.
Как настроить пакетный фильтр для фильтрации по содержимому пакетов?
Следующие правила блокируют прохождение пакетов, данные в которых содержат подстроку virus.exe и ведут лог пакетов с строкой secret внутри:

#!/bin/sh
iptables -A INPUT -m string --string "secret" -j LOG --log-level info \ --log-prefix "SECRET"
iptables -I INPUT -j DROP -p tcp -s 0.0.0.0/0 -m string --string "virus.exe"
# Block Code Red
iptables -I INPUT -j DROP -p tcp -m string --string "cmd.exe"
# Block Nimda
iptables -I INPUT -j DROP -p tcp -m string --string "root.exe"
iptables -I INPUT -j DROP -p tcp -m string --string "default.ida"


Другая ситуация: машина подключена к Инету напрямую, нужно сделать так, чтобы доступ с нее был только на ftp, а все остальные in и out пакеты блокировались.
#!/bin/sh
iptables -F OUTPUT
iptables -P OUTPUT DROP
iptables -A OUTPUT -p tcp --dport 20 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT # это если не хочешь по ip лазать

iptables -F INPUT
iptables -P INPUT DROP
iptables -A INPUT -p tcp -m state --state ESTABLISHED, RELATED -j ACCEPT
iptables -A INPUT -p udp --sport 53 -j ACCEPT # опять же для dns

Похожее

Какой firewall вы используете?

Информация
Комментировать статьи на сайте возможно только в течении 30 дней со дня публикации.