Дмитрий Докучаев
Люди, установившие себе Linux в качестве рабочей станции, нередко придерживаются мнения, что хакеры тянутся только к крупным серверам, поэтому фаервол им ни к чему. Это не совсем верно. Дело в том, что в большинстве случаев взломщику просто наплевать, что ломать и куда вторгаться. Поэтому о своей защите лучше позаботиться заранее, чтобы потом не пришлось кусать локти и сожалеть о собственной беспечности.
Для начала вспомним, что такое фаервол. По сути, это стандартный фильтр пакетов, параметры которого задает пользователь. Юниксистам, в отличие от windows-пользователей, с "огненной стеной" повезло. Фаервол является обязательным атрибутом всех unix-like систем. В линуксе, например, в истории развития операционки можно проследить три фаервола: сначала был простой в использовании ipfadm (его синтаксис схож с ipfw, характерным для BSD-систем), затем с развитием ядра Linux появился ipchains. Он уже умел делать NAT (замена source-ip) и REDIRECT (замена destination-port) и работал на 2.2.х ядрах. С появлением ветки 2.4 приобрел популярность фаервол iptables, который имел множество различных функций и модулей. Последняя версия в истории этого брандмауэра - 1.3.10 (6.10.2000)
Обычно для активации фаервола достаточно выполнить команду service iptables start. После этого будут загружены модули iptable_nat, iptable_owner, iptable_state и iptable_filter. Каждый модуль отвечает за определенные функции. После запуска фаервола можно посмотреть наличие всех (пока еще пустых) цепочек. Делается это командой iptables -L. Будет видно, что у брандмауэра есть три главных цепи: INPUT, OUTPUT и FORWARD. В них как раз и записываются правила, определяющие политику работы фаервола. Политик может быть две - ACCEPT, которая принимает все пакеты без исключения (по умолчанию), и DROP, фильтрующая все соединения, если нет исключающих правил. Кроме того, пользователь может создать свои личные цепи и соединить их с главными.
INPUT содержит в себе правила, проверяющие любые входящие в систему пакеты. После такой проверки ядро "решает" - пропустить пакет или блокировать. Фильтровать пакет можно двумя способами - DROP, делая вид, что сервер недоступен, и REJECT - эмуляция отсутствия сервиса (при этом запрете на порт, фаервол ответит на запрос - connection refused, как будто порт вообще не светится).
В этой цепочке находятся правила, обрабатывающие исходящие пакеты. Принцип работы аналогичен INPUT. При наличии запрещающих правил пакет фильтруется и не выпускается из системы наружу.
Здесь происходит обработка пакетов, которые попали на сервер с другой машины и ожидают дальнейшего переброса (актуальна для роутеров). Обычно на форвард ставится политика DROP, а в цепь записываются правила на доверенные машины (обязательно в оба направления). В этом случае маршрутник будет обрабатывать пакеты лишь с этих серверов.
Теперь вы знаете назначение цепей iptables. Тогда попробуем провести небольшую настройку iptables, после которой злоумышленник не сможет проникнуть на твой комп. Саму настройку лучше производить в он-лайн, т.к. в случае ошибки фаервол просто заблокирует все входящие соединения.
Для начала создадим собственную цепь. Назовем ее, например, ports. Туда мы будем записывать правила, разрешающие соединения на определенные порты твоей машины.
# /sbin/iptables -N ports
После этой команды появится пользовательская цепь ports. Ее можно просмотреть с помощью уже известного нам параметра -L. Теперь добавим первое правило в нашу новую цепь. Оно будет давать разрешение на соединение с 22 портом с доверенного адреса 192.168.0.1.
# /sbin/iptables -A ports -s 192.168.0.1 -p tcp --destination-port 22 -j ACCEPT
Коротко о параметрах и их аргументах:
-A (append). Добавляет правило в конец заданной цепи (в нашем случае в ports).
-s (source_addr) - адрес, с которого пришел пакет. В нашем случае это доверенный 192.168.0.1.
-p (protocol) - явное указание протокола для текущего правила. Может быть tcp, udp и icmp и all.
--destination-port - актуален только для протокола tcp, поэтому пишется всегда после него. Хранит в себе порт назначения.
-j - политика правила. Как я уже говорил, может быть ACCEPT, DROP, REJECT, а также линком на другие цепи.
Дальше попробуйте самостоятельно заполнить цепь ports. Если не сможете вспомнить про все порты, соединения по которым необходимо разрешить, то, не волнуясь, это можно сделать потом.
Теперь займемся главной цепочкой INPUT. Первым делом разрешим принимать пакеты по локальному петлевому интерфейсу. Интерфейс можно задать параметром -i (входящий) и -o (исходящий). Наше правило будет выглядеть следующим образом:
# /sbin/iptables -A INPUT -i lo -j ACCEPT
А теперь следует сделать то, к чему мы так стремились. Нам необходимо запретить все соединения кроме тех, которые были указаны в цепочке ports. Но перед этим следует выполнить, по крайней мере, две команды. Во-первых, надо соединить две цепочки: пользовательскую ports и главную INPUT. Делается это следующим образом:
# /sbin/iptables -A INPUT -j ports
Как видите, аргумент -j является именем пользовательской цепи (линковать базовые цепочки лучше не надо). Теперь, казалось бы, все должно работать и подчиняться правилам. Но стоит вам поменять политику, как ваша аська уйдет в офлайн, а любимый konqueror не сможет зайти ни на один сайт. Все потому, что мы забыли оговорить состояния пакетов.
Каждый пакет может иметь несколько состояний. Вот основные виды:
NEW - данные, начинающие новое соединение.
ESTABLISHED - пакет, приходящий от уже установленного соединения.
RELATED - новый пакет данных, но порожденный старым установленным соединением (например, FTP-передача данных, icmp-ответ и т.д.).
INVALID - состояние, которое не попадает ни под один из вышеперечисленных видов.
Чтобы пакеты корректно пропускались ядром, необходимо разрешить состояния RELATED и ESTABLISHED. Это выполняется командой:
# /sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
Значение параметра -m указывает на внешний модуль, который будет использоваться фаерволом. В нашем случае это iptables_state.so. После того, как модуль активизируется, мы указываем его опцию -state со значением состояний пакетов.
Кажется, всё! Осталось только сменить политику цепи INPUT:
# /sbin/iptables -P INPUT DROP
Если все было сделано верно, то после смены политики соединения не пропадут, а ваша машина будет в относительной безопасности ;).
Кстати, существует возможность производить сравнение не только по ip, но и по MAC-адресу, что положительно повлияет на защиту твоего сервера. Например, правило
# /sbin/iptables -A INPUT -s 192.168.0.1 -m mac --mac-source 00:C0:DF:10:19:FB -j ACCEPT
пропустит пакеты лишь с MAC-адресом 00:C0:DF:10:19:FB.
Пока я рассказал о способах фильтрации только tcp-пакетов. Теперь поговорим про icmp-протокол. Правила обработки таких пакетов должны содержать в себе параметр -p со значением icmp. Можно указывать тип пакета с помощью опции --icmp-type. Типы могут быть различными: echo-request, echo-reply и т.д. (полный список можно посмотреть командой /sbin/iptables -p icmp -h). Особый интерес представляет тип ответа на фильтрованные запросы. Например, ты с легкостью можешь сделать так, чтобы iptables отвечал пингующему, что твой узел недоступен либо permission denied (на кой фиг, ты, собственно, сюда пришел? ;)). Это осуществляется опцией --reject-with, значением которой будет, собственно, тип ответа на запрос. В итоге получаем правило:
# /sbin/iptables -A input -s ! 192.168.0.1 -p icmp --icmp-type echo-request -j REJECT --reject-with icmp-host-prohibited
Восклицательный знак, разделенный пробелом со значением параметра, означает, что правило распространяется на все пакеты, кроме тех, которые удовлетворяют данному параметру. В нашем случае, проброс icmp-пакетов с доверенного 192.168.0.1 будет разрешен.
Наверное, у вас не раз выпрашивали шелл. Конечно, давать доступ к своей машине – не самая приятная вещь. Мало ли чего там наделает эта компьютерная братия, плюс придется оплачивать трафик, который они нагенерят. Но не стоит отчаиваться. В решении этой задачи нам опять поможет iptables. Он имеет встроенный модуль iptables_owner.so, который может закрывать соединения по uid, gid, pid, cmd и прочим атрибутам пользователя. Как вы понимаете, модуль обрабатывает
OUTPUT-цепочку. Давайте, потренируемся. Заведем в системе тестового пользователя tables с уидом 4000:# /usr/sbin/useradd tables -s /bin/bash -u 4000
Наша задача: сделать так, чтобы пользователь не мог пользоваться Интернетом через твой шелл. Правило будет выглядеть следующим образом:
# /sbin/iptables -A OUTPUT -m owner --uid-owner 4000 -j REJECT
Логинимся под пользователем tables и пробуем соединиться по телнету куда-нибудь. Убеждаемся, что правило работает как надо.
А теперь представьте, что некий пользователь в сети подкинул тебе полезную информацию. В знак благодарности вы ему предоставляете
доступ к шеллу, но не желаете, чтобы у него была возможность запускать eggdrop-бота. Подобное реализуется такой вот командой:# /sbin/iptables -A OUTPUT -m owner --cmd-owner eggdrop -j REJECT
Теперь процесс, содержащий слово eggdrop, не сможет отправлять пакеты в сеть.
Iptables, как и ipchains, умеет организовывать маскарадинг (т.е. заменять локальный IP-адрес на глобальный). С помощью NAT можно пропустить в Интернет через свой сервер все машины из локальной сети. За NAT'инг отвечает модуль iptables_nat.so. В нем содержатся три цепи: PREROUTING, OUTPUT и POSTROUTING. В POSTROUTING записываются адреса, которым разрешено маскарадиться. Это происходит следующим образом:
# /sbin/iptables -t nat -A POSTROUTING -s 192.168.0.1 -j MASQUERADE
Вообще, для доступа к цепям NAT достаточно добавить к правилу параметр -t со значением nat. Чтобы осуществить редирект с одного порта на другой (допустим, насильно перенаправить пользователя с 80 на 3128 порт текущей машины), следует добавить в цепь PREROUTING следующую запись:
# /sbin/iptables -t nat -A PREROUTING -s 192.168.0.1 -p tcp --destination-port 80 -j REDIRECT --to-port 3128
После такой команды порт назначения 80 будет меняться на 3128, т.е. пользователи будут пользоваться WWW только через прокси-сервер (естественно, предварительно установленный на машине).
Весь трафик, прошедший через машину, фаервол записывает в контейнеры правил. Их можно просмотреть с помощью опции -v (verbose). Iptables покажет количество пакетов и суммарный трафик, обработанный каждым правилом.
Иногда возникает необходимость периодического обнуления контейнеров. Это реализуется командой:
# /sbin/iptables -Z цепь
Где "цепь" - имя цепочки, которую надо обнулить.
Чтобы корректно сохранить настройки фаервола, необходимо выполнить команду service iptables save. Все правила запишутся в файл /etc/sysconfig/iptables и подгрузятся при следующем запуске компьютера. Если ты сделал что-то неверно, команда service iptables reload загрузит старые правила из этого же файла.
Убедись, что iptables находится в автозапуске. Для этого выполни команду chkconfig --list | grep iptables. Если iptables отобразится, значит, все ок.
Подведем итог. Цель достигнута - мы получили достаточно информации, чтобы грамотно настроить фаервол iptables. Если хотите продолжить изучение этого брандмауэра, то введите команду man iptables. Руководство на несколько страниц на английском языке опишет вам все модули, правила и параметры фаервола.
Вот небольшой список базовых опций фаервола, который поможет выполнить то или иное действие:
-P политика цепь - сменить политику указанной цепи.
-N цепь - создать новую пользовательскую цепочку.
-D цепь [правило] - удалить всю цепь или определенное правило в ней.
--line-numbers - посмотреть номера правил в цепи.
-n - не преобразовывать IP-адреса в хосты.
-L [цепь] - просмотреть правила в указанной цепи.
-F [
цепь] - удалить все правила в цепи либо очистить все цепочки.О классификации брандмауэров можно говорить часами. Помимо программных, бывают также аппаратные фаерволы - отдельные компьютеры, которые ставятся на входе в защищаемую сеть и имеют свое ПО. Как правило, никаких функций, кроме фильтрации данных, такие железки не выполняют.