понедельник, 10 августа 2009 г.

Конфигурирование IPFilter на машине-роутере/форвардере

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

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

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

Именно в силу этих причин мне пришлось потратить достаточно много времени для разработки конфигурации машины-роутера, с достаточно специфической постановкой задачи:

1. Машина находится внутри ДМЗ и обеспечивает контролируемый доступ из сетей ДМЗ во внутреннюю сеть, которая, в свою очередь, должна быть изолирована как ДМЗ в ДМЗ.
2. В то же время, в эту внутреннюю сеть должен быть доступ из внешней ДМЗ по целому ряду сервисов, в числе которых присутствуют SSH, X11, при этом необходимо обеспечивать невозможность транзита целого ряда протоколов во внутреннюю сеть.
3. Внутренняя сеть должна иметь доступ на машину-роутер для доступа к определенным сервисам машины-роутера - TFTP, NFS, FTP, DNS, NTP. Дополнительно, внутренняя сеть должна иметь возможность контролируемого выхода в интернет, использования внешних служб DNS, и роутер должен иметь возможность селективного запрета доступа во внешние сети по определенным портам и протоколам (например, по HTTP).
4. Кроме того, что машина является роутером, она имеет не два подключенных порта, а три, при этом, на третьем порту имеется ряд сервисов, доступ к которым осуществляется из внешней ДМЗ и интернет, и, соответственно,данный порт должен иметь полноценную защиту.
5. Разумеется, большинство сервисов машины-роутера должны быть доступны лишь из прилегающих сетей.

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

Опыт написания конфигураций привел меня к нескольким основным принципам конфигурирования IPF (да и вообще любого брэндмауэра) на роутерах и форвардерах.

Перечислим эти принципы вкратце:

1. Внешний роутинговый и сервисный интерфейс конфигурируется по принципу "Все запрещено, разрешены лишь сервисные порты и порты роутинга". По сути, внешний интерфейс конфигурируется подобно бастионной машине, и отличается от конфигурации бастиона лишь некоторыми послаблениями.
2. Внутренний роутинговый интерфейс конфигурируется по принципу обратной стороны бастиона - "Разрешено практически все по пути на внешний интерфейс, лишь некоторые сервисы/хосты/сети блокируются". Не следует конфигурировать его как внешний интерфейс - прохождение пакетов сервисов и обратные сессии будут блокированы.
3. Дополнительные интерфейсы могут быть сконфигурированы и как бастион, и как роутер - в зависимости от потребности. Характер конфигурации определяется настройками роутинга/форвардинга.

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

Прежде, чем мы начнем, несколько пояснений. Данная конфигурация роутера с тремя интерфейсами, имеет следующие подключения:

# Router host
#
# Host with three interfaces:
# bge0 - external as 192.168.219.30/24 (athena)
# bge1 - internal as 192.168.219.31/24 (pallada)
# bge2 - external as 192.168.219.200/24 (zeus)

На интерфейсе bge0 присутствует трафик трех сетей - 219й (внутренней), 201й и 211й (внешних по отношению к внутренней), на интерфейсе bge1 полностью подключена 219я внутренняя сеть, интерфейс bge2 подключен внешним маршрутом к интернету и сконфигурирован как бастион (не является роутинговым). Машина сконфигурирована как статический роутер RIPv2, и является шлюзовой для доступа из сетей 201 и 211 в сеть 219.

Итак, первый блок - уже достаточно традиционный, блокирующий мусор и попытки сканирования fingerprint:

# ---------------------
# Common blocking rules
# ---------------------

# Block all IP fragments
block in quick all with frag

# Block all short IP fragments
block in quick proto tcp all with short

# Block any IP packets with options set in them
block in quick all with ipopts

# Block nmap OS fingerprint attempts
block in log first quick proto tcp from any to any flags FUP

Дабы разрешить прохождение служебных пакетов роутеров и разрешить транзит пакетов, обрабатываемых роутером, следом идет сответствующий блок (см. презентацию Glenn Brunette):

# Allow routing info
pass in quick proto udp from any to port=route
pass in quick proto icmp from any to any icmp-type 9 # Routeadvert
pass in quick proto igmp from any to any # Pass IGMP

