Добавить в избранное | Сделать стартовой страницей

Большая Linux библиотека для пользователей OS Linux и ПО для нее
Есть что сказать? Нужен совет? Посети наш форум.




Firewall в Linux (ipchains)

Автор : Сергей А. ЯРЕМЧУК

В настоящее время остро стоит проблема защиты информации в сети Интернет. Организации тратят огромные деньги на различные системы защиты, но это не всегда спасает. А что делать обычному пользователю, у которого нет таких средств, но зато есть желание защитить информацию от посторонних глаз? Защитить свой компьютер специальными программными средствами.

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

Один из способов защиты от несанкционированного доступа является firewall (брандмауэр или межсетевой экран) - устройство или программа, предназначенная для фильтрации определенного вида сетевого трафика. Делается это с целью уменьшения вероятности проникновения из одной части сети (незащищенной) в другую (защищенную), а также с целью ограничения доступа из внутренней сети к ненужным ресурсам внешней (ну скажите, зачем в обычном офисе доступ к чатам и развлекательным ресурсам Web). Попутно такие программы могут обеспечивать блокировку рекламы и активного содержания Web-страниц.

Одним из вариантов атаки является негласная установка различных программ для удаленного управления или кражи паролей с компьютера жертвы (слово троян, я думаю, знакомо многим) или более "легальный" вариант - spyware, бесплатные программы, которые, как правило, собирают информацию о посещаемых страницах, ваших интересах и отправляют ее на сайт разработчика. С помощью firewall'a можно без проблем отфильтровать ненужный трафик.

Как же работают межсетевые экраны? Вся связь в Интернет реализована посредством протокола TCP/IP, не требующего прямого физического соединения (здесь применяется т.н. логическое соединение). Передача информации происходит посредством передачи отдельных пакетов (датаграмм), каждая датаграмма является независимой единицей и с точки зрения протокола не имеет ничего общего с другими датаграммами, которыми обмениваются приложения (хотя само приложение следит за своими пакетами). Для установления соединения необходимо обменяться служебной информацией и при согласии двух сторон соединение считается установленным. Но чтобы датаграмма достигла адресата, каждый пакет должен содержать IP-адрес принимающей машины и номер порта который определяет какой программе обрабатывать данный пакет. А так как некоторые сервисы могут одновременно работать с несколькими компьютерами (www например), то в пакете должен содержаться также и адрес отправителя. В состав пакетов также входят т.н. АСК-биты (acknowledgement), которые подтверждают прием предыдущих пакетов по их отсутствию определяется установление нового сеанса связи (вообще то это не все, но этого достаточно для понимания процесса). Поэтому пакеты являющиеся частью уже установленного соединения проходят беспрепятственно, а остальные обрабатываются брандмауэром.

От чего же не может защитить брандмауэр? Самое первое, что приходит в голову, это подделка адреса отправителя. И в самом деле, контролируя DNS, или воспользовавшись одной из множества программ, запросто можно ввести брандмауэр в заблуждение. На более высоком уровне реализации атаки можно получить управление, попробовав подобрать значения ISN (Initial Seqence Number) которые формируются для каждого сеанса индивидуально, но благодаря особенностям реализации протокола в отдельно взятой ОС его практически без проблем можно вычислить (подобрать). И таким образом либо вклиниться в текущий сеанс, либо начать его от имени узла, которому защищаемый доверяет.

Так же злоумышленник может вполне легально разместить исполняемый код, например, на Web-странице - и, естественно, все пакеты, идущие оттуда будут пропущены. Я не говорю уже о таких особенностях протокола TCP/IP, как передача пароля в незашифрованном виде в таких сервисах, как telnet, ftp и других, что создает предпосылки для возможности их перехвата. И еще протокол TCP разбивает длинное сообщение на более короткие фрагменты и брандмауэры рассматривают корректность только первого из них, а остальные пропускают беспрепятственно, поэтому, послав датаграмму не содержащую информацию более высоких уровней, есть вероятность, что она будет принята как часть более длинного сообщения.

Теперь, когда мы разобрались с тем, что может, и что не может firewall, давайте разберемся с конкретной реализацией. Начать я предлагаю с ОС Linux. Почему? Да потому, что firewall поддерживается этой системой на уровне ядра, и пользователю необходимо только его настроить. При этом, конечно, много ручной работы, но в ходе задания правил фильтрации вы убедитесь, что это никакая не магия, и освоите процесс, на практике потрогаете всё, так сказать, своими руками.

