Наши партнеры

UnixForum






Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Лопатин Виталий Борисович

ПОСТРОЙ СЕБЕ САМ: БЫСТРЫЙ СПОСОБ ПОЗНАКОМИТЬСЯ С IPTABLES.

[Писано для журнала "Хакер-Спец". Лексика оригинала сохранена.]

Привет, мужик. Сегодня я хочу с тобой поговорить о том, что бездумная работа может привести к очень печальным последствиям. Но главное, я расскажу тебе, как этих последствий можно избежать, на примере защиты любимой оси aka Linux.

ПАРАНОЙЯ НЕ БЫВАЕТ ЛИШНЕЙ

Знаешь ли ты, что, выходя в Сеть со своей машины, ты становишься весьма и весьма привлекательным для атаки хакера? Только что установленная на твой компьютер система совершенно беззащитна перед хаком. И однажды ты замечаешь, что с твоей тачкой что-то происходит: кто-то вмешивается в твой мир и имеет тебя вместе с твоей осью. Почему? Все очень просто.
Существует аксиома: в любой программе есть ошибки. И ошибки эти на установленной, но толком не настроенной системе тобой не исправлены. Да ты даже не подозреваешь о сотнях из них. Соответственно эти баги могут быть использованы взломщиком для проникновения в систему. И вот, твою тачку или сетку сожрали суровые парни, шаряшие по просторам Сети. И тебя вместе с ней. Какой-то славный чел просканировал диапазон IP адресов и набрел на твой работающий комп.

ДЕМОНЫ

Запомни! На каждой вновь установленной системе работают десятки программ-автоматов, которые обслуживают тебя или другие софтины. Они называются демонами. Другое, более правильное название - системный сервис или системный сервер. Каждый такой демонюга для общения с другими программами открывает для прослушивания специальную штуку - порт. Если на порт послать определенные байты aka пакет, демон что-то сделает, причем сам. Почтовый сервер открывает порт 25, www-сервер - 80, и так далее. Таким макаром, каждая программа на работающем в Инете компе может быть найдена по сочетанию IP-адрес:порт (пример: 192.168.0.1:80).
Хочешь узнать больше о стандартных портах служб - загляни в файл /etc/services. Там есть список часто используемых портом и название сервисов.

ХАК ПО КАДРАМ

Злобный воинствующий хрякер рыщет по просторам сети в поисках потенциальной жертвы. И когда-нибудь он обязательно наткнется на тебя.
Перед тем как провести атаку на систему, хацкер проводит разведку. Его задача - узнать, какие демоны висят на твоей машине. Это делается с помощью утилит с общим названием "сканер портов". Одной из них является программа nmap. Результат ее применения показан ниже:
-------------------------------------------------------------------
[root@zeelog:vitls]# nmap -O 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      open         domain
110/tcp     open         pop-3

Nmap run completed -- 1 IP address (1 host up) scanned in 6 seconds
[root@zeelog:vitls]#

-------------------------------------------------------------------
Взломщику остается точно узнать, какая именно программа слушает тот или иной порт, затем поискать в Сети багу, имеющиеся в этой проге. После чего юзается тулза, использующая ошибку сервиса для атаки на систему aka exploit. В результате взломщик либо получает доступ к командной среде с правами администратора (rootshell), либо имеет возможность ввести в систему "трояна" для дальнейшей атаки.

КАК БОРОТЬСЯ?

