Tuesday, August 20, 2013

Брандмауэр на Cisco IOS используя zone-based firewall



Cisco IOS это довольно многофункциональна платформа, а не только ОС для роутера, на ней можно развернуть и IP-телефонию и полноценный Firewall. Первое я уже где-то описывал, а со вторым не сталкивался, но этот момент не заставил себя ждать. Итак, есть такая интересная незатронутая тема, как Zone-based firewall (ZBF).
В основе всей этой концепции лежит разбиение сети на отдельные участки или зоны. Самый яркий пример, это когда у нас в сети есть обычные пользователи, есть общедоступные сервера и, разумеется, выход в интернет. Само собою понятно, что извне не должно быть доступа к хостам пользователей, но должен быть доступ к серверам ну и имеется еще ряд нюансов. Это все можно сделать с помощью списков доступа (ACL), но как-то это все будет слишком уж коряво выглядеть и так же работать.

Таким образом, чтобы реализовать ZBF, надо первым делом разделить сеть на зоны, в нашем случае это:
- внутренняя, где расположены пользователи (inside)
- внешняя, непосредственно Интернет (outside)
- демилитаризованная зона, где расположены наши сервера (dmz)
Это общие стандартные названия, называть зоны можно как угодно и создавать их сколько угодно.


После создания зон нам необходимо будет привязать к ним определенные интерфейсы на роутере. Теперь правилами доступа мы будем рулить между зонами, а не между интерфейсами. При этом необходимо указать и настроить политики доступа из одной зоны в другую. На роутере можно будет использовать инспекцию трафика, так что инициировать соединение можно будет с одной зоны (если инициирование разрешено из этой зоны) и нельзя будет с другой. В нашем случае, пользователи могут инициировать соединение с серверами в dmz и другими серверами в Интернете. Сервера из dmz, в свою очередь не могут инициировать соединение в хостами во внутренней сети, так же как и сервера в Интернете. Если же необходимо разрешить определенный трафик из dmz, то необходимо указать отдельные разрешающие правила. Точно так же можно указать отдельные правила для соединения извне с серверами в зоне dmz. Например, разрешить только HTTP соединения и т.д. Необходимо учитывать, что эти правила работают только в одну сторону и только между двумя зонами. В любом случае, можно разрешить трафик и с другой стороны.
По умолчанию, между интерфейсами в одной зоне разрешен весь трафик, между интерфейсами в разных зонах – трафик запрещен. Трафик, который генерируется маршрутизатором, или предназначен ему, по-умолчанию разрешен.
 Перейдем к определению терминов
- class-map определяет, какой именно трафик будет инспектироваться (проходить между зонами, также проходить будут ответы на этот трафик). Фильтроваться трафик может по критериям c 4 по 7 уровней модели OSI (т.е. начиная от IP-адреса и заканчивая трафиком определенного приложения). Определяется трафик списками доступа, значением CoS, типом протокола и еще рядом других параметров. Критериев может присутствовать одновременно несколько. При этом можно указать, должен ли трафик попадать под все эти критерии (match-all) или под любой из них (match-any). Таким образом, основная задача class-map это отфильтровать необходимый тип трафика.
- policy-map определяет действие, которое будет произведено с отфильтрованным с помощью class-map трафиком. Действия могут быть следующие: инспектировать (разрешать, при этом контролировать поток), разрешать, запрещать, записывать в лог.
В одном policy-map может быть указано несколько class-map и к каждой из них может применяться отдельное действие. Если class map-ов указано несколько то сравнение будет проходить от первого до последнего правила последовательно до первого совпадения. Если трафик не попадает ни под одно правило, то он запрещается.
- service policies через него мы привязываем policy-map к определенной паре зон в одном направлении.
Для двух зон можно применить только одну service policy в одном направлении и, соответственно, одну в обратном направлении. Если действие с трафиком определено как inspect, то запросы будут контролироваться таким образом, что в обратную сторону будут разрешены ответы на эти запросы. Если действие определено как пропускать трафик, то контролироваться ничего не будет и ответы на этот трафик проходить не будут (если это не разрешено политикой между зонами в обратную сторону).
 