Проверьте, есть ли у вас файл /proc/net/ip_fwchains, если есть, то ядро уже настроено для работы. А если нет, то необходимо пересобрать ядро и включить следующие параметры:

CONFIG_FIREWALL=y
CONFIG_IP_FIREWALL=y

Для настройки фильтрации в Linux с версии 2.2 применяется программа ipchains, до этого применялась программа ipfwadm, эти две программы полностью различаются по синтаксису. С версии 2.4.х правит бал утилита IPTABLES, но мы будем использовать ipchains, тем более, что различий между ними по синтаксису команд практически нет. К пакетам в данной программе применяется набор правил (цепочка). Небольшое уточнение: обрабатывается, как правило, только первый пакет, без него невозможно будет собрать все фрагменты. Действие правил коротко можно охарактеризовать так - если пакет совпадает с описанием, то вот что с ним нужно сделать. Каждой цепочке соответствует своя политика, что делать с пакетами по умолчанию, а затем следуют исключения из общих правил.

Существуют три встроенные в ipchains цепочки, которые должны быть всегда: input, forward, и output (рисунок 1).

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

· ACCEPT - пакет принимается
· DENY - пакет отбрасывается, отправитель думает, что пакет не дошел до места назначения
· REJECT - то же, что и DENY только отправителю отсылается ICMP сообщение о недоступности узла назначения
· MASQ - замаскарадить, можно использовать только если ядро собрано с соответствующим параметром
· REDIRECT - пакет переадресовывается на определенный порт
· RETURN - переходит в конец цепочки без дальнейших проверок

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

Далее пакет проверяется по правилам входной цепочки, если пакет не будет уничтожен или отвергнут, то следующим шагом, если необходимо, производится демаскарадинг (demasquerade) пакета и он поступает в выходную цепочку. Если демаскарадинг не производится, то ядро решает переслать пакет в local process, если пакет предназначен на на этот компьютер, или в цепочку forward после благополучного прохождения которой, пакет поступает в цепочку output и покидает машину. Этот шаг обработки пакетов называется маршрутизация (routing).

Пакеты, сгенерированные локальными процессами, проходят только этапы маршрутизации и выходную цепочку. Пакеты, сгенерированные локальными процессами и адресованные на локальный интерфейс (loopback), проверяются по выходной цепочке с интерфейсом lo, а затем по входной цепочке также с интерфейсом lo.
У программы ipchains довольно много параметров - все перечислять их я вам не буду, но с основными давайте познакомимся. Помните, что правила прохождения проверяются по порядку, и первое правило может завершить прохождение всей цепочки, поэтому начинать необходимо с простых правил, и на их основе создавать более сложные.

Итак, включаем фильтр пакетов:

echo 1 > /proc/sys/net/ipv4/ip_forward

Сначала давайте выясним версию, установленную на компьютере:

[root@grinder sergej]# /sbin/ipchains --version
ipchains 1.3.10, 1-Sep-2000

у меня установлен Red Hat 7.3 2002 года и, как видите, программа давно не обновлялась.

Теперь давайте проверим прохождение ICMP пакетов командой ping по внутреннему кольцу.

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=255 time=0.185 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% loss, time 0ms
rtt min/avg/max/mdev = 0.185/0.185/0.185/0.000 ms

теперь выполните следующую команду

/sbin/ipchains -A input -s 127.0.0.1 -p icmp -j DENY

попробуем еще раз

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
1 packets transmitted, 0 packets received, 100% packet loss

как видите, пакет не прошел. Что же мы сделали? -A (add) - добавили новое правило во входную цепочку input, после флага -s указывается исходный адрес (если -d, то это означает адрес назначения), сетевая маска или порт, адрес 0/0 используется по умолчанию и соответствует всем адресам. Флаг -р означает протокол, здесь можно использовать параметр all, означающий все протоколы, или применять логическое инвертирование "!", означающее "всё кроме". Так как icmp не использует никакие порты, то либо указывается имя icmp, либо номер типа. Последний можно узнать, если ввести /sbin/ipchains -h icmp (-h без указания типа просто выведет справку) и вы получите примерно такой список (сокращен):

Type Description
0 echo-reply (ping)
3 destination-unreachable
5 redirect
8 echo-request (ping)
11 time-exceeded (ttl-exceeded)

Как видите, программой ping используется 0 и 8 тип, тип 11 использует программа traceroute, 5 - маршрутизация, а по 3 типу передаются очень важные системные сообщения "destination-unreachable". Отсюда вывод: icmp пакеты - это не только ping, поэтому, полностью заблокировав их, вы можете сильно замедлить передачу данных, а тип 3 вообще не советую отключать.

