Фильтрация пакетов в Linux

ArticleCategory:

System Administration

AuthorImage:

Vincent Renardias

TranslationInfo:[Author and translation history]

original in fr: Vincent Renardias

fr to en Georges Tarbouriech

en to ru Воронин Леонид

AboutTheAuthor

Пользователь GNU/Linux с 1993, Винсент Ренардиас (Vincent Renardias) начал увлекаться его разработкой в 1996: Разработчик Debian, Французский переводчик программы GIMP и рабочего стола GNOME, основатель группы пользователей Linux User Group в Марселе (PLUG)... Теперь, управляющий компании R&D EFB2, он продолжает содействие GNU/Linux.

Abstract

Данная статья впервые была опубликована в специальном выпуске Linux Magazine France, сосредоточенном на безопасности. Редактор, авторы и переводчики любезно позволили LinuxFocus публиковать все статьи из этого специального выпуска. Соответственно LinuxFocus передаст их вам сразу же после перевода на английский. Спасибо всем, кто вовлечен в эту работу. Данное резюме будет воспроизведено во всех статьях, имеющих то же происхождение.


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

ArticleIllustration:[Das Titelbild des Artikels, do not translate]

[Illustration]

ArticleBody:[Der eigentliche Artikel. Überschriften innerhalb des Artikels sollten h2 oder h3 sein.]

Шлюз, Arp-Проски или сетевой мост?

Механизм фильтрации может быть рассмотрен как сеть, которая будет задерживать некоторые нежелательные пакеты. Наиболее важно найти правильный размер петли (ячейки сети) и правильное место для установки сети.

Расположение брандмауэра в сети
Firewall location

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

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

- Шлюз "ARP-Прокси": предыдущая конфигурация подразумевает деление сети на две подсети, которые приводят к потере половины доступных для сети IP адресов. Это немного раздражает. Например, из 16-ти адресной подсети (с 28 битной маской подсети), только 14 доступны, с тех пор как используются адрес сети и широковещательный адрес. Добавляя ещё один бит в маску подсети, мы уменьшаем доступные адреса с 14 до 6 (8 адресов за вычетом адреса сети и широковещательного адреса). Когда вы не можете допустить потери половины доступных IP-адресов, вы можете использовать данное решение, которое объясняется далее в этой статье. Кроме того, данное решение не требует каких-либо изменений в настройке сети ни на маршрутизаторе, ни на защищаемых компьютерах.

- Мост Ethernet: устанавливая шлюз Ethernet (не IP шлюз), делают механизм фильтрации невидимым с других компьютеров. Такая конфигурация может быть выполнена без назначения IP адресов Ethernet-интерфейсам. В таком случае, компьютеры невозможно обнаружить при помощи ping, traceroute и т.п. Следует заметить, что выполнение фильтрации пакетов в такой конфигурации требует ядра версии 2.2.x, а перенос данной функции на ядра версии 2.4.x пока не закончен.

Простейшие правила фильтрации

Теперь, когда мы знаем где установить наш фильтр, мы должны определить, что он должен будет блокировать или что он должен будет пропускать.
Есть два пути настройки такого фильтра:

- Первый, хороший: задерживаем все пакеты, кроме тех, которые соответствуют правилам.
- Второй, плохой: (но к сожалению, часто используемый) явно запрещенные пакеты задерживаются, а все остальные пропускаются.

Это просто объясняется: В первом случае, забывание (нарушение) правил приводят к нарушению работы службы или полной утере работоспособности. Обычно это быстро выявляется и проидводится добавление правил, достаточных для возобновления работы.
Во втором случае, забывание (нарушение) правил создает потенциальную уязвимость, которую часто очень сложно выявить... если можно вообще.

Netfilter

Наиболее часто используемое программное обеспечение для фильтрации пакетов в Linux - это Netfilter; эта приятная замена 'ipchains', используемой в Linux с ядром 2.2. Netfilter сделан из двух частей: поддержка ядра, которая должна быть скомпилирована в вашем ядре и команды 'iptables' которые должны быть доступны в вашей системе.

Пример настройки

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

Автор отдает предпочтение дистрибутиву Debian для настройки такой системы, но аналогично может быть настроен любой другой дистрибутив.

Во-первых, проверим, что ваше ядро поддерживает Netfilter. Если это так, то загрузочная запись должна содержать:

ip_conntrack (4095 buckets, 32760 max)
ip_tables: (c)2000 Netfilter core team

