1

Автор: Кузнецов Константин

[size=7]Брандмауэр - внешняя защита компьютера (iptables)[/size]

План:
1. Введение
2. Описание работы файервола
3. Управление файерволом с помощью iptables
4. Скрипт для автоматической установки правил
5. Используемые и рекомендуемые источники

------------------------------------------------------------------------------------------

[size=6]1. Введение[/size]

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

------------------------------------------------------------------------------------------

[size=6]2. Описание работы файервола[/size]

Наша задача - установить политику обработки сетевых пакетов по умолчанию в положение "не пропускать", и добавить минимальный набор правил, разрешающий ходить только определенным пакетам.

Немного теории
Принцип работы такой: на наш сервер тем или иным способом попадает сетевой пакет, который нужно отклонить, принять и обработать, перенаправить, изменить или просто ничего не делать. То же самое происходит и с исходящими пакетами. Другими словами, в руки нашего файервола попадает пакет, с которым надо что-то делать. Файервол идет в список инструкций, пробегает по нему, пока не найдет подходящую по критериям к нашему пакету инструкцию, и применяет к нему определенную политику.
Какие критерии могут быть - конечно же, соответствующие информации, идущей с сетевым пакетом:

  • Протокол (-p)
    Ip-адрес отправителя (-s)
    Порт отправителя (--sport)
    Ip-адрес получателя (-d)
    Порт получателя (--dport)
    Состояние (новый, ответный и т.п.) (-m state --state)
    На какой интерфейс пришло (-i)
    С какого интерфейса уходит (-o)
    и прочее

Полученный файерволом пакет проходит некоторые цепочки правил, в зависимости от этих данных.
Таблиц с цепочками всего 3:
Таблица mangle, её цепочки:

  • PREROUTING
    INPUT
    FORWARD
    OUTPUT
    POSTROUTING

Таблица nat, её цепочки:

  • PREROUTING
    OUTPUT
    POSTROUTING

Таблица filter, её цепочки:

  • INPUT
    FORWARD
    OUTPUT

В данном разделе мы будем рассматривать упрощенный вариант: только таблицу filter, цепочки INPUT и OUTPUT.
Входящий пакет проходит filter INPUT. Исходящий, соответственно, filter OUTPUT.
Действий, которые совершаются над пакетами (политики), довольно много, мы будем использовать следующие:

  • Пропустить/разрешить (ACCEPT)
    Отбросить без уведомления (DROP)
    Отбросить с уведомлением (REJECT)

Помимо этих действий в правилах цепочек есть еще политика по-умолчанию на цепочку. То есть, если информация пакета не подошла ни под один из критериев, описанных нами в цепочке файервола, то к нему применяется политика по умолчанию.
Важное замечание: если пакет попал в ту или иную цепочку и по своим критериям подошел к какому-либо правилу, то после осуществления файерволом политики правила над пакетом, пакет выходит из цепочки и остальные правила уже на него не действуют. Это означает, что очередность правил в цепочке имеет важную роль.
Еще одно важное замечание: не забывайте, что для соединения двух компьютеров по сети необходимо как минимум 2 пакета - запрос и ответ. Таким образом, для того, чтобы компьютер имел доступ к серверу, в файерволе на компьютере надо разрешить исходящий трафик на сервер, и входящий трафик с сервер.

------------------------------------------------------------------------------------------

[size=6]3. Управление файерволом с помощью iptables[/size]

Обычно, для настройки той или иной утилиты в ОС Linux достаточно изменить её файл конфигурации и перезагрузить её. Но это не наш случай. У утилиты iptables нет своего конфигурационного файла и ей можно управлять исключительно выполняя команды из консоли. Команда имеет следующий вид:

iptables [ -t ТАБЛИЦА ] ДЕЙСТВИЕ ЦЕПОЧКА [НОМЕР] КРИТЕРИЙ1 [ КРИТЕРИЙ2 КРИТЕРИЙ3 ... ] -j ПОЛИТИКА [ ОПЦИИ ] 

