Full-stack PHP Developer, Sysadmin
0,0
рейтинг
30 июля 2014 в 05:44

Администрирование → Mikrotik: автоматическое переключение канала на резервный и обратно recovery mode

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

Что я хотел сделать, если отключается основной канал Интернета:
1. Переключиться на резервный канал (после «появления», разумеется, вернуться на основной);
2. Отправить уведомление по email о факте изменения состояния.

Кому интересно, прошу под кат.

Нам дано:
— Mikrotik RB450G с прошивкой 5.19 версии;
— 2 порта с Интернетом, один из которых для подключения использует PPPoE соединение.

Сперва добавим 2 скрипта, один из которых будет переключать на резервный канал, а второй вернет подключение к первому.

image

Составим первый скрипт, который будет активировать резервный канал и назовем его "change-to-reserv" и содержать в себе код:
/ip route set gateway=1.1.1.1 [find dst-address=0.0.0.0/0];

(Примечание: IP-адрес 1.1.1.1 выбран как пример и символизирует резервный канал)
То есть, при обнаружении отсутствия пинга на сервер (об этом чуть позже) мы будем выключать маршрут с шлюзом, указывающим на "pppoe-main".
P.S.: После комментария erazel данная схема была улучшена, а именно раннее скрипт переключался между двумя маршрутами, которые давали сбой, а именно, если запустить с компа, например, команду ping google.ru -t, то при изменении маршрута пинг будет уходить на старый интерфейс, так как трансляция не обновилась. В предложенном же методе изменения только шлюза очистка трансляции не требуется.

Следующей строкой в этом же скрипте укажем:

/tool e-mail send server=192.168.1.1 port=25 user=robot@mysite.ru password=1PaSsW0rD1 tls=no to=admin@mysite.ru from="ROBOT<robot@mysite.ru>" \
subject="MikroTik: $[/system clock get date], $[/system clock get time]" \
body="Переключение на резервный канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]";

где:
/tool e-mail send — отправляем уведомление на email администратора о факте изменения статуса
server=192.168.1.1 — SMTP-сервер. Так как у нас используется свой, указываю его;
port=25 — в версии RouterOS 5.x порт указывается отдельно. В нашем случае он по-умолчанию 25;
user=robot@mysite.ru — логин пользователя для авторизации на SMTP-сервере (если требуется);
password=1PaSsW0rD1 — указываем пароль (если требуется);
tls=no — TLS-шифрование трафика. У нас нет, ставлю «no», а если и будет — «yes»;
to=admin@mysite.ru — на какой email-адрес будет приходить уведомление;
from=«ROBOT<robot@mysite.ru>» — от кого будет приходить уведомление (в моем случае совпадает с логином авторизации. В скобках указывается адрес отправителя, а перед ним имя, отображаемое во входящей почте);
subject=«MikroTik: $[/system clock get date], $[/system clock get time]» — указываем заголовок письма. В данном случае он будет иметь вид «MikroTik: jul/30/2014, 10:52:13» (дата и время отправки сообщения);
body=«Переключение на резервный канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]»; — соответственно, само тело сообщения, которое будет иметь вид:
Переключение линии на резервный канал
Дата: jul/30/2014
Время: 10:52:13

В итоге, наш скрипт будет иметь вид (RouterOS 5.19):
/ip route set gateway=1.1.1.1 [find dst-address=0.0.0.0/0];
/tool e-mail send server=192.168.1.1 port=25 user=robot@mysite.ru password=1PaSsW0rD1 tls=no to=admin@mysite.ru from="ROBOT<robot@mysite.ru>" \
subject="MikroTik: $[/system clock get date], $[/system clock get time]" \
body="Переключение на резервный канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]";


И для RouterOS 6.17:
/ip route set gateway=1.1.1.1 [find dst-address=0.0.0.0/0];
/tool e-mail send server=192.168.1.1 port=25 user=robot@mysite.ru password=1PaSsW0rD1 to=admin@mysite.ru from="ROBOT<robot@mysite.ru>" \
subject="MikroTik: $[/system clock get date], $[/system clock get time]" \
body="Переключение на резервный канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]";


Как уже писал выше, сохраним его под именем "change-to-reserv" и приступим к написанию второго скрипта:

/ip route set gateway=pppoe-main [find dst-address=0.0.0.0/0];
/tool e-mail send server=192.168.1.1 port=25 user=robot@mysite.ru password=1PaSsW0rD1 tls=no to=admin@mysite.ru from="ROBOT<robot@mysite.ru>" \
subject="MikroTik: $[/system clock get date], $[/system clock get time]" \
body="Переключение на основной канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]";