Прикрывать свою задницу. Точнее задницу твоей системы. Для этого есть несколько способов. Самый простой и эффективный - нафиг отрубить все сервисы, которыми ты не пользуешься. В принципе, я тебе только что процитировал первое правило хорошего системного администратора. А что делать если сервисы нельзя отключать? Ну, допустим, что ты решил изучить программирование на php, а для этого нужен www-сервер apache, работающий на 80-м порту. Вот тут тебе поможет такая хрень, как firewall, другими словами - брандмауэр, или межсетевой экран.
Firewall - это программный (софтина) или программно-аппаратный (железка+софтина) комплекс, предназначенный для контроля доступа из внешней Сети ко внутренней путем фильтрации всего входящего и исходящего трафика и пропуска только разрешенной информации. Твой комп также является сетью, только крохотной, из одной машины.
Есть три основных типа межсетевых экранов: пакетный фильтр (packet filtering), шлюз на сеансовом уровне (circuit-level gateway) и шлюз на прикладном уровне (application-level gateway). Обычно это коммерческие программные продукты. Но ты не огорчайся. Фишка в том, что в твоем Linux у же есть firewall. Относится он к пакетным фильтрам и называется ipchains или iptables (в зависимости от древности версии ядра твоей оськи). Если ты не чайник, то ты должен знать, что твоя система состоит из ядра и прикладных программ. В ядре содержатся драйвера различных устройств, а также все необходимое для полноценной работы компьютера в сети или соло. Вся инфа, приходящая из сети или уходящая туда проходит сквозь ядро. Иначе не бывает. И как ты думаешь, где лучше всего было поставить фиговину, которая поможет пресечь всякие атаки на твою систему? Правильно, в ядре!
Дальше будем говорить о firewall'ах, которые есть в ядре и которые относятся к разновидности "пакетный фильтр".
Firewall на самом деле состоит из двух частей: самого фильтра пакетов и управляющих утилит. Для каждой версии ядер firewall называются по-разному. В ветви 2.0.х ipfwadm, в ветви 2.2.х - ipchains, в ветви 2.4.х - iptables. Я расскажу как об iptables, так как, скорее всего, у тебя в системе стоит ядро 2.4.х. Версию ядра можно узнать командой uname -r из командной строки.

КАК ЭТО РАБОТАЕТ?

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

ВТЫКАЕМ

Надеюсь, ты сумеешь установить пакет с исходниками ядра или нати и скачать свежее ядро ветки 2.4.х с ftp.kernel.org. Коротко это будет выглядеть так: администратором входишь в каталог /usr/src/linux, в консоли или в терминале. Даешь команду:
make menuconfig
или
make xconfig
(если ты работаешь в Х) Идешь в Networking Options и включаешь поддержку Network packet filtering.
Затем, спустившись немного ниже, можешь настроить фильтр пакетов в разделе Netfilter Configuration.
Если что-то из вариантов настройки фильтра пакетов тебе покажется непонятным, а я на 100 процентов уверен, что тебе будет непонятно почти все, я настоятельно рекомендую выйти в Сеть и прочитать (а заодно слить на свой винт) вот эту доку: http://gazette.linux.ru.net/rus/articles/iptables-tutorial.html. Там про iptables написано почти все.
Сразу скажу, что в современных дистрибутивах: ALT Linux Master 2.0, ASP Linux 7.2, Mandrake Linux 7.2 и выше, Red Hat Linux 7.0 и выше, SuSE Linux, Debian 2.2 и выше и так далее, пакетный фильтр iptables уже включен в ядро и настроен на решение часто используемых задач. Значит, тебе с большой вероятностью не придется самому заниматься конфигурированием и сборкой ядра.
Другое дело в случае консервативного дистриба Slackware или Gentoo. Скорее всего, тебе самому придется ковыряться в ядре, собирать его, скачивать пакет iptables (его тоже надо будет собрать) и устанавливать все это барахло. Но я уверен, справившись с установкой такого дистрибутива ты на 100% расправишься с такой мелочью как настройка и сборка ядра.

УЧИМ ПРАВИЛА

В 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 пакеты блокировались.
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

ЧТО ЧИТАЕМ?

Читать тебе, перчик ты недозрелый, придется много, часто и густо. Ха! Не делай такое кислое лицо - это тебе не идет. Ты думаешь, что крутые перцы, о которых идет такая громкая слава, родились с такими мозгами? Ни хрена подобного! Они просиживают ночами, пытаясь вникнуть в документацию. Бери с них пример. И твои нервы станут мягкими и шелковистыми.
Вот тебе список документов и статей, в скобках под названием документов указан адрес откуда можно взять:

1. Kernel-HOWTO
2. Linux 2.4 Packet-filtering-HOWTO
(www.linux.org.ru:8100/books/HOWTO/index.html)

3. Iptables-HOWTO
(www.linuxguruz.org/iptables/howto/iptables-HOWTO.html)

4. Firewall-HOWTO
(linuxdocs.org/HOWTOs/Firewall-HOWTO.html)

5. NAT-HOWTO
(imc.edu.trekhgorny.ru/~merlin/iptables/NAT-HOWTO.linuxdoc.html)

6.Netfilter-hacking-HOWTO
(www.netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO.html)

7. Iptables-tutorial
(gazette.linux.ru.net/rus/articles/iptables-tutorial.html)

Вот и все. Желаю успехов на тяжком пути хакера.