Иначе, вам придется перекомпилировать ядро после активизации поддержки Netfilter. Соответствующие опции могут быть найдены в подменю "Network Packet Filtering" меню "Networking Options". Выберите необходимые опции в секции "Netfilter Configuration". Если вы сомневаетесь, можете выбрать все опции, кроме того, лучше включить Netfilter в ядро и не использовать модули. Если по каким-то причинам один из модулей Netfilter был пропущен или не загружен, фильтрация работать не будет и мы лучше не будем говорить о риске, который подразумевается в данном случае.

Вы так же можете установить пакет 'iproute2' (последнее не обязательно, но наш пример будет использовать данный пакет, так как данный пакет позволяет сделать конфигурационный скрипт (сценарий) проще). В дистрибутиве Debian, для установки пакета 'iproute2' достаточно набрать команду 'apt-get install iproute'.
В других дистрибутивах, найдите соответствующие пакеты. Установить их можно обычным путем или из исходных кодов, которые можно загрузить со следующего адреса:
ftp://ftp.inr.ac.ru/ip-routing/

Теперь должны быть сконфигурированы две Ethernet карты. Мы должны обратить ваше внимание на то, что ядро Linux, когда производит автоопределение оборудования, останавливает поиск сетевых карт как только найдет первую. Соответственно, определится только первая.
Легкое решение этой проблемы состоит в добавлении следующей строки в файл lilo.conf:
append="ether=0,0,eth1"

Теперь мы должны настроить Ethernet-интерфейсы. Выбранный нами метод позволяет использовать один и тот же IP-адрес для обоих плат, сохраняя, таким образом, один адрес.
Допустим, что у нас есть подсеть 10.1.2.96/28, адреса которой начинаются с 10.1.2.96 по 10.1.2.111 включительно. Маршрутизатор будет иметь адрес 10.1.2.97, а наш компьютер для фильтрации - 10.1.2.98. Интерфейс eth0 будет подключен к маршрутизатору через соединительный кабель RJ-45, если обе карты соединены напрямую, без использования хаба (hub) или свитча (switch); Интерфейс eth1 будет подключен к хабу/свитчу, а оттуда - к компьютерам локальной сети.

Соответственно, оба интерфейса будут сконфигурированы со следующими параметрами:

address  : 10.1.2.98
netmask  : 255.255.255.240
network  : 10.1.2.96
broadcast: 10.1.2.111
gateway  : 10.1.2.97

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

net.vars: configuration variables

PREFIX=10.1.2
DMZ_ADDR=$PREFIX.96/28
# Interface definitions
BAD_IFACE=eth0
DMZ_IFACE=eth1
ROUTER=$PREFIX.97


net-config.sh: network configuration script

#!/bin/sh
# Comment out the next line to display the commands at execution time
# set -x
# We read the variables defined in the previous file
source /etc/init.d/net.vars
# We remove the present routes from the local network
ip route del $PREFIX.96/28 dev $BAD_IFACE
ip route del $PREFIX.96/28 dev $DMZ_IFACE
# We define that the local network can be reached through eth1
# and the router through eth0.
ip route add $ROUTER dev $BAD_IFACE
ip route add $PREFIX.96/28 dev $DMZ_IFACE
# We activate Proxy-ARP for both interfaces
echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp
# We activate the IP forwarding to allow the packets coming to one card
# to be routed to the other one.
echo 1 > /proc/sys/net/ipv4/ip_forward 

Теперь, давайте вернемся к требуемому механизму ARP-прокси для нашей конфигурации.
Для того чтобы один компьютер мог "общаться" с другим в той же сети, ему необходимо знать Ethernet адрес (или MAC адрес или аппаратный адрес), сообщаемый его IP-адресу. Тогда компьютер-источник отправляет запрос: "Какой MAC-адрес интерфейса, имеющего IP-адрес 1.2.3.4 ?" и компьютер-приемник должен ответить.

Вот пример такого "общения", обнаруженного при помощи tcpdump:
- Запрос: компьютер 172.16.6.72 спрашивает MAC-адрес, передаваемый IP-адресу 172.16.6.10.
19:46:15.702516 arp who-has 172.16.6.10 tell 172.16.6.72
- Ответ: компьютер 172.16.6.10 предоставляет свой номер сетевой карты.
19:46:15.702747 arp reply 172.16.6.10 is-at 0:a0:4b:7:43:71

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

На данном уровне, вы должны иметь работающую сеть с компьютером, управляющим всем трафиком между локальной и внешней сетью.