В отличие от первого скрипта, в теле отправляемого email-сообщения мы укажем «Переключение на основной канал» и включим раннее отключенный маршрут.
Сохраним наш скрипт под именем "change-to-main".

Так как память у Mikrotik не резиновая, мы оптимизируем наш скрипт для выполнения поставленной задачи.
Для этого нам необходимо использование утилиты Netwatch, которая работает как тригер. То есть, если состояние подключение изменится, то сменится и статус с выполнением нужных нам скриптов.

image

В Netwatch мы добавим новое правило, где укажем хост 8.8.8.8 и имена скриптов во вкладках «Up» — «change-to-main» и «change-to-reserv» во вкладке «Down» соответственно.
Также следует указать период проверки состояния. У нас указана 1 минута.

image

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

В общем, добавляем маршрут с указанием следующих данных:
Dst. Address = 8.8.8.8 // Указываем, что будем пинговать DNS-сервер Гугла (для меня не критично, указываю его);
Gateway = pppoe-main // То самое PPPoE-соединение на основной канал
Distance = 1
Остальные параметры оставляем как есть.

image

Всё!

Отныне принцип работы следующий:
Netwatch через основной канал будет проверять пинг до DNS-сервера Google. Как только пинг пропадет, выполнится скрипт "change-to-reserv", указанный на вкладке "Down". Данный скрипт отключит основной маршрут (PPPoE) и все пакеты будут идти по резервному каналу. Как только пинг по основному каналу возобновится, скрипт вновь активирует маршрут основного канала (параметр Distance которого, разумеется, "1", а резервного — "2"). Вместе с этим будут приходить уведомления на email-адрес о фактах изменения состояния.

Profit!

ВНИМАНИЕ!!! Для работы скриптов под управлением RouterOS 6.17 необходимо внести изменения в скрипт отправки email-адреса, а именно убрать параметр "tls=".
То есть, наш код (например, для переключения на резервный канал) будет иметь вид:

/ip route set gateway=1.1.1.1 [find dst-address=0.0.0.0/0];
/tool e-mail send server=192.168.1.1 port=25 user=robot@mysite.ru password=1PaSsW0rD1 to=admin@mysite.ru from="ROBOT<robot@mysite.ru>" \
subject="MikroTik: $[/system clock get date], $[/system clock get time]" \
body="Переключение на резервный канал\nДата: $[/system clock get date]\nAВремя: $[/system clock get time]";


