Про NAT при dualhoming с использованием EEM

История решения задачи, которую мы описывали в предыдущей статье, не закончилась на указанной в ней настройке. К нам обратился один клиент, у которого схема подключения была точно такой же, однако была одна особенность, которую мы не рассматривали. Это особенность называется NAT (Network Address Translation) и связана она с тем, что настройка NAT на маршрутизаторе в общем случае довольно простая, но жесткая. С одной стороны, это нас опечалило, так как решение не заработало в полной мере. С другой стороны, у нас дополнились входные данные, которые не были учтены при разработке первого решения. И мы поняли, что нам просто необходимо принять этот вызов и решить задачу с новыми входными данными. Итак, уточнение входных данных (первая часть статьи с входными данными  и решением, которое лежит в основе текущей статьи, ты можешь прочитать здесь):

1)      Внутреннюю подсеть пользователей 30.30.0.0/24 необходимо транслировать (PAT – Port Address Translation, он же dynamic NAT overload) в адрес интерфейса, через который пакеты идут.

2)      Для основного канала – это трансляция в адрес 10.10.0.6.

3)      Для резервного канала – это трансляция в адрес 20.20.0.2.

На всякий случай напомним схему сети:

Рисунок 1 / схема подключения к двум провайдерам с NAT

Рисунок 1 / схема подключения к двум провайдерам с NAT

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

Настройка NAT на маршрутизаторе при singlehominge (подключении к Интернету по одному каналу) не представляет большой проблемы. Поэтому сразу пришла в голову мысль сделать тут точно таким же образом:

CE(config)#access-list 1 remark ACL_for_NAT
CE(config)#access-list 1 permit 30.30.00.0 0.0.0.255
CE(config)#interface fa 0/0
CE(config)#ip nat outside
CE(config)#interface s 0/0
CE(config)#ip nat outside
CE(config)#interface fa 0/1
CE(config)#ip nat inside
CE(config)#ip nat inside source list 1 interface fa 0/0 overload
CE(config)#ip nat inside source list 1 interface s 0/0 overload

Но судьба-злодейка, а точнее Cisco-злодейка, совсем не дает сделать такой фокус. Если мы посмотрим конфиг (в данном случае running-config), то мы увидим в ней только одну запись о правиле трансляции:

CE#show running-config | include ip nat inside
ip nat inside
ip nat inside source list 1 interface Serial0/0 overload

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

Такое поведение маршрутизатора Cisco вполне объяснимо: он должен быть на 100% уверен в том, какие адреса он должен транслировать, и какие адреса должны получиться после трансляции. Соответственно адреса, которые подпадают под один список доступа, будут транслированы в один внешний адрес.

Okay…

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

CE(config)#access-list 2 remark ACL_for_NAT_2
CE(config)#access-list 2 permit 30.30.00.0 0.0.0.255
CE(config)#ip nat inside source list 2 interface s 0/0 overload

Так как просмотр running-config’а показывает нам, что все команды там присутствуют, то мы полагаем, что все настроено  корректно, и начинаем тестирование. Для этого запустим ping на клиентской машине, расположенной за маршрутизатором CE. Уточним, что сейчас схема работает в нормальном режиме, то есть трафик бежит через основной канал:

ClientPC>ping 100.100.100.1
Pinging 100.100.100.1 with 32 bytes of data:
Reply from 100.100.100.1: bytes=32 time=107ms TTL=53
Reply from 100.100.100.1: bytes=32 time=114ms TTL=53
Reply from 100.100.100.1: bytes=32 time=106ms TTL=53
Reply from 100.100.100.1: bytes=32 time=95ms TTL=53
Ping statistics for 100.100.100.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 95ms, Maximum = 114ms, Average = 105ms

На маршрутизаторе CE в данный момент мы можем увидеть то, как осуществляются трансляции:

