Mikrotik OS и автоматическое переключение на резервный канал

В недавнем прошлом в связи с переходом с ADSL на Ethernet представилась отличная возможность попробовать оборудование от Mikrotik. В связи с чем был куплен роутер RB750GL. Железка оказалась превосходной как внешне, так и с точки зрения функционала и надёжности.
В итоге у меня осталось оба канала и было решено настроить резервирование с автоматическим переключением. Стандартные средства переключения шлюзов не покрывают всё многообразие сбоев, поэтому нужно писать свои скрипты.

Конфигурация сети


1. Канал Ehernet от NLink втыкается в первый порт роутера, получает IP по DHCP и поднимает pptp соединение, названное nlink. Это будет основное соединение.
2. Канал ADSL от провайдера Домолинк проходит через DLink-2500 в режиме моста и втыкается во второй порт роутера, поверх поднимается pppoe соединение, названное domolink. Это будет резервное соединение.
3. Порты 3-5 роутера используются для подключения устройств локальное сети.

Настройки роутера


Настройка подключений и маскарадинга для компьютеров локальное сети является тривиальной и детально описана в официальной вики.

При настройке ppp подключений нужно отключить добавление маршрутов по умолчанию, а затем создать статические маршруты разными метриками и подходящими комментариями:
/ip route
add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink scope=30 target-scope=10
add comment=RsrvGW disabled=no distance=2 dst-address=0.0.0.0/0 gateway=domolink scope=30 target-scope=10

Теперь чтобы переключать каналы достаточно изменять параметр distance. Трафик пойдёт через канал с меньшим значением этого параметра.

Скрипты


Установка глобальных параметров при запуске роутера


Скрипт называется set_global_parameters
#Main interface name
:global MainIf nlink
#Reserve interface name
:global RsrvIf domolink
#Main interface ip address
:global MainIfAddress ""
#Reserve interface ip address
:global RsrvIfAddress ""

Определение IP-адресов интерфейсов


Определение IP-адреса основного интерфейса


Скрипт называется define_main_if_ip
:global MainIf
:global MainIfAddress ""
:set MainIfAddress [/ip address get [find interface=$MainIf] address]

Данный скрипт определяет IP-адрес основного интерфейса для доступа в интернет. Если этот интерфейс отсутствует, то скрипт будет завершаться с ошибкой, а в переменной MainIfAddress будет пустая строка.

Определение IP-адреса резервного интерфейса


Скрипт называется define_reserved_if_ip
:global RsrvIf
:global RsrvIfAddress ""
:set RsrvIfAddress [/ip address get [find interface=$RsrvIf] address]

Определение этих адресов вынесено в отдельные скрипты, т.к. эти значения я использую ещё в ряде скриптов на роутере (например, обновление записей в DynDNS), а пользовательские функции тут создавать нельзя. Следует заметить, что напрямую команды определения адресов нельзя использовать в других скриптах, т.к. в случае проблем с интерфейсом они генерируют ошибку и приводят к завершению скрипта.

Переключение каналов


Скрипт называется connection_check
:global MainIf
:global RsrvIf
:global MainIfAddress
:global RsrvIfAddress

:local PingCount 3

#www.ru
:local PingTarget1 194.87.0.50

#ya.ru
:local PingTarget2 87.250.250.203

#google dns
:local PingTarget3 8.8.8.8

#Check main internet connection
:local MainIfInetOk false;

if ($MainIfAddress="") do={delay 5}

if ($MainIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$MainIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$MainIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$MainIf]

:set MainIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

#Check reserved internet connection
:local RsrvIfInetOk false;

if ($RsrvIfAddress="") do={delay 5}

if ($RsrvIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$RsrvIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$RsrvIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$RsrvIf]

:set RsrvIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

:put "MainIfInetOk=$MainIfInetOk"
:put "RsrvIfInetOk=$RsrvIfInetOk"

if (!$MainIfInetOk) do={
/log error "Main internet connection error"
}

if (!$RsrvIfInetOk) do={
/log error "Reserve internet connection error"
}