Теперь, мы должны настроить фильтрацию используя Netfilter.
Netfilter позволяет действовать непосредственно на поток пакетов. В простейшей конфигурации, пакеты управляются тремя цепочками правил:
- INPUT: для пакетов, входящих через интерфейс,
- FORWARD: для всех пакетов, передающихся от одного интерфейса к другому,
- OUTPUT: для пакетов, выходящих через интерфейс.

Команда 'iptables' позволяет добавлять, изменять и удалять правила в каждой из этих цепочек для изменения поведения фильтрации.
Кроме того, каждая цепочка имеет политику по умолчанию, которая определяет действия в случае, когда пакет не соответствует ни одному правилу в цепочке.

Четыре наиболее распространенных правила - это:
- ACCEPT: пакету позволено проходить,
- REJECT: пакет отклоняется и посылается пакет, связанный с ошибкой (ICMP Port Unreachable, TCP RESET, в зависимости от ситуации),
- LOG: Примечание пакета пишется в системный журнал,
- DROP: Пакет игнорируется и ответ не посылается.

Проход пакетов через стандартные цепочки

Packet flow

Вот главные опции iptables, позволяющие управлять цепочками. Мы детализируем их позже:

-N: создает новую цепочку.
-X: удаляет пустую цепочку.
-P: изменяет политику цепочки по умолчанию.
-L: выводит список правил в цепочке.
-F: сбрасывает все правила в цепочке.
-Z: очищает байты и счетчики пакетов, прошедших через цепочку.

Для изменения цепочки доступны следующие команды:
-A: добавляет правило в конец цепочки.
-I: вставляет новое правило в заданную позицию в цепочке.
-R: заменяет заданное правило в цепочке.
-D: удаление правила в цепочке, используя либо номер правила, либо его описания.

Давайте рассмотрим маленький практический пример: мы заблокируем ping-ответы (это тип ICMP-пакетов 'echo-reply'), идущие от заданного компьютера.
Сначала удостоверимся, что заданный компьютер "пингуется" (т.е. отвечает на команду ping):

# ping -c 1 172.16.6.74
PING 172.16.6.74 (172.16.6.74): 56 data bytes
64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms

--- 172.16.6.74 ping statistics ---

1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.6/0.6/0.6 ms
Теперь, добавим правило (которое прервет ICMP-ответ) в INPUT-цепочку ('-p icmp --icmp-type echo-reply') для пакетов, идущих с компьютера 172.16.6.74 ('-s 172.16.6.74'). Эти пакеты будут проигнорированы ('-j DROP').
# iptables -A INPUT -s 172.16.6.74 -p icmp --icmp-type echo-reply -j DROP

Теперь, давайте снова "пинганем" этот компьютер:

# ping -c 3 172.16.6.74
PING 172.16.6.74 (172.16.6.74): 56 data bytes

--- 172.16.6.74 ping statistics ---

3 packets transmitted, 0 packets received, 100% packet loss

Как мы и могли ожидать, пакеты не прошли. Мы можем проверить, что три пакета были заблокированы (3 пакета или 252 байта):

# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 604K packets, 482M bytes)
 pkts bytes target     prot opt in    out     source       destination
  3   252   DROP       icmp --  any   any     172.16.6.74    anywhere

Чтобы вернуть все как было, нам надо только удалить первое правило из цепочки INPUT:

# iptables -D INPUT 1

Теперь, PING заработает снова:

# ping -c 1 172.16.6.74
PING 172.16.6.74 (172.16.6.74): 56 data bytes
64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms

--- 172.16.6.74 ping statistics ---

1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.6/0.6/0.6 ms
#

Работает!

Вы можете добавить другие цепочки к трем изначально существующим (которые вы не сможете удалить в любом случае) и сделать часть трафика проходящим через них. Например, может быть полезным избегать дублирования правил в различных цепочках.

Теперь, давайте настроим требуемые правила для минимального брандмауэра. Он будет позволять ssh, службу доменных имен (DNS), службы http и smtp и ничего больше.
Для упрощения, команды настройки записаны в сценарий оболочки (скрипт), чтоб сделать конфигурацию проще. Сценарий начнет очищать текущую конфигурацию перед установкой новой. Эта маленькая уловка позволяет выполняться скрипту при активной конфигурации без риска дублирования правил.

rc.firewall

#!/bin/sh

# Flushing out the rules
iptables -F
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD


# The chain is built according to the direction.
# bad = eth0 (outside)
# dmz = eth1 (inside)
iptables -X bad-dmz
iptables -N bad-dmz
iptables -X dmz-bad
iptables -N dmz-bad
iptables -X icmp-acc
iptables -N icmp-acc
iptables -X log-and-drop
iptables -N log-and-drop