CE#debug ip nat
*Mar 2 12:18:57.787: NAT*: s=30.30.0.2->10.10.0.6, d=100.100.100.1 [160]
*Mar 2 12:18:57.787: NAT*: s=100.100.100.1, d=10.10.0.6->30.30.0.2 [160]
*Mar 2 12:18:57.791: NAT*: s=30.30.0.2->10.10.0.6, d=100.100.100.1 [161]
*Mar 2 12:18:57.795: NAT*: s=100.100.100.1, d=10.10.0.6->30.30.0.2 [161]
*Mar 2 12:18:57.795: NAT*: s=30.30.0.2->10.10.0.6, d=100.100.100.1 [162]
*Mar 2 12:18:57.799: NAT*: s=100.100.100.1, d=10.10.0.6->30.30.0.2 [162]
*Mar 2 12:18:57.803: NAT*: s=30.30.0.2->10.10.0.6, d=100.100.100.1 [163]
*Mar 2 12:18:57.807: NAT*: s=100.100.100.1, d=10.10.0.6->30.30.0.2 [163]
*Mar 2 12:18:57.807: NAT*: s=30.30.0.2->10.10.0.6, d=100.100.100.1 [164]
*Mar 2 12:18:57.811: NAT*: s=100.100.100.1, d=10.10.0.6->30.30.0.2 [164]

Все работает нормально в этом случае. Следующим пунктом тестирования решения в нашим чек-листе является тестирование резервного канала. Отключаем основной канал и видим такую картину: ничего не работает. Смотрим на CE, что там происходит:

CE#debug ip nat
*Mar 2 12:14:10.496: NAT: translation failed (A), dropping packet s=30.30.0.2 d=100.100.100.1

На данном этапе танцы с бубном успеха не принесли, к сожалению. Статистика NAT говорит нам о том, что под наше новое правило ничего не подпадает:

CE#show ip nat statistics
[Id: 1] access-list 1 interface FastEthernet0/0 refcount 5
[Id: 3] access-list 2 interface Serial0/0 refcount 0

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

1)      У нас должно быть только одно правило трансляции, которое указывает в какой IP-адрес мы транслируем свои внутренние IP-адреса в данный момент.

2)      При переключении канала с основного на резервный правило трансляции NAT также должно изменяться.

3)      При возвращении трафика на основной канал правило должно вернуться к изначальному виду.

Одно правило трансляции, которое изменяется, означает необходимость изменять настройку маршрутизатора в зависимости от активного канала. А мы говорим о том, что мы хотим этот процесс автоматизировать. Не первый момент, может показаться, что мы шутим, однако это не так. В маршрутизаторах и коммутаторах Cisco есть замечательный инструмент – EEM (Embedded Event Manager). По сути своей – это инструмент условного программирования, то есть он позволяет создавать нам скрипты (например, последовательность команд, которые изменят существующую настройку маршрутизатора Cisco), которые будут выполняться при наступлении определенных условий. Такие условия у нас есть:

1)      Переключение с основного канала на резервный;

2)      Переключение с резервного канала на основной.

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

CE#TRACKING-5-STATE: 123 rtr 1 reachability Up->Down

А если второе, то запись выглядит так:

CE#TRACKING-5-STATE: 123 rtr 1 reachability Down->Up

Супер! Нам остается создать два скрипта, которые будут выполнять нужные нам действия, и активация которых будет наступать при выведении в командной строке указанных команд. Так как по умолчанию у нас работает основной канал, то и правило NAT должно быть соответствующее трансляции в адрес 10.10.0.6. Значит, при переключении на резервный канал, правило трансляции NAT должно изменяться на трансляцию в адрес 20.20.0.2. Напишем нужный EEM скрипт:

CE(config)#event manager applet UPDOWN
CE(config-applet)#event syslog pattern «TRACKING-5-STATE: 123 rtr 1 reachability Up->Down»
CE(config-applet)#action 1.0 cli command «enable»
CE(config-applet)#action 1.1 cli command «clear ip nat trans forced»
CE(config-applet)#action 1.2 cli command «config term»
CE(config-applet)#action 1.3 cli command «ip nat inside source list 1 interface s 0/1 overload»