UPDATED: Изменены маршруты в скриптах
UPDATED 2: Чтобы во входящей почте не отображался email-адрес «robot@mysite.ru» как отправителя, был изменен параметр «from» (исправления с комментариями внесены в код выше)
Андрей Николаевич @Helldar
карма
12,2
рейтинг 0,0
Full-stack PHP Developer, Sysadmin
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (27)

  • +6
    wiki.mikrotik.com/wiki/Advanced_Routing_Failover_without_Scripting
    Проще, быстрее, надежнее.
    • –3
      Не везде применимо.
      Например используется DSL соединение, модем (шлюз в данном случае), будет отвечать на пинг, а связи (DSL-канала) может не быть.
      • +2
        Прочтите ман внимательно :)
        • +2
          Спасибо)) Буду внимательнее.
          Ваш вариант очень интересен.
  • 0
    Аналогичные скрипты уже не раз выкладывались под микротик. Тем не менее спасибо)

    А вот вам задача актуальная, но менее «боян». Резервный канал в «мирное» время, вполне можно утилизировать и пустить через него часть клиентов.

    Задача расширить маршруты и скрипт с таким условием, чтобы:
    — в обычных условиях часть клиентов (пусть будет некий диапазон ip адресов нашей сети) ходили в интернет через основной канал, а другие (следующий диапазон) через резервный.
    — Но, при падении, какого либо канала, обеспечить доступность всем))
    • 0
      Я подумаю на досуге над этим вопросом :)
    • 0
      Создаете две таблицы маршрутизации. Делите клиентов на группы любым удобным способом. Первую группу — в первую таблицу, вторую группу — во вторую. А дальше крутите маршруты как душе угодно.
  • 0
    Спасибо за подробную инструкцию!
    Вопрос в тему: можно ли на Микротике обеспечить постоянную доступность резервного канала извне? Т.е. чтобы я мог подключиться к роутеру извне через канал с большим distance, который в данный момент не используется для выхода в интернет?
    Причина: например, бывает удобно часть VPN-клиентов пустить через второй канал для балансировки.
    Кроме того, пинг от 8.8.8.8 не всегда означает полную работоспособность. Роутер может думать, что основной канал работает, а я даже не смогу подключиться удаленно, чтобы его переубедить.
    • +1
      Можно. Я для этого настроил себе доступ так:
      IP -> Firewall -> NAT
      Вкладка «General»:
      Chain: dstnat
      Protocol: 6 (tcp)
      Dst. Port: 3389
      Вкладка «Advanced»:
      Src. Address List: (указал список IP-адресов, с которых я разрешаю заходить)

      Вкладка «Action»:
      Action: dst-nat
      To Address: 192.168.1.1
      To Ports: 3389

      И все, после этого на какой бы я IP-адрес (из указанных на вкладке «Advanced») ни зашел — меня пускает :)
    • 0
      По поводу «Причины». У меня ситуация следующая: на основном канале отключили Инет за неуплату. Все браузеры, при попытках открыть сайт, выходят на страницу провайдера, где написано что у меня не оплачено. Если пустить пинг на DNS Гугла, то скрипт работает.
      Возможно, мой способ можно назвать «костылем», но для конторы данного уровня это терпимо, так как основной канал впервые за 4 года «упал» не по причине проблем провайдера. А вообще максимум раз в год он падает ненадолго.
      Это сейчас 3-и сутки начинают идти как канал не работает :)

      К чему я это. Ах да! Возможно решение пинать IP 8.8.8.8 было неверно, зато действенно. Разумеется, если я найду более лучший способ написания скрипта, то приложу ссылку на него, а пока довольствуюсь этим :)
      • 0
        дёргайте wget-ом www.google.com/robots.txt — он всегда будет там, покуда стоит Гугль.
    • +1
      да, нужно маркировать инпут на тот интерфейс и давать ему марк-роутинга через него же. Тоесть то что вошло в ВАН2 через него должно и выйти
      /ip firewall mangle
      add action=mark-connection chain=input comment=Ukrtelecom connection-mark=no-mark in-interface=Ukrtelecom new-connection-mark=ukrtelecom
      add action=mark-routing chain=output connection-mark=ukrtelecom new-routing-mark=ukrtelecom passthrough=no
      Как то так приблизительно. Взял с одного роутера где Укртелеком это резервный канал
  • 0
    еще, кстати, на эту же тему — можно почитать вот тут на русском ;)

    http://podarok66.livejournal.com/4939.html

    Тоже без всякого участия скриптов :) и немного затронута тему распределения нагрузки)
  • 0
    Скажите, вы эту схему проверяли в работе?
    Мне кажется, что минута это много для проверки, за пинги раз в 15 секунд не накажут.
    Если убирается маршрут, то не нужно ли чистить трансляции NAT?
    Можно ли сразу два маршрута по умолчанию иметь?
    • 0
      У меня эта схема даже заработала (правда, слегка адоптированная под свои реалии).

      в моем случае: 1ый ISP (основной — static), 2ой ISP (резерв — PPPoE) failover происходит совсем незаметно для пользователей.

      На тему двух маршрутов — в той же статье описан вариант параллельной работы двух провайдеров для разных целей. У меня такой нужды не было — так что вот за это ручаться совсем не могу.
      • 0
        Не могут пользователи не заметить переход на другого провайдера — порвутся же сессии все. Конечно, если они не пользуются онлайн-мессенджерами всякими, а просто браузерят интернет, то у них могут недогрузиться картинки большие.
        А можете проверить что происходит с правилами сетевой трансляции при удалении маршрута?
        Получается, что если не удалить правила, то сессии будут висеть «в никуда» и заработает только все когда у сессий кончится время жизни?
        • 0
          После Вашего комментария код был обновлен, а именно, убран второй маршрут и схема работает по принципу смены шлюза в записи.
          Обновление записи происходит динамически. Например, открыл юзер страницу в браузере, а в этот момент сменился провайдер. Юзер по ссылке кликает и у него вновь открывается, а о смене он и не заподозрит.
    • 0
      У меня эта схема сейчас работает. Вот прямо сейчас :)
      Я ее отладил, после этого на хабре написал как один из вариантов.
      Я трансляции не очищаю — и так работает :)
      По-умолчанию сразу два? Разве что распределить клиентов по группам чуть выше в комментариях ссылка есть на распределение нагрузки по нескольким провайдерам.
      • 0
        А что будет с вашей схемой, если сломается DNS гугла и на ваши пинги, что по первому, что по второму каналу не будет ответа?

        Не так ли? instagram.com/p/rB8fzSO61G/
        • 0
          Пинг проверяется по одному каналу. Если пинг есть — остается активным основной, а если нет — резервный.
          Если сломается DNS Гугла… Если… Тогда скрипт автоматом всех переведет на резервный канал, ожидая пока его наладят :)
          Вот так он и будет работать ;)
  • 0
    Это всё хорошо, но при переключении роутов не мешало бы конекштрекинг ресетить, что бы старые конекты пошли по новому каналу.
    Есть еще вариант не отключать роуты а переписывать шлюз в маршруте. При таком подходе не надо ресетить контрекинг, так как роут останется прежним, а гетвей будет уже «акутуальным»
    • 0
      В случаях, если используется всего один канал, думаю, так будет правильней…
    • 0
      Дело говоришь! Обновляю статью!
  • 0
    Если основной провайдер раздает настройки через DHCP, предложенная схема не сработает.
    Advanced_Routing_Failover_without_Scripting тоже не сработает.
    Мы заранее не знаем адрес шлюза, а маршрут вида «ip route add dst-address=8.8.4.4/32 distance=1 gateway=ethernet1» не сработает. То есть мы не можем указать интерфейс вместо адреса в маршруте (могли бы, в случае PPP соединения).

    Предлагаю решение:

    1. Пометить DHCP клиент основного провайдера примечанием «Default Route» и включить добавление динамического маршрута.

    2. Добавить в крон скрипт, который
    --а. Ищет dhcp-client с пометкой «Default Route»
    --b. Берет из него адрес шлюза.
    --c. Присваивает проверочному маршруту найденный шлюз.
    Пример такого скрипта.

    3. Добавить Netwatch смотрящий на проверочный маршрут.
    On Up: ip dhcp-client set default-route-distance=1 [find comment=«Default Route»]
    On Down: ip dhcp-client set default-route-distance=10 [find comment=«Default Route»]

    Запасной маршрут должен иметь дистанцию от 2 до 9.
    Внутри Netwatch можно добавить ресет коннекшенов и отправку email

    • 0
      Может этот скрипт подойдет? habrahabr.ru/post/243071/ Только функционал netwatch реализован скриптом.
  • 0
    Если основной провайдер раздает настройки через DHCP, предложенная схема не сработает.
    Advanced_Routing_Failover_without_Scripting тоже не сработает.
    Мы заранее не знаем адрес шлюза, а маршрут вида «ip route add dst-address=8.8.4.4/32 distance=1 gateway=ethernet1» не сработает. То есть мы не можем указать интерфейс вместо адреса в маршруте (могли бы, в случае PPP соединения).

    Предлагаю решение:

    1. Пометить DHCP клиент основного провайдера примечанием «Default Route» и включить добавление динамического маршрута.

    2. Добавить маршрут для проверки основного канала. gateway=любой, address=8.8.4.4, comment=«Check Gateway»

    3. Добавить в крон скрипт, который
    --а. Ищет dhcp-client с пометкой «Default Route»
    --b. Берет из него адрес шлюза.
    --c. Ищет route с пометкой «Check Gateway»
    --c. Присваивает проверочному маршруту найденный шлюз.

    ip route set [find comment="Check Route"] gateway=[/ip dhcp-client get [find comment="Default Route"] value-name=gateway]

    3. Добавить Netwatch смотрящий на проверочный маршрут.
    On Up: ip dhcp-client set default-route-distance=1 [find comment="Default Route"]
    On Down: ip dhcp-client set default-route-distance=10 [find comment="Default Route"]

    Запасной маршрут должен иметь дистанцию от 2 до 9.
    Внутри Netwatch можно добавить ресет коннекшенов и отправку email
  • +1
    Хорошая статья. Единственное когда я попытался ее реализовать без PPP подключений(у обоих провайдеров статика) возникла следующая проблема:
    есть маршрут 8.8.8.8 через провайдера 1.
    Ситуация 1 — у провайдера отпадает шлюз. Все ок, маршрут активен и все переключается.
    Ситуация 2 — физический линк между микротиком и провайдером 1 разрывается. Т.к. интерфейс не активен — маршрут тоже становится неактивен. Это приводит к переключению на резерв, потом начинает пинговаться 8.8.8.8 (маршрут то не работает), скрипт кидает на основной канал, инета нет, кидает обратно. И так постоянно.
    После вариантов переписывания скриптов решил проблему очень просто — создал bridge, и в него засунул ether1 с основным провайдером. Все! Маршрут доступен через bridge, и даже в случае обрыва линка — маршрут на 8.8.8.8 все равно активен, т.к. bridge тоже активен.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.