# Specific chain used for logging packets before blocking them
iptables -A log-and-drop -j LOG --log-prefix "drop "
iptables -A log-and-drop -j DROP

# The packets having the TCP flags activated are dropped
# and so for the ones with no flag at all (often used with Nmap scans)
iptables -A FORWARD -p tcp --tcp-flags ALL ALL -j log-and-drop
iptables -A FORWARD -p tcp --tcp-flags ALL NONE -j log-and-drop

# The packets coming from reserved addresses classes are dropped
# and so for multicast
iptables -A FORWARD -i eth+ -s 224.0.0.0/4 -j log-and-drop
iptables -A FORWARD -i eth+ -s 192.168.0.0/16 -j log-and-drop
iptables -A FORWARD -i eth+ -s 172.16.0.0/12 -j log-and-drop
iptables -A FORWARD -i eth+ -s 10.0.0.0/8 -j log-and-drop

# The packets belonging to an already established connexion are accepted
iptables -A FORWARD -m state --state INVALID -j log-and-drop
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# The corresponding chain is sent according to the packet origin
iptables -A FORWARD -s $DMZ_ADDR -i $DMZ_IFACE -o $BAD_IFACE -j dmz-bad
iptables -A FORWARD -o $DMZ_IFACE -j bad-dmz
# All the rest is ignored
iptables -A FORWARD -j log-and-drop

# Accepted ICMPs
iptables -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-request -j ACCEPT
iptables -A icmp-acc -p icmp --icmp-type echo-reply -j ACCEPT
iptables -A icmp-acc -j log-and-drop

# Outside -> Inside chain
# mail, DNS, http(s) and SSH are accepted
iptables -A bad-dmz -p tcp --dport smtp -j ACCEPT
iptables -A bad-dmz -p udp --dport domain -j ACCEPT
iptables -A bad-dmz -p tcp --dport domain -j ACCEPT
iptables -A bad-dmz -p tcp --dport www -j ACCEPT
iptables -A bad-dmz -p tcp --dport https -j ACCEPT
iptables -A bad-dmz -p tcp --dport ssh -j ACCEPT
iptables -A bad-dmz -p icmp -j icmp-acc
iptables -A bad-dmz -j log-and-drop

# Inside -> Outside chain
# mail, DNS, http(s) and telnet are accepted
iptables -A dmz-bad -p tcp --dport smtp -j ACCEPT
iptables -A dmz-bad -p tcp --sport smtp -j ACCEPT
iptables -A dmz-bad -p udp --dport domain -j ACCEPT
iptables -A dmz-bad -p tcp --dport domain -j ACCEPT
iptables -A dmz-bad -p tcp --dport www -j ACCEPT
iptables -A dmz-bad -p tcp --dport https -j ACCEPT
iptables -A dmz-bad -p tcp --dport telnet -j ACCEPT
iptables -A dmz-bad -p icmp -j icmp-acc
iptables -A dmz-bad -j log-and-drop

# Chains for the machine itself
iptables -N bad-if
iptables -N dmz-if
iptables -A INPUT -i $BAD_IFACE -j bad-if
iptables -A INPUT -i $DMZ_IFACE -j dmz-if

# External interface
# SSH only accepted on this machine
iptables -A bad-if -p icmp -j icmp-acc
iptables -A bad-if -p tcp --dport ssh -j ACCEPT
iptables -A bad-if -p tcp --sport ssh -j ACCEPT
ipchains -A bad-if -j log-and-drop

# Internal interface
iptables -A dmz-if -p icmp -j icmp-acc
iptables -A dmz-if -j ACCEPT

Несколько слов о качестве обслуживания. Linux может модифицировать поле ToS ("тип сервиса") и изменять его значения, чтобы дать пакетам различные приоритеты. Например, следующая команда изменяет исходящие SSH пакеты для улучшения отклика соединения.

iptables -A OUTPUT -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay

Тем же путем, для FTP соединений, вы можете использовать опцию '--set-tos Maximize-Throughput' для улучшения скорости передачи.

Вот и всё. Теперь, вы знаете основы настройки системы фильтрации пакетов. Однако, имейте ввиду, что брандмауэр - не панацея, когда беспокоит безопасность. Это всего лишь ещё одна предосторожность. Установка брандмауэра не освобождает вас от использования хороших ("сильных") паролей, самых последних патчей по безопасности, систем обнаружения вторжений и т.д.

Ссылки на дополнительные ресурсы