В квадратных скобках обозначены не обязательные параметры. Если не указать таблицу, то выбирается таблица filter, как раз то, что нам нужно. Опции мы не будем использовать в этой главе. Действия могут быть такими:

  • Добавить правило в конец цепочки (-A)
    Удалить правило из цепочки (-D), можно указать номер правила в цепочке, а можно и само правило
    Добавить правило в цепочку (-I), необходимо указать после имени цепочки номер правила, перед которым оно встанет
    Установить политику по-умолчанию (-P). Для этого КРИТЕРИЙ и -j указывать не нужно.

Просмотр состояния файервола выполняется так: iptables -nvL (по таблице FILTER) или iptables -t nat -nvL (по таблице NAT)
L - LISTING - вывод информации
n - чтобы вывод был только числовой, без перевода ip в доменное имя, портов в их названия и т.п.
v - чтобы вывод был более информативным (verbose)

Предостережение
По своему опыту скажу Вам, что не стоит бездумно играть с файерволом, подключившись к нему удаленно. Так можно закрыть доступ к нашему серверу, сразу же вылететь из него и не мочь потом к нему подключиться. Из этого следует шаг №1.

  • Шаг №1 - обезопасить своё соединение с удаленным сервером от его обрыва настраиваемым файерволом. Еще можно сделать так: прежде чем добавить правило, запланировать отключение файервола через 10 минут, но это мы рассматривать не будем.
    Шаг №2 - установить политики по-умолчанию для всех цепочек в DROP (отбрасывать без уведомления).
    Шаг №3 - по очереди добавлять правила, разрешая тот или иной необходимый трафик.

Причем, чем конкретнее будут описаны критерии правил, тем безопаснее будет настроен наш файервол.

Разрешаем ssh-доступ к серверу
Какими критериями мы можем манипулировать:
Протокол - tcp
Порт получателя - 22
IP-адрес получателя - адрес нашего сервера 192.168.0.1
IP-адрес отправителя - наш адрес 192.168.0.2
Наше правило будет выглядеть так:

iptables -A INPUT -p tcp -d 192.168.0.1 -s 192.168.0.2 --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp -s 192.168.0.1 -d 192.168.0.2 --sport 22 -j ACCEPT

Все очень просто. Результат можно сразу посмотреть iptables -nvL

Устанавливаем политики по-умолчанию на "отбрасывание"
Если мы все сделали правильно, то можно приступать к блокировке политик по-умолчанию:

iptables -P INPUT DROP
iptables -P OUTPUT DROP

После чего отключаемся и пытаемся зайти на наш сервер вновь. Если это нам удалось, то я Вас искренне поздравляю.
Что мы получили: сервер, у которого открыт на прием только 22 порт протокола tcp и только для компьютера 192.168.0.2 плюс на отдачу только с 22 порта протокола tcp и только для компьютера 192.168.0.2. Очень защищенный сервер. Далее по аналогии можно открывать/закрывать те или иные соединения.

