ASA: заморочки трансляции сетевых адресов. Часть 1

advertisement
Руки дошли: продолжаем про ASA
Начнем, пожалуй, с базовых настроек интерфейсов и маршрутизации, а также настройки
подключений для удаленного администрирования
Настройка интерфейсов
Cisco ASA является аппаратным межсетевым экраном с инспектированием сессий с
сохранением состояния (stateful inspection). ASA умеет работать в двух режимах: routed
(режим маршрутизатора, по умолчанию) и transparent (прозрачный межсетевой экран,
когда ASAработает как бридж с фильтрацией). Мы познакомимся с работой в первом
режиме и далее везде будем его подразумевать, если явно не указан иной режим.
В режиме routed на каждом интерфейсе ASA настраивается ip адрес, маска, уровень
безопасности (security-level), имя интерфейса, а также интерфейс надо принудительно
«поднять», так как по умолчанию все интерфейсы находятся в состоянии «выключено
администратором». (Исключения бывают: иногда АСАшки приходят уже
преднастроенными. Это характерно для модели 5505. В этом случае, как правило,
внутренний интерфейс с названием inside уже настроен как самый безопасный и поднят,
на нем работает DHCP сервер, задан статический адрес из сети 192.168.1.0/24, внешний
интерфейс с названием outside тоже поднят и сам получает адрес по DHCP и настроена
трансляция адресов из сети за интерфейсом inside в адрес интерфейса outside. Получается
такой plug-n-play :))
int g0/0
ip address {адрес} {маска}
security-level {number}
nameif {имя}
no shutdown
Параметр «уровень безопасности» (security level) – это число от 0 до 100, которое
позволяет сравнить 2 интерфейса и определить, кто из них более «безопасен». Параметр
используется качественно, а не количественно, т.е. важно только отношение «большеменьше». По умолчанию трафик, идущий «наружу», т.е. с интерфейса с большим уровнем
безопасности на интерфейс с меньшим уровнем безопасности, пропускается, сессия
запоминается и обратно пропускаются только ответы по этим сессиям. Трафик же идущий
«внутрь» по умолчанию запрещен.
Параметр «имя интерфейса» (nameif) в дальнейшем позволяет использовать в настройках
не физическое наименование интерфейса, а его имя, которое можно выбрать «говорящим»
(inside, outside, dmz, partner и т.д.). По идее, как утверждает сама cisco, имя не зависит от
регистра, (не case sensitive), однако на практике ряд команд требует соблюдения регистра,
что довольно неудобно. Характерный пример: применение crypto map на интерфейс
требует точного написания названия интерфейса. Название интерфейса продолжается
нажатием кнопки TAB, т.е. можно набрать начало названия и табулятором продолжить
его до конца, если набранное начало однозначно идентифицирует интерфейс.
Такая настройка интерфейсов характерна для всех моделей ASA, кроме ASA 5505. В
модели 5505 реализован встроенный 8мипортовый L2/L3 коммутатор. IP адреса в модели
5505 задаются на логических интерфейсах
interface vlan {#}
ip address {адрес} {маска}
security-level {number}
nameif {имя}
no shutdown
Сами же физические интерфейсы L2 сопоставляются VLANам.
interface f0/0
switchport access vlan {#}
Таким образом, межсетевое экранирование возникает между логическими interface vlan.
Как правило, уровень безопасности интерфейсов подбирается таким образом, чтобы
максимально соответствовать логической топологии сети. Сама топология представляет
из себя зоны безопасности и правила взаимодействия между ними. Классической схемой
считается присвоение разным интерфейсам разных уровней безопасности.
Никто не запрещает сделать уровень безопасности на разных интерфейсах одинаковым,
однако по умолчанию обмен трафиком между такими интерфейсами запрещен. Такой
трафик можно сознательно разрешить, дав команду
same-security-traffic permit inter-interface
Однако надо понимать, что между интерфейсами с одинаковым уровнем безопасности не
возникает межсетевого экранирования, а только маршрутизация. Поэтому такой подход
применяется для интерфейсов, относящихся к одной и той же логической зоне
безопасноcти (например, 2 локальные сети пользователей, объединяемые при помощи
ASA)
Маршрутизация
Ну куда же без неё! Как у любого маршрутизатора (ASA тоже им является, т.к. использует
таблицу маршрутизации для передачи пакетов) сети, настроенные на интерфейсах,
автоматически попадают в таблицу маршрутизации с пометкой «Присоединенные»
(connected), правда при условии, что сам интерфейс находится в состоянии «up».
Маршрутизация пакетов между этими сетями производится автоматически.
Те сети, которые ASA сама не знает, надо описать. Это можно сделать вручную,
используя команду
route {interface} {network} {mask} {next-hop} [{administrative distance}]
[track {#}]
Указывается тот интерфейс, за которым надо искать next-hop, т.к. ASA сама не делает
такого поиска (в отличие от обычного маршрутизатора cisco). Напоминаю, что в таблицу
маршрутизации попадает только один маршрут в сеть назначения, в отличие от
классическим маршрутизаторов, где может использоваться до 16 параллельных путей.
Маршрут по умолчанию задается таким же образом
route {interface} 0.0.0.0 0.0.0.0 {next-hop}
Если ASA не имеет записи в таблице маршрутизации о сети назначения пакета, она пакет
отбрасывает.
Если возникает задача сделать запасной статический маршрут, который будет работать
только при пропадании основного, то это решается указанием так называемой
Административной дистанции маршрута. Это такое число от 0 до 255, которое указывает,
насколько хорош метод выбора маршрута. Например, статическим маршрутам по
умолчанию сопоставлена AD 1, EIGRP – 90, OSPF – 110, RIP – 120. Можно явно указать
AD для запасного маршрута больше, чем AD основного. Например:
route outside 0.0.0.0 0.0.0.0 {next-hop} 1
route backup 0.0.0.0 0.0.0.0 {next-hop_backup} 210
Но в этой ситуации есть один важный вопрос: как заставить «пропасть» основной
маршрут? Если физически упал интерфейс все очевидно – само получится, а если
интерфейс поднят, а провайдер погиб? Это очень распространенная ситуация, учитывая,
что на ASA сплошной ethernet, который физически падает крайне редко.
Для решения этой задачки используется технология SLA. Она весьма развита на
классических маршрутизаторах, а на ASA с версии 7.2 внедрили только самый простой
механизм: доступность некоторого хоста по протоколу icmp. Для этого создается такая
«пинговалка» (sla monitor)
sla monitor {#}
type echo protocol ipIcmpEcho {ip адрес} interface {интерфейс}
Далее, её необходимо запустить, указав время начала (есть возможность запустить
«сейчас») и окончания работы (можно задать работу до бесконечности)
sla monitor schedule {#} start now life forever
Но и это ещё не все. Надо создать «переключатель» (track) который будет отслеживать
состояние «пинговалки».
track {track #} rtr {sla #} reachability
Не спрашивайте, почему привязка пинговалки производится ключевым словом rtr – это
ошметки несогласованности настроек на маршрутизаторах cisco. К слову, на самих
маршрутизаторах такое несоответствие уже починили, а вот на ASA ещё нет.
И вот теперь все готово, чтобы применить эту конструкцию к статической маршрутизации
route outside 0 0 {next-hop_outside} track {#}
route backup 0 0 {next-hop_backup} 210
Теперь, пока пингуемый хост доступен, track будет в поднятом (чуть не написал в
«приподнятом» :)) состоянии и основной маршрут будет в таблице маршрутизации, но как
только связь пропадет, через заданное количество потерянных пакетов (по умолчанию
пакеты посылаются раз в 10 секунд и ждем пропадания трех пакетов) track будет
переведен в состояние down и основной маршрут пропадет из таблицы маршрутизации, а
пакеты будут отправляться по запасному пути.
Приведу пример конфига двух дефолтных маршрутов через разных провайдеров с
проверкой доступности основного провайдера:
sla monitor 1
type echo protocol ipIcmpEcho 1.1.1.1 interface outside
sla monitor schedule 1 start now life forever
track 11 rtr 1 reachability
route outside 0 0 1.1.1.1 track 11
route backup 0 0 2.2.2.1 210
Динамическая маршрутизация на ASA возможна по протоколам RIPv1,2, OSPF, EIGRP.
Настройка этих протоколов на ASA очень похожа на настройку маршрутизаторов cisco.
Пока динамической маршрутизации касаться в этих публикациях не буду, хотя если
дойдут руки и будет интерес – напишу отдельную главу.
Удаленное управление
Понятно, что при нынешнем развитии сетей передачи данных было бы неразумно не
внедрять удаленное управление межсетевыми экранами. Поэтому ASA, как и
большинство устройств cisco, предоставляет несколько способов удаленного управления.
Самое простое и небезопасное – telnet. Чтобы предоставить доступ на ASA по телнету
необходимо явно указать, с каких хостов и сетей и на каком интерфейсе разрешен доступ,
а также необходимо задать пароль на телнет командой passwd:
telnet 192.168.1.128 255.255.255.128 inside
telnet 192.168.1.254 255.255.255.255 inside
passwd {пароль}
В целях безопасности работа по телнету на самом небезопасном (с наименьшим уровнем
безопасности в рамках данной ASA) интерфейсе заблокирована и обеспечить работу на
этом интерфейсе по телнету можно только в том случае, если он приходит через IPSec
туннель.
Более безопасный доступ к командной строке обеспечивается протоколом ssh. Однако,
для обеспечения доступа по ssh кроме явного указания того, с каких хостов можно
заходить для управления, необходимо также задать RSA ключи, необходимые для
шифрования данных о пользователе. По умолчанию для подключения по ssh используется
пользователь pix и пароль, задаваемый командой passwd (пароль на telnet).
! Задаем имя домена
domain name {имя}
!
! Желательно задать недефолтовое имя хоста
hostname {имя}
!
! После этого можно сгенерировать ключи
crypto key generate rsa
!
! Разрешаем ssh
ssh 192.168.1.128 255.255.255.128 inside
ssh 1.2.3.4 255.255.255.255 outside
passwd {пароль}
Как правило, на ASA начиная с версии 7.2 имя домена уже задано (domain.invalid) и
дефолтные ключи сгенерированы, однако как минимум это надо проверить
show crypto key mypubkey rsa
Наличие хотя бы каких то ключей RSA уже позволяет работать по ssh. Но можно
дополнительно создать и недефолтовые ключевые пары. Для этого надо указать явно имя
ключевой пары
crypto key generate rsa label {имя пары}
Чтобы удалить ключевую пару (или все пары) используется команда
crypto key zeroize rsa [label {имя пары}]
Совет: после любых действий с ключевыми парами (создание, удаление) обязательно
сохраняйтесь. Для этого можно использовать стандартные команды cisco
copy running-config startup-config
write memory
или короткий вариант последней команды
wr
Также ASA предоставляет крайне популярный метод настройки с использованием вебброузера. Этот метод называется ASDM (Adaptive Security Device Manager). Для доступа
используется безопасный протокол https. Обеспечение доступа настраивается очень
похоже на настройку ssh: необходимо выработать или убедиться в наличии дефолтовых
RSA ключей и указать, откуда можно подключаться.
domain name {имя}
hostname {имя}
crypto key generate rsa
! Включаем сам https сервер, по умолчанию часто включен. При включении
! генерирует самоподписанный сертификат.
http server enable
! Разрешаем https
http 192.168.1.128 255.255.255.128 inside
http 1.2.3.4 255.255.255.255 outside
Если больше ничего не настраивать, то доступ будет обеспечен без указания пользователя.
Если же был указан пароль на привилегированный режим
enable password {пароль}
то при подключении надо в качестве пароля указывать именно его, не указывая
пользователя.
Надо проверить, что во флеше ASA лежит файл ASDM, соответствующий используемой
ОС.
dir flash:
show flash
При работе с ASDM используется java и верно следующее: если вы используете ОС
версии 7.Х, то ASDM нужен версии 5.Х и java 1.5. Если же используется ОС 8.Х, то
ASDM нужен версии 6.Х и java версии 1.6. К чести разработчиков и радости
настройщиков, ASDM версии 6 работает не в пример лучше и быстрее версии 5.Х. Чья тут
заслуга: java или cisco или обоих – не знаю.
Возникает резонный вопрос: а если хочется использовать не дефолтовые правила доступа,
а явно указывать, откуда брать пользователя? Для этого используются команды (console
— ключевое слово)
aaa authentication telnet console {имя AAA сервера} [LOCAL]
aaa authentication ssh console {имя AAA сервера} [LOCAL]
aaa authentication http console {имя AAA сервера} [LOCAL]
Если используется только локальная база данных пользователей, то в правиле
аутентификации можно указывать только LOCAL (проверьте, что хотя бы один
пользователь создан, иначе можно себе заблокировать доступ), а если требуется
использовать внешние базы, доступные по протоколам TACACS+, RADIUS или LDAP, то
такие сервера надо предварительно настроить
aaa-server {имя AAA сервера} protocol {tacacs|radius|ldap}
aaa-server {имя AAA сервера} ({interface}) host {ip}
key {ключ}
! и другие команды, специфичные для данного типа сервера
Локальная база пользователей задается командой
user {пользователь} password {пароль} [privilege #]
Доступ по ASDM возможен только от имени пользователя с уровнем привилегий 15
(максимальный, означает, что пользователю можно все настраивать)
Также локальным пользователям можно задать ряд атрибутов, используя команду
user {пользователь} attributes
! различные атрибуты пользователя
Завершая эту часть приведу кусочек конфига. В нем настроено 2 интерфейса (в данном
случае это gigabitethernet 0/0 и 0/1, однако на разных платформах это могут быть и другие
физические интерфейсы), inside и outside, дефолтный маршрут, разрешен удаленный
доступ по ssh и https ото всюду, при этом
аутентификация использует локальную базу данных пользователей.
hostname MyAsa
!
domain name anticisco.ru
!
interface g0/0
nameif outside
security-level 0
ip address 1.1.1.2 255.255.255.252
no shut
!
int g0/1
nameif inside
security-level 100
ip address 10.1.1.1 255.255.255.0
no shut
!
! на ASA запись 0.0.0.0 можно сократить до 0
!
route outside 0 0 1.1.1.1
!
username admin password cisco privilege 15
!
ssh 0 0 inside
ssh 0 0 outside
!
http 0 0 inside
http 0 0 outside
!
aaa authentication ssh console LOCAL
aaa authentication http console LOCAL
Используя такие настройки вы разрешите пакетам ходить из непосредственно
присоединенной сети за интерфейсом inside наружу. Снаружи будут приходить только
ответы по сессиям (tcp и udp), открытым изнутри, т.к. напомню по умолчанию трафик
идущий «внутрь» весь запрещен. Как его разрешить поговорим в следующей части.
ASA: списки доступа (продолжение цикла статей про
ASA)
Довольно простая глава. Списки доступа (ACL, Access Control List) – это правила
проверки заголовка ip пакета до уровня 4 модели OSI. Списки доступа – это просто
конструкции, состоящие из строчек. В каждой строчке – правило разрешить (permit) или
запретить (deny). Строчки просматриваются сверху вниз на предмет точного совпадения
заголовка пакета со строкой списка доступа. Списки доступа на ASA могут выполнять
несколько ролей:
1. Фильтрация на интерфейсе входящего или исходящего трафика
2. Описание правил NAT (Policy NAT)
3. Описание правил редистрибуции маршрутов (в route-map)
4. Критерий попадания в класс трафика для дальнейшей обработки (Modular Policy
Framework, MPF)
5. Описание «интересного трафика» для шифрования. Применяется список доступа в
crypto map
6. Описание прав удаленного пользователя при подключении через IPSec или SSL VPN
Важно: в конце любого списка доступа стоит невидимое «запретить все» (implicit deny
any), поэтому «мимо» списка доступа ни один пакет не пройдет.
Списки доступа делятся на стандартные и расширенные.
Стандартные списки доступа проверяют только адреса источника. На ASA такие списки
доступа имеют весьма узкое применение (например, для описания трафика для
удаленного VPN пользователя, который необходимо заворачивать в туннель. Технология
Split Tunneling)
Формат команды
access-list {NAME} [line #] standard {permit|deny|remark} {NETWORK} {MASK}
Ключевое слово remark используется для вставки комментариев в списки доступа.
параметр line # используется для вставки строки в определенное место списка доступа.
Например, если уже существует список доступа и надо вставить между 4 и 5 строкой
новую, то достаточно написать
access-list {NAME} line 5 {новая строка}
все строки строки начиная с 5 сдвинутся на 1 вниз.
Удалить конкретную строку из списка доступа можно, явно написав
no access-list {NAME} {конкретная строка списка доступа целиком}
написать только номер строки вот так
no access-list {NAME} line #
нельзя – ASA скажет, что «incomplete command».
Удалить полностью список доступа можно построчно :) Но не очень удобно для больших
списков, поэтому есть команда
clear configure access-list {NAME}
Незнание этой команды сильно портит кровь настройщикам ASA и является весомым
аргументом для их язвительных замечаний :)
Важно: команда clear configure довольно мощная и может привести к неприятным
последствиям, поскольку убивает из текущей конфигурации все строчки, начинающиеся с
ключевых слов, указанных после слов clear configure. Например, можно убить всю
текущую конфигурацию командой
clear configure all
Маска сети в списках доступа на ASA используется прямая (а не wildcard как на
маршрутизаторах). Для удобства указания адресов есть ряд сокращений, которые удобно
использовать. Так, если необходимо описать «все сети», то вместо громоздкой записи
0.0.0.0 0.0.0.0
Можно использовать ключевое слово
any
а вместо описания хоста с маской 32 бита
1.2.3.4 255.255.255.255
Можно использовать ключевое слово host перед самим адресом
host 1.2.3.4
Порядок следования строк в списках доступа очень важен, т.к. просмотр идёт сверху вниз
и останавливается при первом же совпадении. Поэтому наиболее точные указания надо
ставить повыше.
Пример: если мы хотим разрешить трафик на конкретный хост 10.1.1.100, запретить на
подсеть 10.1.1.0/24 и разрешить все, кроме этой сети, то писать надо так
access-list
access-list
access-list
access-list
SPLIT
SPLIT
SPLIT
SPLIT
remark -=ACL for VPN users=permit host 10.1.1.100
deny 10.1.1.0 255.255.255.0
permit any
В этом случае указание хоста – более точно, чем указание сети. А сеть – более точное
указание, чем «все адреса».
Формат расширенных списков доступа несколько сложнее, потому что учитывает ещё и
протокол, адреса назначения и может также учитывать порты TCP/UDP источника и
назначения (в формате команды — одна
строка):
access-list {NAME} [line#] {permit|deny] {protocol} {source net} {source
mask} [{operator} {port#}] {destination net} {destination mask} [{operator}
{port#}]
protocol – протокол стека TCP/IP (ICMP,TCP,UDP,OSPF,IGMP,ESP и т.д.) Если надо
указать все IP пакеты, то и писать надо в качестве протокола слово «ip»
operator – буквенная запись математических операторов (eq – равно, gt – больше, lt –
меньше, range – диапазон)
port – номер или название TCP или UDP порта.
Пример:
access-list
access-list
access-list
access-list
access-list
access-list
ANTISPOOF
ANTISPOOF
ANTISPOOF
ANTISPOOF
ANTISPOOF
ANTISPOOF
deny ip host 0.0.0.0 any
deny ip host 255.255.255.255 any
permit tcp any host 1.2.3.4 eq 80
permit tcp any host 1.2.3.4 eq https
permit udp any any range 16384 32768
permit icmp any any unreachable
В качестве удобного способа отладки можно использовать ключевое слово log в конце
строки списка доступа. Тогда каждый раз, когда по этой строке пройдет совпадение, будет
генерироваться syslog сообщение. Можно регулировать частоту генерирования такого
сообщения.
Важно: не увлекайтесь логгированием! Это весьма трудоемкий для ASA (и не только для
неё) процесс. Используйте её только для отладки. Плохим тоном лично я считаю всюду
пихать в конце явное (хотя в учебниках такую строку очень любят)
deny ip any any log
Также, удобно пользоваться ключевым словом inactive (начиная с версии 8.0) для
временного отключения строки списка доступа, не удаляя её совсем.
access-list
ANTISPOOF permit icmp any any unreachable inactive
Чтобы вновь вернуть эту строку к жизни, надо снова её набрать без слова inactive
Еще полезным дополнением является указание временного диапазона работы строки
списка доступа. Для этого используется конструкция time-range
time-range {NAME}
{absolute|periodic} {время работы}
Например:
time-range WORKTIME
periodic weekdays 10:00 to 19:00
Далее останется только применить time-range к строке списка доступа
access-list
{NAME} {строка} time-range {NAME}
Например:
access-list
WORKTIME
ANTISPOOF permit ip any host 198.133.219.25 time-range
Посмотреть полученные списки доступа можно командой
show run access-list {NAME}
При этом вы увидите строки конфига, которые начинаются со слов access-list {NAME}.
Если же нужно просмотреть список доступа с проставленными номерами строк и с
совпадениями по строкам, то лучше использовать команду
show access-list {NAME}
Важно: в отличие от маршрутизаторов, которые по списку доступа проверяют каждый
пакет, ASA проверяет пакет по списку доступа только если записи о сессии нет в кэше
сессий (о сессиях читайте в Главе «Обработка пакетов и создание сессии»). Поэтому
количество совпадений (hit) для сессионных протоколов (TCP и UDP) скорее означает
количество открытых по этой строке сессий.
Совет: я рекомендую всем применять не слишком длинные, но «говорящие» названия
списков доступа и писать их большими буквами. Можно даже выработать для себя свои
названия для разных случаев и всегда их придерживаться, например список доступа на
вход интерфейса backup у меня бы выглядел FROMBACKUP, а для проброса мимо NAT
на интерфейсе dmz — NONATDMZ. Часто бывает так, что конфигурацию создают
несколько администраторов или часть сделана при помощи Web-интерфейса, который
создает свои имена списков (какие же они неудобные!) и тогда в настройках
плохочитаемая каша. Можно переименовать список доступа с некрасивым именем,
используя команду rename
access-list {UGLYNAME} rename {PRETTYNAME}
______________
UPD 21.01.2010 00:18
Простите, выпал кусочек
На интерфейсе списки доступа применить можно как на вход, так и на выход интерфейса.
Список доступа на вход подобен охраннику ночного клуба, который может не пустить вас
внутрь из-за непрезентабельной внешности. А список доступа на выход интерфейса
подобен турникетам на выходе из бутика, который начинает истерично пиликать, если
почует спрятанные за пазухой гламурные стринги :)
access-group {NAME} {in|out} interface {INTERFACE NAME}
Пример:
access-group FROMOUTSIDE in interface outside
______________
Объектные группы
Если в вашей сети есть много схожих объектов (например, сетей пользователей, серверов
с одинаковым набором сервисов и т.д.), то при настройке списков доступа вы обязательно
столкнетесь с тем, что они становятся трудночитаемыми и плохо расширяемыми. Для
упрощения написания больших списков доступа на ASA применяются так называемые
объектные группы (object group). При помощи них можно группировать схожие элементы
сети (протоколы, сети, сервисы, сообщения icmp).
object-group network {NAME}
network-object host {ip}
network-object {NET} {MASK}
!
object-group service {NAME} {tcp|udp}
port-object {operator} {port}
!
object-group protocol {NAME}
protocol-object {PROTOCOL}
!
object-group icmp {NAME}
icmp-object {icmp type}
Пример:
object-group network SERVERS
network-object host 192.168.100.100
network-object host 192.168.100.101
network-object host 192.168.100.102
!
object-group service WEBTCP tcp
Port-object eq 80
Port-object eq 443
Port-object eq 1494
Сами объектные группы применяются вместо явного указания однотипного элемента в
списке доступа. Например, вместо адресов источника или назначения можно применить
объектную группу сетевого типа (object-group network), а вместо явного указания сервиса
TCP (ssh, http) можно применить группу типа сервис ТСР.
Пример:
access-list FROMOUTSIDE permit tcp any object-group SERVERS object-group
WEBTCP
При этом ASA все равно развернет ваши группы в списках доступа построчно, но при
этом все строки списка с объектной группой будут иметь один и тот же номер строки.
asa# show access-list
access-list FROMOUTSIDE
group WEBTCP
access-list FROMOUTSIDE
5)
access-list FROMOUTSIDE
access-list FROMOUTSIDE
access-list FROMOUTSIDE
2)
<output omitted>
FROMOUTSIDE
line 1 permit tcp any object-group SERVERS objectline 1 permit tcp any host 192.168.100.100 eq 80 (hit
line 1 permit tcp any host 192.168.100.100 eq 443
line 1 permit tcp any host 192.168.100.100 eq 1494
line 1 permit tcp any host 192.168.100.101 eq 80 (hit
Заметьте, что количество совпадений (hit) будет при этом у каждой строки, а не только
общее количество совпадений.
Посмотреть объектные группы можно командой
show run object-group [{тип}]
Трансляция сетевых адресов (coming soon :))
ASA: заморочки трансляции сетевых адресов. Часть 1.
Динамические трансляции
Трансляция сетевых адресов (Network Address Translation, NAT) — это подмена какоголибо адреса или порта в пакете. Она, как правило, требуется на границе между сетью
компании и провайдером Интернет. Однако, это далеко не единственная задача.
Рассмотрим несколько типичных задач и способы решения при помощи межсетевого
экрана ASA.
Для начала определимся с терминами. Как вы уже знаете, на ASA при помощи сравнения
уровней безопасности интерфейса-источника и интерфейса-назначения легко
определяется направление «наружу» и «внутрь» межсетевого экрана (ситуацию с
одинаковыми уровнями безопасности рассмотрим отдельно).
Обычно разделяют внутреннюю (inside) и внешнюю (outside) трансляции. Внутренняя
трансляция подменяет адрес источника при выходе «наружу» межсетевого экрана, а
внешняя трансляция подменяет адрес источника при проходе «внутрь» МЭ.
Как правило, достаточно использовать внутреннюю трансляцию, чтобы подменить
частные, немаршрутизируемые в Интернете адреса (RFC1918) на глобальные, выданные
провайдером.
Также, делят на трансляции адрес в адрес (NAT, выполняется на 3 уровне модели OSI,
один адрес заменяется другим), и трансляции с учетом порта (Port Address Translation,
PAT, выполняется на 4 уровне модели OSI и подменяет не только адрес, но и порт).
Понятно, что трансляцию РАТ можно выполнить только для протоколов, у которых есть
порты (TCP, UDP). Зато используя РАТ можно несколько локальных адресов
странслировать в один глобальный: в кэш трансляций записывается соответствие
исходного адреса и порта и полученных в результат трансляции адреса и порта.
Пример: пусть 2 локальных пользователя с адресами 10.1.1.100 и 10.1.1.200 решили
посетить один и тот же сайт www.anticisco.ru. Если мы используем NAT, в этом случае
нам надо каждому внутреннему пользователю выдать по глобальному адресу из пула
провайдера ISPPool():
10.1.1.100 -> ISPPool(1)
10.1.1.200-> ISPPool(2)
Если же мы будем использовать РАТ, то можем сопоставить разным частным адресам
один глобальный, но запишем ещё и порты источника:
10.1.1.100:29010 -> ISPPool(1):1024
10.1.1.200:18932 -> ISPPool(1):1025
И когда придёт ответ от сервера, ASA выберет из кеша трансляций ту, на чей порт придёт
ответ.
Чтобы окончательно добить вас, дорогие читатели, скажу ещё, что трансляции делятся на
статические и динамические. Статические строго привязывают один адрес к другому (в
случае с NAT) или пару адрес и порт (в случае с РАТ). А динамические создаются по
необходимости, если пришедший пакет удовлетворяет критерию отбора для правил
трансляции.
От слов к настройке.
Чтобы понять, в каким образом будет осуществляться трансляция, надо напомнить, что
первым делом пришедший на интерфейс пакет проверяется таблицей маршрутизации.
После этого определяется исходящий интерфейс или пакет уничтожается, если маршрут в
сеть назначения не найден. Если сеть назначения находится «снаружи» МЭ (за
интерфейсом с меньшим security level по сравнению с входящим интерфейсом), то
проверяются правила внутренних (inside) трансляций, а если «внутри» — то внешних
(outside)
В отличие от маршрутизаторов cisco, на ASA правила трансляций неразрывно связаны с
интерфейсами, участвующими в приёме и передаче пакета. Это упрощает написание
правил.
Ещё одно отличие от маршрутизаторов: на ASA можно жестко запретить прохождение
пакетов, для которых нет правил трансляции. Регулируется это командой
nat-control
По умолчанию эта команды выключена, т.е. если правил трансляции нет – пакеты идёт
просто по маршрутизации, а если правила есть, то будет произведена трансляция. Если же
эту команду включить, то пакеты, явно не попавшие под правил трансляции, будут
жестоко уничтожены.
Динамические трансляции
Напомню, что динамические трансляции создаются по необходимости, когда на
интерфейс приёмник приходит «интересный» пакет. Правило, описывающее, какой пакет
необходимо странслировать, описывается командой nat, при помощи которой задаются
адреса источника пакета:
nat ({interface}) # {network} {mask}
interface – название интерфейса, со стороны которого пришел пакет
# — это номер трансляции. Он необходим для поиска соответствующего указания, во что
транслировать адрес.
Пример:
nat (ins) 1 10.1.1.0 255.255.255.0
nat (ins) 1 10.2.2.2 255.255.255.255
Как видите, правил с одним и тем же номером может быть много
Понятно, что одного указания, что транслировать, не достаточно. Надо ещё описать, во
что транслировать. Это делается при помощи команды global
global ({interface}) # {pool|address}
interface – название интерфейса, через который пакет пойдёт наружу
# — номер трансляции. Он должен быть таким же, как и у интересующего нас условия nat
pool – явное задание диапазона адресов в формате ip_start-ip_end, в которые мы будем
транслировать. В этом случае получится динамическая NAT трансляция.
address – если указать не пул адресов, а один адрес, то все трансляции будут
производиться в него, а значит будет выполняться трансляция РАТ.
Пример:
global (out)
global (out)
1
1
81.1.1.10-81.1.1.20
81.1.1.21
Если у вы хотите транслировать в адрес исходящего интерфейса, то надо это явно указать,
используя ключевое слово interface
global (out)
1 interface
Если у вас есть несколько правил global с одинаковым номером, то сначала будет
выполняться трансляция NAT (в пул адресов), потом РАТ в отдельный адрес и только
потом РАТ в адрес интерфейса. Может возникнуть резонный вопрос: а когда наступает
это «потом»? Про пул адресов, надеюсь, понятно: когда адреса в пуле кончатся, а между
адресами в трансляциях РАТ? Что, неужели такой вопрос не возник? Ну, подумайте ещё :)
Повторяйте все вместе: когда возникает переключение между адресами, используемыми в
РАТ трансляции и вообще, может ли их быть много?
На оба эти вопроса один ответ: на ASA зарезервировано лишь около 4000 трансляций на
один адрес для РАТа. После этого новые трансляции создаваться не будут. А что же
делать? Использовать несколько адресов для РАТа. Т.е. несколько строчек global с одним
и тем же номером.
Особняком стоит правило nat с номером 0. Это правило описывает, что не надо
транслировать при выходе наружу. Особенно это правило необходимо, когда включен
строгий режим nat-control. Это правило не требует слова global для своей работы. По сути
можно себе представлять, что для этих пакетов действует правило трансляции адреса в
себя же.
Итак, мы описали правила внутренних динамических трансляция (NAT и PAT). Т.е. когда
пакет идет «наружу» проверяется наличие на входящем интерфейсе правил nat, и если
правила там есть и пакет под них попал, то на исходящем интерфейсе ищем
соответствующее правило global. При этом исходящий интерфейс имеет уровень
безопасности (security level) меньший, чем у входящего интерфейса
Если же нам необходимо динамически менять адреса источника пакетов, идущих
«внутрь» ASA, то надо явно указать, что правила global необходимо искать на
интерфейсах с большим уровнем безопасности. Делается это при помощи ключевого
слова outside в команде nat (применимо и для правил nat 0):
nat ({interface}) # {network} {mask} outside
Пример: пусть мы хотим «спрятать» все реальные адреса источника обращений из
Интернета, подменив их адресом внутреннего интерфейса
nat (out) 10 0 0 outside
global (ins) 10 interface
Как видите, формат команд очень похож. Кстати, приведенный в примере тип трансляций,
к сожалению, не поддерживается маршрутизаторами cisco (outside PAT)
Дополнительных возможностью трансляции адресов является возможность ограничить
максимальное количество открытых ТСР сессий, максимальное количество UDP сессий, а
также количество полуоткрытых ТСР сессий (embryonic), после которого включается
технология защиты от DoS атаки SYN Flood (огромное количество запросов на открытие
сессии). Технология называется SYN Cookie.
nat ({interface}) # {network} {mask} tcp {max} {embryonic} udp {max}
Если указать 0, то это будет означать «не отслеживать этот параметр».
А теперь вопрос на засыпку: а как нам транслировать в один пул, если идем в одну сеть и
в другой пул – если в другую сеть? Мы пока нигде не видели, что в качестве критерия
может вступать сеть назначения.
Для решения этой задачи приведенных выше команд не достаточно. Для этого
используется policy NAT («обычный» NAT, описанный ранее, называется regular)
Но не стоит пугаться раньше времени: ничего сложного в policy NAT нет, просто там в
качестве критерия надо указывать не сеть источника, а список доступа, в котором мы
указываем словом permit не только что мы собрались транслировать, но и когда.
Например, мы хотим транслировать наш LAN в адрес IPSPool(1), когда идём в сеть
PARTNER.
access-list NAT permit ip LAN PARTNER
nat (ins) 1 access-list NAT
global (out) 1 ISPPool(1)
На списки доступа, применяемые в policy NAT, есть ограничение: в нем нельзя
использовать строчки deny. Т.е. все, что вы хотите странслировать, должно быть явно
описано строками permit. Исключение делается только для списка доступа для nat 0. В нем
могут присутствовать строки deny. И означать эти строки будут, что надо просмотреть
другие правила трансляции – вдруг адрес требует подмены.
Policy NAT более привилегирован по сравнению с regular NAT.
Порядок обработки правил NAT – штука запутанная, но знать необходимо. Поэтому, не
дожидаясь части про статические трансляции, попробуем эти правила упорядочить
Самое первое правило – всегда policy NAT 0
nat ({interface}) 0 access-list {NONAT}
Далее идёт блок статических трансляций, с которым мы разберемся позже. Главное, что
нужно запомнить, что статические трансляции более привилегированные, чем
динамические
За ним следом идут трансляции policy NAT
nat ({interface}) # access-list {ACL}
При этом ASA отслеживает, чтобы эти списки доступа не пересекались.
Далее идут правила regular NAT, у которых действует правило наибольшего совпадения
маски (longest match). Причем, для правил nat 0 оно тоже верно.
Например, можно транслировать адрес 10.1.1.1, не транслировать сеть 10.1.1.0/24 и
транслировать все остальное во что-нибудь другое.
nat (ins) 0 10.1.1.0 255.255.255.0
nat (ins) 1 10.1.1.1 255.255.255.255
nat (ins) 2 0 0
Для закрепления этого кусочка 2 маленьких упражнения:
1. У вас есть доступ снаружи на АSA, за которой за внутренним интерфейсом подключен
компьютер с неправильно настроенным (отсутствующим) шлюзом по умолчанию. Надо
обязательно до него добраться (например, там включен RDP)
2. Расставьте правила трансляций в том порядке, в котором они будут выполняться
access-list NAT1 permit ip any host 198.133.219.25
access-list NAT1 deny ip any host 216.255.83.40
global (out) 2 int
global (out) 2 1.1.1.1-1.1.1.100
nat (ins) 0 10.1.1.1 255.255.255.255
nat (ins) 2 10.1.1.0 255.255.255.0
global (out) 1 1.1.1.254
global (out) 1 1.1.1.101-1.1.1.110
nat (ins) 1 access-list NAT1
Статические трансляции (не обессудьте: продолжение только следует)
ЗЫ Друзья, при перепечатке, переводе, использовании в работе с сотрудниками
пожалуйста, ссылайтесь на меня и www.anticisco.ru! Заранее спасибо за понимание :)
ASA: заморочки трансляции сетевых адресов. Часть 2.
Статические трансляции
Статические трансляции
Статические трансляции, в отличие от динамических, жестко связывают адреса (или
адреса с портами). Именно эта их особенность позволяет инициировать сессии как
изнутри, так и снаружи МСЭ. Но для того, чтобы раз и навсегда не путаться в написании
статических трансляций, я научу вас их «читать» правильно. Итак, формат команды
довольно прост:
static ({source_int},{dest_int}) {translated_address} {real_addess}
где
source_int – интерфейс на который приходит пакет
dest_int – интерфейс, с которого пакет пойдёт дальше
real_address – реальный адрес хоста
translated_address – странслированный адрес хоста
И читается трансляция так:
Когда пакет бежит с интерфейса source_int на интерфейс dest_int его адрес ИСТОЧНИКА
подменяется с real_address на translated_address.
Когда же пакет бежит в обратном направлении, т.е. приходит на интерфейс dest_int и идет
далее через интерфейс source_int его адрес НАЗНАЧЕНИЯ меняется с translated_address
на real_address
Т.к. адреса связаны жестко, можно инициировать сессию как изнутри, с адреса источника
real_address, так и снаружи, на адрес назначения translated_address. Именно про это
свойство я говорю, что статическая трансляция работает в обе стороны.
Собственно, вся сложность это запомнить «скрытые» слова (выделены жирным) и никогда
их не путать.
Статическая РАТ трансляция не сложнее. Надо лишь указать транспортный протокол и
пару портов
static ({source_int},{dest_int}) {tcp|udp} {translated_address}
{translated_port} {real_addess} {real_port}
При этом порты могут быть как одинаковые, так и разные, т.е. трансляцией можно
подменять реальные порты, на котором работает приложение.
Иногда возникает задача статически привязать одну сеть к другой той же мощности. Для
этого служит команда
static ({source_int},{dest_int}) {translated_address} {real_addess} netmask
{mask}
такая трансляция задает подмену сетевого префикса, но осталяет «суффикс», т.е. сам
адрес хоста в рамках данной сети.
Пример: свяжем внутренний адрес 10.1.1.100 с внешним 192.168.1.100, внутренний адрес
и порт веб-сервера 10.1.1.101 внешним адресом и портом 8080, а также подменим сеть
10.1.1.128/25 на 192.168.1.128/25
static (ins,out) 192.168.1.100 10.1.1.100
static (ins,out) tcp 192.168.1.101 8080 10.1.1.100 80
static (ins,out) 192.168.1.128 10.1.1.128 netmask 255.255.255.128
Также как у динамических трансляций есть обычные трансляции и трансляции с условием
(policy NAT), у статических тоже можно применить правила с условием (policy static)
Для этого тоже применяется список доступа, описывающий сразу и что транслируем
(адрес источника) и когда транслируем (адрес назначения).
Формат команды такой:
static ({source_int},{dest_int}) {translated_address} access-list {ACLNAME}
Разберем для примера задачку: пусть нам необходимо транслировать адрес 10.1.1.100 в
192.168.1.100 только если сервер общается с сетью 2.0.0.0/8
access-list STATIC permit ip host 10.1.1.1 2.0.0.0 255.255.255.0
static (ins,out) 192.168.1.100 access-list STATIC
Таким образом список доступа и запись о трансляции – неотъемлемые части конструкции.
В списке доступа не допускаются строчки deny, а если таких трансляций несколько, то
адреса назначения в списках доступа не должны пересекаться (иначе нельзя будет
однозначно решить, какую трансляцию выполнять).
Такая статическая трансляция тоже работает в обе стороны, но с сохранением условия:
адрес назначения 192.168.1.100 подменится на 10.1.1.100 только если обращение идёт из
сети 2.0.0.0/8
Важно: в качестве адреса источника в списке доступа для policy static указывается либо
адрес, если мы делаем NAT, либо адрес с портом и протокол, по которому мы делаем РАТ
трансляцию, либо подсеть, которую мы хотим транслировать в другую подсеть.
Примеры:
access-list STATICPAT permit tcp host 10.1.1.100 eq 80 2.0.0.0 255.0.0.0
static (ins,out) tcp 192.168.1.101 8080 access-list STATICPAT
!
access-list STATICNET permit ip 10.1.1.128 255.255.255.128 2.0.0.0 255.0.0.0
static (ins,out) 192.168.1.128 access-list STATICNET
_______________
UPD 7:50 16/02
Для статических трансляций, как и для динамических, можно ограничивать максимальное
количество открытых TCP и UDP сессий, а также количество полуоткрытых сессий, после
которого включается технология SYN Cookie
static ({source_int},{dest_int}) {любые условия} tcp {max} {embryonic} udp
{max}
_______________
А теперь разберем самое коварное: порядок выполнения статических трансляций:
— первыми выполняются трансляции policy static (со списками доступа). При этом ASA
сама отслеживает, чтобы списки доступа не конфликтовали друг с другом
— далее выполняются обычные статические трансляции. И вот тут то и ждет коварство:
трансляции выполняются в той последовательности, в которой они записаны в
конфигурации!
Пример коварства:
! в этом случае мы можем анонсировать web-сервер 10.1.1.101 по адресу
192.168.1.100 и на
! порту 8080, а все остальные порты и протоколы адреса 192.168.1.100
«пробросить» на
! адрес 10.1.1.100
!
static (ins,out) tcp 192.168.1.100 8080 10.1.1.101 80
static (ins,out) 192.168.1.100 10.1.1.100
!
!а в этом случае – нет
!
static (ins,out) 192.168.1.100 10.1.1.100
static (ins,out) tcp 192.168.1.100 8080 10.1.1.101 80
Итого, подрезюмируем последовательность правил:
nat (ins) 0 access-list
static (ins,out) Glob_ip access-list ACL
static (ins,out) Glob_ip Loc_ip
nat (ins) 1 access-list ACL (policy NAT)
nat (ins) # NETWORK (regular NAT)
# — число больше или равное нулю
Если есть возможность в динамических трансляциях использовать NAT (пул адресов), он
будет использоваться, пока не кончится, потом будет использоваться PAT в адреса, не
назначенные на интерфейс и только последним будет использоваться РАТ в адрес
интерфейса
global (out) 1 {start_ip}-{end_ip}
global (out) 1 {ip_address}
global (out) 1 interface
Здесь тоже дам задачку: как транслировать адрес 10.1.1.100 в 192.168.1.100, если идем во
все сети, кроме сети 192.168.100.0/24. А если идем в 192.168.100.0 надо транслировать
10.1.1.100 в 192.168.100.100.
Download