Обратите внимание, что при использовании машины в качестве только форвардера, данный блок не является необходимым.

Далее конфигурации роутеров традиционно имеют разрешающий блок для loopback-интерфейса:

# Make sure the loopback allows packets to traverse it
# lo0 interface
pass in quick on lo0 all
pass out quick on lo0 all

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

# Rules groups setup
# Group 100 - Blocked networks and/or protocols/ports
# Group 100 setup
block in all head 100
# Group 200 - Opened incoming ports on bge0
# Group 200 setup
pass in on bge0 head 200
# Group 300 - Opened incoming ports on bge1
# Group 300 setup
pass in on bge1 head 300
# Group 400 - Opened incoming ports on bge2
# Group 400 setup
pass in on bge2 head 400
# Group 700 - Outgoing and callback sessions
# Group 700 setup
pass out all head 700

При использовании групп следует иметь в виду следующие тонкости:

1. Группа как правило привязывается к интерфейсу (хотя это не закон, и не привязанные группы правил имеют свои преимущества и могут использоваться исключительно для удобства).
2. При приходе пакета на интерфейс, пакет прогоняется через группы правил, привязанные к интерфейсу и проверяется на непривязанных правилах только в случае их наличия. Таким образом, чем меньше будет несгруппированных правил в конфигурации, тем меньше накладные расходы на обработку пакета и тем выше производительность файрвола.
3. Группы не могут содержать взаимоисключающих действий, например, одновременного сочетания pass и block либо не могут быть одновременно определены для различных интерфейсов.

Следующая группа правил позволяет пинговать интерфейсы, но только из двух внешних сетей и только пропуская пакеты ICMP ECHO REQUEST и ICMP ECHO REPLY:

# Pass ICMP Echo on bge0 from internal networks
# bge0 interface
pass in quick on bge0 proto icmp from 192.168.201.0/24 to 192.168.219.0/24 icmp-type echo group 200
pass in quick on bge0 proto icmp from 192.168.211.0/24 to 192.168.219.0/24 icmp-type echo group 200
pass out quick on bge0 proto icmp from 192.168.219.0/24 to any icmp-type echorep
# Pass ICMP Echo on bge1 from internal networks
# bge1 interface
pass in quick on bge1 proto icmp from 192.168.201.0/24 to 192.168.219.0/24 icmp-type echo group 300
pass in quick on bge1 proto icmp from 192.168.211.0/24 to 192.168.219.0/24 icmp-type echo group 300
pass out quick on bge1 proto icmp from 192.168.219.0/24 to any icmp-type echorep
# Pass ICMP Echo on bge2 from internal networks
# bge2 interface
pass in quick on bge2 proto icmp from 192.168.201.0/24 to 192.168.219.200/24 icmp-type echo group 400
pass in quick on bge2 proto icmp from 192.168.211.0/24 to 192.168.219.200/24 icmp-type echo group 400
pass out quick on bge2 proto icmp from 192.168.219.0/24 to any icmp-type echorep

Мы не открываем ICMP отовсюду, а только и исключительно из интрасети. Разумеется, совсем по хорошему было бы и ответные правила echorep сделать лишь в сторону интрасети (так было бы более безопасно), однако это ощутимо увеличивает количество правил и немного снижает производительность.

Поскольку машина - роутер, установим активное правило невидимости роутера для traceroute:

# Stealth for traceroute (hide as hop)
block in quick on bge0 fastroute proto udp from any to 192.168.219.0/24 port 33434 - 33465
block in quick on bge1 fastroute proto udp from 192.168.219.0/24 to any port 33434 - 33465

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

# Anti-spoofing rules
#block in quick from 192.168.0.0/16 to any group 100
block in quick from 172.16.0.0/12 to any group 100
block in quick from 10.0.0.0/8 to any group 100
#block in quick from 127.0.0.0/8 to any group 100
block in quick from 0.0.0.0/8 to any group 100
block in quick from 169.254.0.0/16 to any group 100
block in quick from 192.0.2.0/24 to any group 100
block in quick from 204.152.64.0/23 to any group 100
block in quick from 224.0.0.0/3 to any group 100