Важное замечание
Обратите внимание на особенности некоторых соединений, а именно: ftp и pptp (vpn).
Раньше я думал, что для соединения по протоколу FTP необходимо два tcp порта: 20 и 21. Как оказалось, не все так просто. При соединении на этих портах сервер и клиентская машина "созваниваются" и договариваются, на каком порту они будут работать дальше. То есть мы этого не можем знать заранее. Как же быть? У пакетов могут быть различные состояния, которые и могут нам помочь.
NEW. Признак NEW сообщает о том, что пакет является первым для данного соединения. Это означает, что это первый пакет в данном соединении, который увидел модуль трассировщика. Например если получен SYN пакет являющийся первым пакетом для данного соединения, то он получит статус NEW. Однако, пакет может и не быть SYN пакетом и тем не менее получить статус NEW. Это может породить определенные проблемы в отдельных случаях, но может оказаться и весьма полезным, например когда желательно "подхватить" соединения, "потерянные" другими брандмауэрами или в случаях, когда таймаут соединения уже истек, но само соединение не было закрыто.
RELATED. Состояние RELATED одно из самых "хитрых". Соединение получает статус RELATED если оно связано с другим соединением, имеющим признак ESTABLISHED. Это означает, что соединение получает признак RELATED тогда, когда оно инициировано из уже установленного соединения, имеющего признак ESTABLISHED. Хорошим примером соединения, которое может рассматриваться как RELATED, является соединение FTP-data, которое является связанным с портом FTP control, а так же DCC соединение, запущенное из IRC. Обратите внимание на то, что большинство протоколов TCP и некоторые из протоколов UDP весьма сложны и передают информацию о соединении через область данных TCP или UDP пакетов и поэтому требуют наличия специальных вспомогательных модулей для корректной работы.
ESTABLISHED. Состояние ESTABLISHED говорит о том, что это не первый пакет в соединении. Схема установки состояния ESTABLISHED достаточна проста для понимания. Единственное требование, предъявляемое к соединению, заключается в том, что для перехода в состояние ESTABLISHED необходимо чтобы узел сети передал пакет и получил на него ответ от другого узла (хоста). После получения ответа состояние соединения NEW или RELATED будет изменено на ESTABLISHED.
INVALID. Признак INVALID говорит о том, что пакет не может быть идентифицирован и поэтому не может иметь определенного статуса. Это может происходить по разным причинам, например при нехватке памяти или при получении ICMP-сообщения об ошибке, которое не соответствует какому либо известному соединению. Наверное наилучшим вариантом было бы применение действия DROP к таким пакетам.
RELATED и ESTABLISHED - это как раз наш случай. Соединение на 20 и 21 портах tcp протокола, разрешенное нашим файерволом, инициировало новое соединение на других портах. Команды, разрешающие трафик, подходящий под эти критерии, будут такими:

iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

Но этого оказалось мало, нужно еще загрузить модуль ip_conntrack_ftp (новое имя - nf_conntrack_ftp)

modprobe nf_conntrack_ftp
echo nf_conntrack_ftp >> /etc/modules