Теперь перейдем к самому интересному, к настройке. Посмотрим еще раз на рисунок, эта топология будет взята за основу построения нашего файрвола. В левой стороне находится внутренняя сеть, в нижней части показаны два сервера (ubuntu web-сервер, debian – другой сервер, предназначение которого нам неизвестно), в правой части выход в Интернет. Я пропущу настройки интерфейсов на маршрутизаторе и прочие мелочи, это уже никому не интересно, адресами интерфейсов будут первые доступные адреса в указанных подсетях.
Итак, с зонами мы определились. Теперь попробуем настроить трафик между зонами inside и outside
Тут все более-менее просто и понятно, создаем список доступа ACL
ZBF-Router(config)#access-list 20 permit 10.0.0.0 0.0.0.255
ZBF-Router(config)#
Теперь создадим class-map, где определим трафик как попадающий под наш список доступа. Как видно именно тут ключевым словом match-any указывается необходимо ли попадание под все критерии описанные в  class-map (match-all) или под любой из них.
ZBF-Router(config)#class-map type inspect match-any From_Inside
ZBF-Router(config-cmap)#?
Class-map configuration commands:
  description  Class-Map description
  exit         Exit from class-map configuration mode
  match        classification criteria
  no           Negate or set default values of a command
  rename       Rename this class-map
ZBF-Router(config-cmap)#match ?
  access-group  Access group
  class-map     Class map
  protocol      PAM Protocol
ZBF-Router(config-cmap)#match access-group 20
ZBF-Router(config-cmap)#

Теперь создадим policy-map и определим в нем необходимое действие с трафиком (inspect) а также укажем использование class-map для фильтрования. У меня они оба называются From_Inside, но эти имена могут отличаться, даже лучше, когда они отличаются.
ZBF-Router(config)#policy-map type ?
  access-control   access-control specific policy-map
  control          Configure a control policy policy-map
  inspect          Configure CBAC Policy Map
  logging          Control-plane packet logging
  port-filter      Control-plane tcp/udp port filtering
  queue-threshold  Control-plane protocol queue limiting
ZBF-Router(config)#policy-map type inspect ?
  WORD    policy-map name
  http    Configure CBAC policy-map for HTTP protocol
  im      Configure CBAC policy-map for IM protocol
  imap    Configure CBAC policy-map for IMAP protocol
  p2p     Configure CBAC policy-map for P2P protocols
  pop3    Configure CBAC policy-map for POP3 protocol
  smtp    Configure CBAC policy-map for SMTP protocol
  sunrpc  Configure CBAC policy-map for RPC protocol
ZBF-Router(config)#policy-map type inspect From_Inside
ZBF-Router(config-pmap)#class type inspect From_Inside
ZBF-Router(config-pmap-c)#?
Policy-map class configuration commands:
  drop            Drop the packet
  exit            Exit from class action configuration mode
  inspect         Context-based Access Control Engine
  no              Negate or set default values of a command
  pass            Pass the packet
  police          Police
  service-policy  Deep Packet Inspection Engine
  urlfilter       URL Filtering Engine
 
ZBF-Router(config-pmap-c)#inspect ?
ZBF-Router(config-pmap-c)#inspect
%No specific protocol configured in class From_Inside for inspection. All protocols will be inspected
ZBF-Router(config-pmap-c)#
ZBF-Router(config-pmap-c)#exit
ZBF-Router(config-pmap)#exit
ZBF-Router(config)#
На этом этапе создаем зоны, если они еще не созданы.
ZBF-Router(config)#zone security inside
ZBF-Router(config-sec-zone)#exit
ZBF-Router(config)#zone security outside
ZBF-Router(config-sec-zone)#exit
ZBF-Router(config)#
Теперь разрешаем трафик между двумя зонами, который определен в service-policy From_Inside.
ZBF-Router(config)# zone-pair security in-to-out source inside destination outside
ZBF-Router(config-sec-zone-pair)#service-policy type inspect ?
  WORD  policy-map name
ZBF-Router(config-sec-zone-pair)#service-policy type inspect From_Inside
ZBF-Router(config-sec-zone-pair)#exit
ZBF-Router(config)#
Дело за малым, привязываем интерфейсы к зонам.
ZBF-Router(config)#int fa2/0
ZBF-Router(config-if)#zone-member security inside
ZBF-Router(config-if)#exit
ZBF-Router(config)#int fa0/0
ZBF-Router(config-if)#zone-member security outside
ZBF-Router(config-if)#exit
ZBF-Router(config)#
Доступа к серверам в dmz из сети пользователей не будет на данном этапе потому что не указана политика доступа между зонами. Давайте разрешим доступ к серверам в dmz по следующим критериям:
- доступ из пользовательской сети (и только от этих адресов) по протоколам ssh, telnet и http.
- доступ из внешней сети всем только по протоколу http