:local MainGWDistance [/ip route get [find comment="MainGW"] distance]
:local RsrvGWDistance [/ip route get [find comment="RsrvGW"] distance]
:put "MainGWDistance=$MainGWDistance"
:put "RsrvGWDistance=$RsrvGWDistance"

#SetUp gateways
if ($MainIfInetOk && ($MainGWDistance >= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=1
/ip route set [find comment="RsrvGW"] distance=2
/log info "Switch to main internet connection"
}

if (!$MainIfInetOk && $RsrvIfInetOk && ($MainGWDistance <= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=2
/ip route set [find comment="RsrvGW"] distance=1
/log warning "Switch to reserve internet connection"
}


Обратите внимание на пинг через конкретный интерфейс, а так же на критерий признания канала неисправным. Я пингую три разных узла и считаю, что интернет на данном интерфейсе не работает, если приходит меньше 2/3 ответов.

Планировщик


1. Скрипт set_global_parameters запускается один раз при запуске роутера.
2. Скрипты определения IP-адресов запускаются каждые 27 секунд. Такое значение выбрано чтобы минимизировать количество одновременных запусков с основным скриптом.
3. Скрипт connection_check запускается каждую минуту.

Выводы


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

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

    +2
    Осталось добавить метки пакетов\соединений и выпускать уходящий пакет через интерфейс в который он пришел и будет полный шоколад :) как-то так
    /ip firewall mangle
    add action=mark-connection chain=prerouting disabled=no in-interface=nlink-ppp new-connection-mark=nlink_c passthrough=yes
    add action=mark-connection chain=prerouting disabled=no in-interface=dlink-ppp new-connection-mark=dlink_c passthrough=yes
    add action=mark-routing chain=prerouting connection-mark=nlink_c disabled=no new-routing-mark=nlink_r passthrough=yes
    add action=mark-routing chain=prerouting connection-mark=dlink_c disabled=no new-routing-mark=dlink_r passthrough=yes
    

    и к шлюзам в ip\route добавить routing-mark=интерфейс_r на подобии этого:
    /ip route
    add comment=gw-nlink disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink routing-mark=nlink_r scope=30 target-scope=10
    add comment=gw-dlink disabled=no distance=1 dst-address=0.0.0.0/0 gateway=dlink  routing-mark=dlink_r scope=30 target-scope=10
    add comment=gw-def disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink scope=30 target-scope=10
    

    останется только менять у def-gw значение gateway (что аналогично примеру выше)… вот.
      +1
      Failover на микротике делается гораздо проще и без скриптов за счет цепочек гейтвеев:
      wiki.mikrotik.com/wiki/Advanced_Routing_Failover_without_Scripting

      Подсказал бы лучше кто, где найти конвертер из iptables в формат routerOS…
        0
        Спасибо, интересная ссылка. Я правильно понял, что идея в том, чтобы объявить некий удалённый хост фиктивным шлюзом, тогда его доступность можно проверять с помощью стандартных средств Router OS. Но задача переключения шлюза по-умолчанию всё-таки должна решаться внешним скриптом?
          0
          Шлюз используется первый доступный (с сортировкой по distance).
          Смысл в том, что описанный в статье механизм по сути использует рекурсивный маршрут как обычный. То есть правила
          /ip route
          add dst-address=Host1 gateway=GW1 scope=10
          add dst-address=Host2 gateway=GW2 scope=10
          add distance=1 gateway=Host1 routing-mark=ISP1 check-gateway=ping
          add distance=2 gateway=Host2 routing-mark=ISP1 check-gateway=ping

          эквивалентны

          /ip route
          add distance=1 gateway=GW1 routing-mark=ISP1 check-gateway=ping
          add distance=2 gateway=GW2 routing-mark=ISP1 check-gateway=ping

          за тем исключением, что доступность маршрута проверяется пингом не на GWx, а на Hostx. Соответственно пинг не прошел — маршрут считается неактивным и роутер переключается на следующий по distance. Если пинги снова пойдут, роутер переключится обратно.

          Я не до конца понимаю, как эта схема работает, но факт что она работает именно так.
            +1
            Хм, совершенно не очевидное поведение… Видимо надо вдумчиво курить мануал про роутинг на микротике.
          0
          К этому надо попробовать прикрутить vrrp еще, и будет отличное решение в офис!
            0
            wiki.mikrotik.com/wiki/Manual:Interface/VRRP Собственно поддержка там уже есть, никаких проблем кроме чисто технических: как объяснить начальству зачем нужны две (три, четыре...) таких железки, а не одна.
              0
              Да я уже можно сказать настроил, дело только было за переключением каналов.
              Ну объяснять иногда не надо. Коробки кстати у нас на базе Axiomtek NA-813.
              На текущий момент довольно (как готовое решение)

              Хотя я тут хочу взять что нибуть на ARM с 4 сетевыми картами нормальными, но судя по тому, что некто не производит их — это пока что мечты.
          +2
          Возникла идея как реализовать на микротике одну штуку. Полез с работы по удалёнке домой. Потом вспомнил, что «удалённая настройка фаерволла — к выезду». Лучше уж на пару часов отложу.
            0
            PS Кстати, железка такая же дома стоит. Работает отлично. Первый роутер который действительно «настроил и забыл», ни глюков, ни зависаний. И так же первый роутер, который я не боюсь обновлять( ну чисто от нечего делать).
              0
              Согласен на все 100! За 3 месяца ни одной проблемы. С содроганием вспоминаю DLink-2500 в режиме роутера, который пришлось подвесить на верёвочке дабы не перегревался.
              Я сейчас немного жалею, что не удалось купить вот такой RB751G-2HnD, приходиться отдельную точку доступа держать.
                0
                О, у меня как раз RB751G-2HnD. Мощность вайфая для такой мелкой коробочки без внешней антенны меня практически пугает, по всей квартире ловит на 5/5, хотя стоит далеко не в центре.
                  0
                  +1 — у меня 750G второй год. И аптайм почти такой же :)
                    0
                    Когда я покупал этот роутер RB751G-2HnD не было ещё в продаже. Стоит на 1000 дороже. Я бы наверное взял. А сейчас dlink Dir 615 прошитый openwrt работает как точка доступа. Железо у длинка неплохое, но вот родные прошивки — это ужас. ОпенВРТ исправляет положение, но памяти мало, чтобы развернуться на полную мощь такому железу. Было бы флеша 16-32 Мб — отличная вещь бы получилась.
                      0
                      В этом случае хорошо спасает tp-link, они железа обычно не жалеют, а Openwrt или Gargoyle, предоставляют вполне гибкий функционал.
                0
                Не первый раз слышу про Mikrotik. Чем он так хорош? Тем что дешев и работает?
                  0
                  Плюс микротика — огромная гибкость и надёжность за вменяемые деньги.
                  Минус — сложная по сравнению с ширпотребом настройка.
                    0
                    Еще пару вопросов:
                    Настройка только через конфиги/shell?
                    Пробовали в коммерческом применении?
                      0
                      1. Не обязательно. Есть Web-интерфейс и утилита winbox. Мне больше всего нравиться winbox, 99% настроек через нее делаются.
                      2. Смотря что понимать под коммерческим применением. У меня статистика не очень большая, но 3 дружественных офиса пользуются и радуются. Как верно отмечали в комментарии выше: «Настроил и забыл».
                        0
                        Довольно часто продукция микротика используется разными малым и средними провайдерами. Довольно неплохие железяки.
                      0
                      Тем, что сравнительно дешев для своей функциональности и работает получше более именитых аналогов (речь о потребительском сегменте, т.е. zyxel, dlink, netgear, etc)
                      А что касается функциональности… Посмотрите просто на сайте у них. Или RouterOS поставьте на виртуалку и посмотрите. Сравнимо с цисками местами.
                        0
                        Сравнимо с цисками местами.

                        по количеству поддерживаемых функций?
                          0
                          Эм… Если оперировать термином «количество» адекватно, то да.
                            0
                            Тогда, я не совсем понял фразу:
                            А что касается функциональности… Сравнимо с цисками местами.
                              0
                              Вопрос не в номинальном количестве функций, а в возможности решения различных прикладных задач средствами роутера. Это, конечно, зависит от номинального количества поддерживаемых технологий, не без того. Но не только. Отсюда сомнения в адекватности термина.
                        0
                        Много функций, оптимально цена — качества.
                        Гданое не начинайте делать магистральные каналы на них, и потом говорить что они плохи :)
                        0
                        В Латвии, кстати, эти железки продаются значительно дешевле, чем в России.
                          0
                          Есть такое дело :(
                          Для уже упомянутого RB751G-2HnD, разница получается где-то $20 + доставка. Если не лень ждать, то можно на ebay заказать.
                            0
                            Если заказывать толпой, но нормально. Доставка 35 долларов плюс хитрые проценты (немного).
                            Я брал четыре штуки RB751G-2HnD — вышел каждый по 2000 р. со всеми расходами.
                            Брал тут: ru.eurodk.com/catalogue/integrated_solutions
                              0
                              Сорри. Я покупал RB751U-2HnD, вот только никак не пойму чем он сильно отличается от RB751G-2HnD
                                0
                                В 751G 7242, вместо 7241 Atheros CPU (хотя частота одинаковая), RAM 64MB (в отличии от 32 у U версии), ну и конечно же гигабитные порты :)
                                  +1
                                  Я это понимаю. Но зная мощь этих процов, не вижу смысла в этом, ибо гигабит оно все равно не прожует.
                                  Да и гигабитный инет дома не каждый имеет )
                                    0
                                    У моего RB750GL тоже 5 гигабитных портов, так вот 2 у меня выделено для WAN, о остальные объединены в аппаратный свитч — вполне себе шустро работает. Точную скорость не замерял, но точно быстрее 100 Мб.
                                      0
                                      смотря в каком режиме. NAT может и не прожует (зависит от размера пакетов).

                                      в чистом свитчинге — легко.
                                        0
                                        Если зависимость пакеты/с к загрузке проца линейна — то в торрентах у меня должен выдавать 200-250 мбит/с. При 100 мбит/с трафике( всё через PPPoE) загрузка проца колеблется в районе 35-50 %. Это на 750GL
                                          0
                                          У меня дома стоит RB751U-2HnD, инет там 8 Мбит/с всего, поэтому ничего про производительность точно не скажу.

                                          На работе стоит RB750G и инет гигабитный. Так вот при скачке торрентов, при 100 Мбит/с загрузка проца 100%.
                                        0
                                        Скажем так — изначально такие решения не были ориентированы для домашнего сегмента. Говоря о железе — гигабитными порты названы немного лукаво. Сейчас дома работает RB450G, гигабит у него только между 1 и 2 портами, остальные порты — до 650Мбит. Железо в нормальном (не разогнанном и не замедленном) режимах нормально маршрутизирует ~60k & ~65k pps для 1500 и 512 b пакетов соответственно.
                                          0
                                          Смотря чем и как грузить. Если вы будете делать шейперы + крутить правила, то тут и память и проц очень сильно пригодятся. На тему каналов, тут зависит от модели. У меня RB450G, перавый порт полноценный 1gb между остальными, все другие 650.
                                  0
                                  Как бы латвийская компания-производитель.
                                  0
                                  Очень интересный пример, только стоило сначала пообщаться со службой поддержки. Для всех, кто попробует это сделать таким же образом, цитирую.

                                  interface setting for ping is not working for IPv4, that is IPv6 feature only so you could pink Link-Local addresses. If it works for ipv4 that is only coincidence, and it can/will brake even without reboot or version upgrade.

                                  so you could try to ping IPv6 LL address

                                  Проверка валидности интерфейса таким образом некорректна. Для интереса я проверил на 3х разных моделях и разных интерфейсах и действительно, есть случаи, когда пинг через интерфейс не работает!
                                    0
                                    Очень удобно использовать эту комманду, но в RouterOs 6* при добавлении маршрута таким способом пинг не проходит:
                                    /ip route
                                    add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink scope=30 target-scope=10
                                    Для динамического IP мне пришлось писать скрипт

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

                                    Самое читаемое