«Если в простой конфигурации микротик не работает, значит вы не умеете его готовить… или явно что-то упустили.»
Как работают вместе failover и netwatch. Взгляд изнутри.
Почти каждой более-менее подросшей компании начинает хотеться качества коммуникаций. Среди прочего, заказчику часто хочется отказоустойчивый «Dual WAN» и VoIP телефонию. Тоже отказоустойчивую, разумеется. Руководств и статей по каждой теме в отдельности написано много, но внезапно оказалось, что совместить первое и второе получается не у всех.
На Хабре уже есть статья «Mikrotik. Failover. Load Balancing» от vdemchuk. Как оказалось, она послужила для многих источником копипасты кода в маршрутизаторы.
Хорошее, рабочее решение, но SIP-клиенты из LAN, подключающиеся к внешней IP-АТС посредством NAT, при переключении теряли связь. Проблема известная. Связана она с работой Connection tracker, который запоминает имеющиеся соединения вовне, и сохраняет их состояние независимо от других условий.
Понять почему так происходит можно посмотрев на диаграмму packet flow:
Для транзитного трафика процедура обработки connection tracker выполняется всего в одной цепочке — prerouting, (т.е. до роутинга), до выбора маршрута и исходящего интерфейса. На этой стадии еще неизвестно, через какой интерфейс пакет пойдет в Интернет, и отследить src-ip при нескольких Wan-интерфейсах невозможно. Механизм фиксирует установленные соединения уже пост-фактум. Фиксирует и запоминает на время пока через соединение идут пакеты или пока не истечет заданный таймаут.
Описанное поведение характерно не только для маршрутизаторов MikroTik, но и для большинства Linux-based систем выполняющих NAT.
В результате, при обрыве связи через WAN1, поток данных послушно направляется через WAN2, только SOURCE IP прошедших через NAT пакетов остается неизменный — от интерфейса WAN1, т.к. в connection tracker уже есть соответствующая запись. Естественно, ответы на такие пакеты идут на интерфейс WAN1 уже потерявший связь с внешним миром. В итоге, связь как будто есть, но на самом деле её нет. При этом все новые соединения устанавливаются корректно.
Hint: увидеть с каких и на какие адреса делается NAT можно в колонках «Reply Src. Address» и «Reply Dst. Address». Отображение этих колонок включается в таблице «connections» с помощью правой кнопки мыши.
На первый взгляд выход выглядит довольно простым — при переключении сбросить ранее установленные SIP-соединения, чтобы они установились заново, уже с новым SRC-IP. Благо простой скрипт по просторам интернета бродит.
:foreach i in=[/ip firewall connection find dst-address~":5060"] do={ /ip firewall connection remove $i }
Три шага к фейлу.
Шаг первый. Копипастеры добросовестно переносят конфиг для Failover recursive routing:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
###Обеспечение failover c более глубоким анализом канала###
#с помощью параметра scope укажем рекурсивные пути к узлам 8.8.8.8 и 8.8.4.4
/ip route add dst-address=8.8.8.8 gateway=10.100.1.254 scope=10
/ip route add dst-address=8.8.4.4 gateway=10.200.1.254 scope=10
# укажем 2 default gateway через узлы путь к которым указан рекурсивно
/ip route add dst-address=0.0.0.0/0 gateway=8.8.8.8 distance=1 check-gateway=ping
/ip route add dst-address=0.0.0.0/0 gateway=8.8.4.4 distance=2 check-gateway=ping
Шаг второй. Отследить событие переключения. Чем? "/tool netwatch", естественно! Попытка отследить падение шлюза WAN1 обычно выглядит так:
add comment=«Check Main Link via 8.8.8.8» host=8.8.8.8 timeout=500ms /
down-script=":log warning («WAN1 DOWN»)
:foreach i in=[/ip firewall connection find dst-address~":5060"] do={
:log warning («clear-SIP-connections: clearing connection src-address:$[/ip firewall connection get $i src-address] dst-address:$[/ip firewall connection get $i dst-address]»)
/ip firewall connection remove $i}"
up-script=":log warning («WAN1 UP»)
:foreach i in=[/ip firewall connection find dst-address~":5060"] do={
:log warning («clear-SIP-connections: clearing connection src-address:$[/ip firewall connection get $i src-address] dst-address:$[/ip firewall connection get $i dst-address]»)
/ip firewall connection remove $i}"
Шаг третий. Проверка.
Админ гасит первый аплинк WAN1 и вручную запускает скрипт. SIP-клиенты переподключились. Работает? Работает!
Админ включает обратно WAN1 и вручную запускает скрипт. SIP-клиенты переподключились. Работает? Работает!
Fail.
В реальной обстановке такой конфиг работать отказывается. Неоднократное повторение шага №3 приводит админа в состояние озлобления и мы слышим «Не работает ваш микротик!».
Разбор полётов.
Всё дело в непонимании того, как происходит работа утилиты Netwatch. Применительно в отношении именно рекурсивного роутинга, утилита просто пингует заданный хост согласно основной таблице маршрутизации, используя активные маршруты.
Проведем эксперимент. Отключим основной канал WAN1 и посмотрим и интерфейс /tool netwatch. Мы увидим, что хост 8.8.8.8 по-прежнему имеет состояние UP.
Для сравнения опция check-gateway=ping, работает для каждого маршрута в отдельности в т.ч. рекурсивно, и делает сам маршрут активным либо НЕактивным.
Netwatch использует уже активные на данный момент маршруты. Когда что-либо происходит на линке до шлюза провайдера ISP1 (WAN1), маршрут до 8.8.8.8 через WAN1 становится неактивным, и netwatch игнорирует его, отправляя пакеты в новый default route. Failover играет злую шутку, и netwatch считает, что всё в порядке.
Второй вариант поведения netwatch, это двойное срабатывание. Механизм его таков: если пинги от netwatch попадут в таймаут check-gateway, то на один цикл проверки хост будет признан DOWN. Сработает скрипт переключения канала. SIP-соединения корректно перейдут на новый линк. Работает? Не совсем. Скоро таблица маршрутизации перестроится, хост 8.8.8.8 получит статус UP, вновь сработает скрипт сброса SIP-соединений. Соединения второй раз переустановятся через WAN2.
В результате, при возвращении в строй ISP1 и переходе рабочего трафика на WAN1, SIP-соединения так и останутся висеть через ISP2 (WAN2). Чревато это тем, что при проблемах у на запасном канале система этого не заметит и телефонной связи не станет.
Решение.
Для того, чтобы трафик на используемый для мониторинга хост 8.8.8.8 не заворачивался на ISP2, нам нужно иметь запасной маршрут до 8.8.8.8. На случай падения ISP1, создаем резервный маршрут с большим значением distance, например distance=10 и type=blackhole. Он и станет активным при пропадании линка до WAN1 Gateway:
/ip route add distance=10 dst-address=8.8.8.8 type=blackhole
В итоге имеем дополнение конфига всего лишь одной строкой:
/ip address add address=10.100.1.1/24 interface=ISP1
/ip address add address=10.200.1.1/24 interface=ISP2
# Настроим локальный интерфейс
/ip address add address=10.1.1.1/24 interface=LAN
# скроем за NAT все что выходит из локальной сети
/ip firewall nat add src-address=10.1.1.0/24 action=masquerade chain=srcnat
###Обеспечение failover c более глубоким анализом канала###
#с помощью параметра scope укажем рекурсивные пути к узлам 8.8.8.8 и 8.8.4.4
/ip route add dst-address=8.8.8.8 gateway=10.100.1.254 scope=10
/ip route add distance=10 dst-address=8.8.8.8 type=blackhole
/ip route add dst-address=8.8.4.4 gateway=10.200.1.254 scope=10
# укажем 2 default gateway через узлы путь к которым указан рекурсивно
/ip route add dst-address=0.0.0.0/0 gateway=8.8.8.8 distance=1 check-gateway=ping
/ip route add dst-address=0.0.0.0/0 gateway=8.8.4.4 distance=2 check-gateway=ping
Данная ситуация характерна именно при падении последней мили, когда шлюз ISP1 становится недоступным. Либо при использовании туннелей, которые более подвержены падениям в силу цепной зависимости.
Надеюсь, статья поможет вам избежать подобных ошибок.
Выбирайте свежие мануалы. Будьте в курсе, и всё у вас «взлетит».
Автор: nkusnetsov