Порядковый номер команды указывает на очередность ее выполнения, поэтому надо указывать команды по порядку и с верными номерами. Хотим отметить, что команда под номером «1.1» является крайне важной, так как если ты не почистишь текущую таблицу трансляций NAT, то Cisco IOS не даст тебе изменить правило трансляции. Фактически, последовательность команд, которую мы указываем тут, идентична той, которую мы бы набирали сами. Можно рассматривать EEM в качестве виртуального пользователя, который через vty линию настраивает наш маршрутизатор Cisco.

Скрипт, который возвращает маршрутизатор в исходное состояние, выглядит несколько сложнее:

CE(config-applet)#event manager applet DOWNUP
CE(config-applet)#event syslog pattern «TRACKING-5-STATE: 123 rtr 1 reachability Down->Up»
CE(config-applet)#action 2.0 cli command «enable»
CE(config-applet)#action 2.1 cli command «config term»
CE(config-applet)#action 2.2 cli command «int s0/1″
CE(config-applet)#action 2.3 cli command «shut»
CE(config-applet)#action 2.4 cli command «do clear ip nat trans forced»
CE(config-applet)#action 2.5 cli command «ip nat inside source list 1 interface fa 0/0 overload»
CE(config-applet)#action 2.6 cli command «int s0/1″
CE(config-applet)#action 2.7 cli command «no shut»

Как и в первом скрипте, порядок команд должен быть строго таким, какие бы ты сам вводил на маршрутизаторе. На этом наша настройка завершена. Осталось оттестировать решение, чем мы и займемся.

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

CE#
*Mar 2 13:20:43.094: %TRACKING-5-STATE: 123 rtr 1 reachability Up->Down
*Mar 2 13:20:43.282: %SYS-5-CONFIG_I: Configured from console by vty2

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

CE#show ip nat statistics
[Id: 1] access-list 1 interface Serial0/0 refcount 0

Запустим ping с клиентского терминала в сеть Интернет:

ClientPC>ping 100.100.100.1
Pinging 100.100.100.1 with 32 bytes of data:
Reply from 100.100.100.1: bytes=32 time=117ms TTL=53
Reply from 100.100.100.1: bytes=32 time=112ms TTL=53
Reply from 100.100.100.1: bytes=32 time=103ms TTL=53
Reply from 100.100.100.1: bytes=32 time=104ms TTL=53
Ping statistics for 100.100.100.1:Packets:
Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 103ms, Maximum = 117ms, Average = 109ms

Все здорово транслируется и передается как надо. Это очень хорошо, даже очень хорошо. Теперь настал черед вернуть все в исходное состояние, то есть вернуть в работу основной канал. Как только на icmp начнут приходить ответы, канал вернется в исходное состояние:

CE#
*Mar 2 13:43:28.147: %TRACKING-5-STATE: 123 rtr 1 reachability Down->Up
*Mar 2 13:43:28.312: %SYS-5-CONFIG_I: Configured from console by vty2

Еще раз проверим настройки трансляции NAT:

CE#show ip nat statistics
[Id: 1] access-list 1 interface FastEthernet0/0 refcount 0

Все именно так, как должно было бы быть. Остается проверить ping с пользовательского терминала:

Вот и все, все тесты показали корректную работу разработанного решения. Это значит, что дополненные условия были правильно оценены и интегрированы в новое решение.

Вместо послесловия. При тестировании данного решения на Cisco 1841 с ADSL каналом была обнаружена проблема, которая приводила к перезагрузке маршрутизатора. Детальное изучение проблемы указало на то, что в случае запуска скрипта в момент поднятия интерфейсов Virtual-access происходит краш системы. Подкрутка таймеров IP SLA позволило победить эту проблему и сделать решение применимым в конкретной сети. Вот как-то так.

Напоминаем, если тебе понравилась данная статья – поднимай палец вверх, то есть ставь «нравиться» и «поделиться» под ссылкой к данной статье в facebook и в целом не стесняйся, а показывай, что тебе эта страничка «нравиться». А если тебе не нравиться – пиши нам в комментариях, будем дорабатывать ее. Удачи тебе!


Комментарии:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Hide me
Получать регулярно свежие материалы, лабораторные и вебинары
Email Имя
Show me