Создаем зону и привязываем к ней интерфейс
ZBF-Router(config)#zone security dmz
ZBF-Router(config-sec-zone)#exit
ZBF-Router(config)#int fastEthernet 0/1
ZBF-Router(config-if)#zone-member security dmz
ZBF-Router(config-if)#
Создаем Class-Map для пары inside-dmz (укажем их тут несколько для разнообразия)
ZBF-Router(config)#class-map type inspect match-all Ins-dmz-ssh-map
ZBF-Router(config-cmap)#match access-group 20
ZBF-Router(config-cmap)#match protocol ssh
ZBF-Router(config-cmap)#exit
ZBF-Router(config)#class-map type inspect match-all Ins-dmz-map
ZBF-Router(config-cmap)#match access-group 20
ZBF-Router(config-cmap)#match protocol http
ZBF-Router(config-cmap)#exit
ZBF-Router(config)#class-map type inspect match-all Ins-dmz-telnet-map
ZBF-Router(config-cmap)#match access-group 20
ZBF-Router(config-cmap)#match protocol telnet
ZBF-Router(config-cmap)#exit
ZBF-Router(config)#
Создаем policy-map, где указываем все три созданные нами Class-Map
ZBF-Router(config)#policy-map type inspect Inside-dmz
ZBF-Router(config-pmap)#class type inspect Ins-dmz-ssh-map
ZBF-Router(config-pmap-c)#inspect
ZBF-Router(config-pmap-c)#exit
ZBF-Router(config-pmap)#class type inspect Ins-dmz-map
ZBF-Router(config-pmap-c)#inspect
ZBF-Router(config-pmap-c)#exit
ZBF-Router(config-pmap)#class type inspect Ins-dmz-telnet-map
ZBF-Router(config-pmap-c)#inspect
ZBF-Router(config-pmap-c)#exit
ZBF-Router(config-pmap)#
Создаем пару между зонами
ZBF-Router(config)#zone-pair security ins-to-dmz source inside destination dmz
ZBF-Router(config-sec-zone-pair)#service-policy type inspect Inside-dmz
ZBF-Router(config-sec-zone-pair)#exit
ZBF-Router(config)#
Что ж, доступ есть из внутренней сети есть. А теперь интересный момент, мы не разрешили протокол ICMP, поэтому доступ к серверу через браузер и через ssh c telnet-ом будет, а пинг проходить не будет. Такие дела.



Повторим еще раз пройденный материал, разрешим извне доступ к серверам по протоколу http.
ZBF-Router(config)#class-map type inspect match-any Out-dmz-map
ZBF-Router(config-cmap)#match protocol http
ZBF-Router(config-cmap)#exit
ZBF-Router(config)#

ZBF-Router(config)#policy-map type inspect Out-dmz-pol
ZBF-Router(config-pmap)#class type inspect Out-dmz-map
ZBF-Router(config-pmap-c)#inspect
ZBF-Router(config-pmap-c)#exit
ZBF-Router(config-pmap)#

ZBF-Router(config)#zone-pair sec out-dmz source outside destination dmz
ZBF-Router(config-sec-zone-pair)#service-policy type inspect Out-dmz-pol
ZBF-Router(config-sec-zone-pair)#

Тут такая же история, есть доступ через браузер, но нет доступа через другие протоколы, в том числе ICMP.
Замечу, что сервера при этом не могут вообще никуда инициировать соединения кроме как между собой. При этом они могут отвечать на соединения извне. Спокойно можно из внутренней сети зайти по ssh для администрирования сервера.

На последок добавлю что, zone based firewall совсем не мешает использовать NAT. В нашем случае пользователи из внутренней сети выходят в Интернет именно используя NAT. Конфигурация довольно нехитрая и выглядит таким образом:
ZBF-Router(config)# ip nat inside source list 10 interface FastEthernet0/0 overload
ZBF-Router(config)#access-list 10 permit 10.0.0.0 0.0.0.255
ZBF-Router(config)#int fa2/0
ZBF-Router(config-if)#ip nat inside
ZBF-Router(config-if)#int fa0/0
ZBF-Router(config-if)#ip nat outside
ZBF-Router(config-if)#



No comments:

Post a Comment