# Anti-spoofing rules 2 - reversed
#block in quick from any to 192.168.0.0/16 group 100
block in quick from any to 172.16.0.0/12 group 100
block in quick from any to 10.0.0.0/8 group 100
#block in quick from any to 127.0.0.0/8 group 100
block in quick from any to 0.0.0.0/8 group 100
block in quick from any to 169.254.0.0/16 group 100
block in quick from any to 192.0.2.0/24 group 100
block in quick from any to 204.152.64.0/23 group 100
block in quick from any to 224.0.0.0/3 group 100

Также запретим транзит пакетов netbios через наш роутер:

# Block netbios packets
block return-rst in quick proto tcp from any to any port=135 flags S keep state group 100
block return-icmp-as-dest(port-unr) in quick proto udp from any to any port=137 group 100
block return-rst in quick proto tcp from any port=137 to any flags S keep state group 100
block return-icmp-as-dest(port-unr) in quick proto udp from any port=137 to any group 100
block return-rst in quick proto tcp from any port=138 to any flags S keep state group 100
block return-icmp-as-dest(port-unr) in quick proto udp from any port=138 to any group 100
block return-rst in quick proto tcp from any port=139 to any flags S keep state group 100
block return-icmp-as-dest(port-unr) in quick proto udp from any port=139 to any group 100

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

Далее идет основной блок разрешающих правил для сервисов и транзитных портов. Он достаточно хорошо описан в предыдущей статье. Стоит лишь подчеркнуть один достаточно специфический блок правил, касающийся трафика X11:

# 177 port - x11 service. Disable port on Internet servers!
# Access from internal networks only
# bge0 interface
pass in quick on bge0 proto udp from 192.168.201.0/24 to 192.168.219.0/24 port=177 keep state group 200
pass in quick on bge0 proto udp from 192.168.211.0/24 to 192.168.219.0/24 port=177 keep state group 200

В нашем случае машина-роутер не является прокси-сервером X11, соответственно, мы всего лишь пропускаем XCDMP-пакеты внутрь 219й сети, обратные сессии из 201 и 211 сети устанавливаются транзитом через роутер, не открывая дисплея на самом роутере за счет блока правил возвратных сессий (описывается ниже).

Роутер является сервером DNS для 219 сети:

# 53 port - DNS
# bge1 interface
# Allow incoming DNS requests to server
pass in quick on bge1 proto tcp/udp from 192.168.219.0/24 to any port=domain keep state group 300

Также он является сервером NTP для той же самой сети:

# 123 port - NTP
# bge1 interface
# Allow incoming NTP requests to server
pass in quick on bge1 proto udp from 192.168.219.0/24 to any port=ntp keep state group 300

Завершает конфигурацию блок исходящих правил и правил для возвратных сессий сервисов (группа 700):

# Allow connections originating from local machine out
pass out quick proto tcp from any to any flags S/SA keep state group 700
# Enable outgoing UDP to use traceroute from server
# Note: We dont open it for security reasons
pass out quick proto udp from any to any keep state group 700
pass out quick proto icmp from any to any keep state group 700

И, наконец, самое главное - основные блокирующие правила:

# Finally block any unmatched
block in quick on bge0 all # On bge0
block in quick on bge2 all # On bge2

Обратите внимание, что, в отличие от бастиона, мы не можем просто блокировать все пакеты, не удовлетворившие вышеописанным правилам. Согласно условию нашей задачи, мы блокируем входящие пакеты из внешней ДМЗ, а также блокируем входящие пакеты на сервисном интерфейсе, который не охвачен правилами роутинга. Если данные правила написать как для бастиона, работа машины как роутера будет полностью блокирована, поскольку возвратный трафик из внутренней сети будет отсекаться.

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

Вот и весь набор правил для роутера/форвардера. Он весьма компактен, быстро работает, и умещается менее, чем в 12 Кб.

PS. В данном примере не используется NAT/PAT. Мы рассмотрим их в одной из следующих статей.