Соединение по протоколу pptp (vpn) тоже имеет свои подводные камни. Идем в энциклопедию и видим:
«PPTP работает, устанавливая обычную PPP сессию с противоположной стороной с помощью протокола Generic Routing Encapsulation. Второе соединение на TCP-порту 1723 используется для инициации и управления GRE-соединением. PPTP сложно перенаправлять за сетевой экран, так как он требует одновременного установления двух сетевых сессий.»
Со вторым соединением все понятно - -p tcp --dport 1723 -j ACCEPT, а вот что это за GRE? Идем в /etc/protocols и видим
gre 47 GRE # General Routing Encapsulation
Обязательно нужно проверить, не закомментирована ли эта строчка (# в начале строки отсутствует). Хорошо, как нам теперь разрешить подключения по этому протоколу:

iptables -A INPUT -p 47 -j ACCEPT
iptables -A OUTPUT -p 47 -j ACCEPT

------------------------------------------------------------------------------------------

[size=6]4. Скрипт для автоматической установки правил[/size]

В данном примере я покажу, как можно написать скрипт, устанавливающий правила файервола. Все данные, необходимые для выполнения скрипта распределены для удобства на 3 файла: исходные данные, функции с правилами и запускной скрипт. Начнем с первого.
Создаем директорию /etc/iptables/ и в ней файл iptables.data. В этом файле мы опишем те необходимые данные, с которыми мы будем работать в скриптах файервола. Так будет намного удобнее адаптировать наш скрипт, например, при смене провайдера.

# Internet
INTIF="eth0"
INTIP="62.5.246.190"
INTMASK="255.255.255.240"
INTGW="62.5.246.189"
INTDNS1="62.5.246.105"
INTDNS2=$INTGW

# Localnet
LANIF="eth1"
LANIP="192.168.0.1"
LANMASK="255.255.255.0"
LAN="192.168.0.0/24"

# LoopBack
LOIF="lo"
LOIP="127.0.0.1"
LOMASK="255.0.0.0"
LO="127.0.0.0/8"

# Ports
SSH="22"
HTTP="80"
DNS="53"
SMTP="25"
POP3="110"
FTP="20:21"

Следующим будет файл с функциями /etc/iptables/iptables.rules

#!/bin/sh
ipt_clear()
{
echo -n " Clearing rules, stoping firewall"
$IPT -t filter -F
$IPT -t filter -X
$IPT -t nat -F
$IPT -t nat -X
}

start_nat()
{
$IPT -t nat -A POSTROUTING -o $INTIF -s $LAN1 -j MASQUERADE
}

start_wall()
{
echo -n " Closing ports"
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
success
}

start_nowall()
{
echo -n " Opening all ports"
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT
}


start_input_open()
{
# Open all ports for lo (127.0.0.0/8)
$IPT -A INPUT -s $LO -d $LOIP -i $LOIF -j ACCEPT

# Open all ports for localnet (192.168.2.0/24)
$IPT -A INPUT -s $LAN -d $LANIP -j ACCEPT

# ssh
$IPT -A INPUT -p tcp --sport 22 -j ACCEPT

# sshd
$IPT -A INPUT -p tcp -d $FTPIP --dport $SSH -j ACCEPT

# RELATED,ESTABLISHED
$IPT -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
}

start_output_open()
{
# Open all ports for lo (127.0.0.0/8)
$IPT -A OUTPUT -d $LO -s $LOIP -o $LOIF -j ACCEPT

# Open all ports for localnet (192.168.2.0/24)
$IPT -A OUTPUT -d $LAN -s $LANIP -j ACCEPT

# ssh
$IPT -A OUTPUT -p tcp --dport 22 -j ACCEPT

# sshd
$IPT -A OUTPUT -p tcp -s $FTPIP --sport $SSH -j ACCEPT
}

и так далее по образу и подобию.
А теперь создаем файл /etc/init.d/rc.iptables и редактируем его.

#!/bin/sh

DIR=/etc/iptables/
. $DIR/iptables.rules
. $DIR/iptables.data

case "$1" in
start)
start_wall
start_input_open
start_output_open
;;
stop)
start_nowall
;;
restart)
$0 stop
$0 start
;;
save)
iptables-save > /etc/iptables/rules-save
;;
load)
cat /etc/iptables/rules-save | iptables-restore
;;
status)
$IPT -L -n -v
;;
*)
echo -e "\n rc.iptables - firewall script"
echo " Usage:"
echo " rc.iptables start"
echo " rc.iptables stop"
echo " rc.iptables restart"
echo " rc.iptables save"
echo " rc.iptables load"
echo " rc.iptables status"
;;
esac

Сначала мы указали в скрипте, какие дополнительные файлы подключить. Без этого система выдаст нам ошибку "не знаю что за функция start_wall", равно как и остальные функции. После этого мы делаем выбор входного параметра. Любой скрипт можно запускать передав ему параметр или параметры опциями. Делается это так: /etc/init.d/somescript option1 option2 option3. В нашем случае мы хотим сделать так, чтобы запуск с опцией start запускал наш файервол, stop - останавливал, restart - перезапускал, save - сохранил, load - загрузил, status - показал состояние файервола. Работать с входными параметрами можно через сочетание символов $1 – первый входной параметр, $2 – второй, и так далее. При вводе опции load у нас выполняется комманда cat /etc/iptables/rules-save | iptables-restore, это означает, что сначала мы выводим содержимое файла, а затем перенаправляем его в другую комманду. После многочисленных проверок ставим скрипт в автозагрузку системы.

------------------------------------------------------------------------------------------

[size=6]5. Используемые и рекомендуемые источники[/size]

http://ru.wikipedia.org/wiki/Iptables
Руководство по iptables (Iptables Tutorial 1.1.19)