Чтобы удалить правило, можно воспользоваться одним из двух вариантов:

# ipchains -D input 1

удаляет правило под номером 1 во входной цепочке, или

# ipchains -D input -s 127.0.0.1 -p icmp -j DENY

т.е просто заменили в -А на -D , такой вариант удобен, если вы не знаете номер или не хотите считать его. Если одинаковых правил несколько, то будет удалено только первое из них.

Исходный адрес и адрес назначения (после параметров -s и -d) может быть задан в одной из четырех формах:
· в виде символического имени (localhost, www.linux.org);
· в виде IP-адреса (127.0.0.1);
· в виде IP-адреса с маской в виде четырех десятичных чисел (192.168.0.0/255.255.255.0);
· в виде IP-адреса с битовой маской (192.168.0.0/24);

Последние два примера абсолютно идентичны по результату и означают все узлы в диапазоне от 192.168.0.0 по 192.168.0.255.

Флаги -s и -d, как и -р допускают инвертирование путем указания '!' перед параметром. Например, так можно указать все пакеты, кроме пришедших с localhost `-s ! localhost'. Протоколы могут указываться по номеру (см. файл /etc/protocols) или по имени, вот так можно указать на все протоколы кроме TCP - '-p ! TCP'.

Для протоколов UDP и TCP можно еще указать и номера портов в виде символического имени (например, www - cм. в /etc/services) или в виде десятичного номера или диапазона номеров, который обозначается знаком ':'. Например, 6000:6010 означает 11 портов в диапазоне от 6000 по 6010. Если опущена нижняя граница диапазона, то подразумевается 0 (например ':1024', означает все порты в диапазоне от 0 по 1024), аналогично пропущенная верхняя граница соответствует максимальному порту, т.е. 65535. По умолчанию подразумеваются все порты. Естественно, и здесь можно использовать инверсию - например, так выделяются пакеты TCP кроме пришедших на www (80 порт):

-p TCP -d 0.0.0.0/0 ! www или
-p TCP -d 0.0.0.0/0 ! 80

Заметьте, что условие

-p TCP -d ! 192.168.1.1 www

отличается от

-p TCP -d 192.168.1.1 ! www

Первое означает любой TCP-пакет на www-порт любой машины, кроме как на 192.168.1.1. Второе означает любой TCP-пакет на любой порт машины 192.168.1.1, кроме порта www.

А следующая запись означает любой TCP-пакет, кроме адресованных на любой порт машины 192.168.1.1 и кроме адресованных на www-порт любой машины.

-p TCP -d ! 192.168.1.1 ! www

Опция -i означает интерфейс. Интерфейсом для входящих пакетов (входная цепочка) является интерфейс, через который были получены пакеты, а для выходящих (выходная цепочка) - через который будут отправлены.
Для транзитных пакетов проверяемых по цепочке forward считается тот интерфейс, через который они будут отправлены. При проверке по пользовательской цепочке интерфейс определяется в зависимости от того, из какой встроенной цепочки она была вызвана.

При задании правил можно указывать отсутствующий на данный момент интерфейс - как только он появится, для него уже будут готовы правила. При задании интерфейсов возможно использование масок и инверсий. Так , '-i ppp+' означает все интерфейсы, имена которых начинаются с 'ppp' (даже не существующие), а '-i ! eth0' - все, кроме eth0.

Иногда необходимо разрешить создание соединений TCP только в одну сторону, но протокол TCP требует, чтобы пакеты проходили в обеих направлениях (подтверждение ранее принятых пакетов, например, без этого соединение попросту разорвется), поэтому фильтрация просто всех TCP пакетов только может навредить. Каждый пакет, являющийся запросом на соединение, содержит флаг SYN (FIN и ACK соответственно сброшены), вот для проверки этого условия существует флаг -у (напоминаю, он используется только с ТСР протоколом).

-p TCP -s 192.168.1.1 -y

отбирает все запросы на установку соединения с машины с адресом 192.168.1.1 .

Еще один момент, связанный с безопасностью. Так как на самом нижнем уровне модели OSI (эталон, описывающий взаимодействие протоколов в сети) - физическом, может находится любая аппаратура от разных производителей, (естественно, со своей скоростью передачи и пропускной способностью), то иногда получается, что длина пакета превышает максимально допустимую для передачи по некоторому каналу (MTU-maximum transfer unit). В этом случае пакеты разбиваются на несколько частей, т.е. фрагментируются, и каждый фрагмент посылается дальше отдельно. В точке приема (а промежуточные станции по умолчанию, даже если есть возможность, этого не проделывают) пакеты собираются обратно, т.е. дефрагментируются. Проблема состоит в том, что все данные, которые необходимы для проверки, содержатся только в первом пакете (порт отправителя, порт получателя, тип ICMP, код ICMP, TCP флаг SYN), так вот, раньше считалось, что отбросив только его, можно про остальные забыть, но известны случаи нарушения работы компьютеров путем посылки фрагментов.

Например, условия -p TCP -s 192.168.1.1 www как и -p TCP -s 192.168.1.1 ! www на втором и последующих пакетах попросту не сработают.

Так вот, если ваша машина является единственным шлюзом, соединяющим локальную сеть с Интернетом, то пересобрав ядро с параметром (CONFIG_IP_ALWAYS_DEFRAG), вы можете заставить дефрагментировать все проходящие пакеты. А с помощью флага -f можно указать правила для второго и следующих пакетов.

Например, с помощью следующего правила можно уничтожить все пакеты, поступающие на 192.168.1.1

# ipchains -A output -f -d 192.168.1.1 -j DENY

Если пакет соответствует условию, то действие, которое должно произойти с пакетом задается флагом -j (jump). О них я говорил выше.

Вот таким примерно условием можно отсеять пакеты посылаемые довольно известным трояном BackOriffice, если вы защищаете сеть с Windows-машинами:

# /sbin/ipchains -A output -j REJECT -i ppp0 -p udp -d 0/0 31337 -l
# /sbin/ipchains -A output -j REJECT -i ppp0 -p udp -d 0/0 31338 -l

А примерно так можно отсеять рекламные баннеры:

#/sbin/ipchains -A input -j REJECT -i ppp0 -p tcp -s server_ip_adress -d your_ip_adress

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

Как видите, такой подход может только увеличить загрузку страниц и часть ненужных нам пакетов все таки попадут в канал. Поэтому, что бы зарубить это все на корню, поменяем местами IP-адреса назначения и отправителя, т.е. правило будет выглядеть так:

#/sbin/ipchains -A input -j REJECT -i ppp0 -p tcp -s your_ip_adres -d server_ip_adress

в этом случае браузер, послав запрос, сразу же получает ответ, что узел назначения недостижим (поэтому здесь и используется REJECT, а не DENY) и на этом успокаивается, а сервер не получает запроса и остается в неведении о происходящем, так мы существенно ускорим загрузку документа и уменьшим нагрузку на канал. Но команда на загрузку банера, хотя это, по моему, и менее вероятно, может быть в принципе дана и с сервера (ASP, CGI и еще много чего там повыдумывали) поэтому первый вариант тоже имеет право на существование. И конечно же вы должны понимать, что если баннеры грузятся с того же узла, что и документ, то он благополучно пройдет все заслоны, но тут уж ничего не поделаешь.

Флаг -l означает, что такие пакеты необходимо регистрировать в системном журнале. Если нет никаких действий, то идет просто подсчет пакетов. Например,

ipchains -A input -s 192.168.0.1

который выводится командой ipchains -L -v. Применение флага -t позволяет манипулировать четырьмя битовыми флагами имеющимися в каждом IP-заголовке, называемыми TOS (Type Of Service) их значения иногда учитываюся маршрутизаторами и это может ускорить обработку пакетов на промежуточных станциях. Их названия и рекомендуемые значения приведены в таблице.

Название Типа Обслуживания: Значения параметров: Типичное применение:
Minimum Delay
минимальная задержка
0x01 0x10 ftp, telnet
Maximum Throughput
максимальная пропускная способность
0x01 0x08 ftp-data
Maximum Reliability
максимальная надежность
0x01 0x04 snmp
Minimum Cost
минимальная цена
0x01 0x02 nntp

Например, для telnet'a и устанавливающего соединение ftp - минимальная задержка, для получения данных ftp - максимальная пропускная способность.

# ipchains -A output -p tcp -d 0.0.0.0/0 telnet -t 0x01 0x10
# ipchains -A output -p tcp -d 0.0.0.0/0 ftp -t 0x01 0x10
# ipchains -A output -p tcp -s 0.0.0.0/0 ftp-data -t 0x01 0x08

Создать свою цепочку правил можно, воспользовавшись флагом -N (new):

# ipchains -N test

Удалить цепочку можно только в том случае, если она пустая (т.е. не содержит никаких правил) и на нее не ссылаются из других цепочек. Для удаления используется флаг -Х (почему Х, а потому, что все остальные буквы заняты, можно прикинуть примерное количество опций программы)

# ipchains -X test

Очистка цепочки (т.е. удаление из нее всех правил) производится командой '-F' (flush), например:

ipchains -F forward

Осторожно! Если имя цепочки не указано, то будут очищены все цепочки. Просмотр одной цепочки или всех сразу производится командой '-L' (list), например:

ipchains -L input

Вместе с флагом -L для удобства вывода информации можно использовать флаги: -n (numeric), -v (verbose), -x (expand numbers). Для сброса счетчиков применяется флаг -Z (zero).

Для того чтобы проверить правила, проще всего смоделировать несколько ситуаций и воспользоваться командой -С с заданием -s адреса и порта, -d адреса и порта, с заданием параметров -p и -i, список результатов теста можно вывести, задав параметр -v - таким образом можно увидеть, прошел пакет или нет.

Например, тестируем TCP SYN пакет от 192.162.1.1 по порту 60000 (X Window System) к 192.168.1.2 порт www, начиная от входной цепочки. Это классическое www соединение.

# ipchains -C input -p tcp -y -s 192.168.1.1 60000 -d 192.168.1.2 www

Еще два слова хочу сказать о подходе к фильтрации, их может быть два: все что не разрешено явно - запрещено, и наоборот, все что не запрещено - разрешено т.е. в первом случае ACCEPTим все необходимое, а все остальное - REJECTим или отDENYваем, во втором случае наоборот. Можно, естественно, смешивать эти два варианта - для входящих пакетов выбрать одну политику, а для исходящих другую. Решать вам.

Это в принципе все, что я хотел рассказать о firewall'е в Linux. Как видите, основным достоинством является полный контроль над происходящим, никакой зависимости от конкретной программы - что желаем, то пропускаем, а что ненужно, то соответственно отбрасываем. Недостаток такой реализации (а недостаток ли это вообще) вытекает из достоинства - необходимо иметь соответствующие знания, чтобы правильно все настроить, новичку, я думаю, это будет сделать сложновато, ведь необходимо хорошо разбираться не только в Linux, а и в принципах реализации различных протоколов Интернета.

Но прогресс не стоит на месте. В Интернете можно встретить большое количество скриптов, которые помогают несколько автоматизировать процесс настройки брандмауэра. Некоторые из них представленны и в документации IPCHAINS - HOWTO, Firewall-HOWTO. В этих же документах расписаны остальные рекомендуемые опции, которые необходимо включить при перекомпиляции ядра, приведены примеры и рассказано о других параметрах программы.

Еще по адресу http://www.ecst.csuchico.edu/dranch/Linux/index-linux.html вы можете найти поэтапное руководство по настройке всей системы (TrinityOS), а не только firewall, в нем очень хорошо расписан процесс создания безопасной системы со множеством примеров конфигурационных файлов, которые к тому же, используя различные переменные окружения, настраиваются автоматически и хорошо комментированы.

Их рекомендую посмотреть еще из-за того, что правила после перезагрузки надо перезаписывать заново, т.к. они не сохраняются, и, хотя есть специальные утилиты, лучше, по-моему, воспользоваться всё-таки скриптом. К тому же IP-адрес может быть, как это часто бывает, не постоянным, а так как в скриптах возможно использование переменных, то его можно получить с помощью программы ifconfig.

Также в последнее время в Интернете можно найти много различных графических firewalloв, но на поверку большинство (а мне другие еще и не попадались) front-end'ом к ipchains (или к iptables), а действительно - зачем изобретать велосипед и создавать что-то новое, если то, что есть, отлично работает. Например, в моем Red Hat 7.3 имеется утилита lokkit (рис.2), которая в стиле Wizarda позволяет, отвечая на вопросы, задать правила. Естественно, таким образом можно создать только общие правила, а остальное все равно придется делать конечному пользователю вручную.

Это всё - основные команды, касающиеся именно фильтрации пакетов. Я не касался вопроса маскарадинга (соединение нескольких компьютеров с Интернетом по одному каналу) с помощью данной программы, думаю домашнему пользователю этот вопрос менее интересен, а системные администраторы более подготовлены и разберутся сами, если в том будет необходимость. Как видите, применение команды не должно вызвать особых затруднений, если определиться, с политикой - т.е. какие пакеты отбрасывать и на каком этапе. Как видите, это никакая не магия, все научно обосновано и логично. Напоследок остается пожелать удачных фильтраций. Защищаться никогда не поздно. Linux forever...


Обсудить данную тему на нашем форуме "Все о Linux"