Рекурсивная маршрутизация в MikroTik через шлюзы назначемые DHCP

    Наиболее часто задаваемый мне вопрос по использованию рекурсивной маршрутизации звучит так: «Что делать, если основной провайдер назначает нам ip-адрес через dhcp, при этом часто изменяется шлюз по-умолчанию?».

    image

    Warning! материалы и схемы в данной статье упрощены до примитивизма с целью дать общее понятие о методе решения проблемы. Без углубления в частности.

    Для чего нужна рекурсивная маршрутизация? Для мониторинга наличия интернета за шлюзом провайдера. Ведь нередко случается, что маршрутизатор провайдера прекрасно отвечает на эхо-запросы, но [ап]линк в глобальную сеть у провайдера о какой-то причине пропал.

    Рекурсивная маршрутизация позволяет оценить наличие доступа в Интернет через выбранного провайдера и принять решение о маршрутизации трафика.

    Однако, дело в том, что использование рекурсивной маршрутизации предполагает наличие прибитого гвоздями прямое явное указание IP-адреса шлюза среди параметров создаваемого маршрута. Указание в качестве шлюза имени broadcast-интерфейса является неправильным и во многих случаях просто не работает, т.к. требует наличия proxy-arp со стороны провайдера. А еще, вместо провайдера proxy-arp может включить ваш сосед про провайдерскому свитчу и попытаться перехватить таким образом ваш трафик, устроив классический MITM!

    Магия рекурсивной маршрутизации прячется за параметрами «scope» и «target-scope». Чтобы маршрут работал как рекурсивный, его «target-scope» должен быть больше или равен значению «scope» у статического маршрута на который он ссылается рекурсивно, а указанный в маршруте шлюз лежал вне прямой досягаемости через один из интерфейсов.

    Рассмотрим простейшую схему Active/Backup. Наш маршрутизатор выполнятет NAT и подключен к двум провайдерам посредством интерфейсов Ether1-isp1 и Ether2-isp2. Основной провайдер (ISP-1) раздаёт своим клиентам IP-адреса посредством протокола DHCP и никак иначе. Второй провайдер предоставляет нам статический IP-адрес, но значительно меньшую скорость.
    Переключение на запасного (ISP-2) должно происходить тогда, когда доступ в Интернет через основного провайдера становится невозможным.

    image

    Изюминкой от провайдера для подобной схемы является периодическая произвольная смена не только IP-адреса клиента, но и default-gateway.

    До версии 6.39 мне приходилось видеть весьма изощренные костыли в различных комбинациях sheduler, netwatch и тому подобных механизмов.

    Начиная с версии 6.39 разработчики RouterOS пошли навстречу таким пользователям и создали возможность вызывать специальный скрипт при срабатывании dhcp-клиента на устройстве.

    Собственно решение состоит из двух частей:

    1. нужно получить по протоколу dhcp от провайдера IP-адрес и адрес шлюза для использования в рекурсивных маршрутах
    2. полученный от провайдера адрес шлюза из автоматического использования по возможности исключить.

    Итак, начнём с конца.

    Создадим резервный маршрут через «ISP-2» со значением «distance» больше, чем у будущего основного. В данном примере я использовал «distance=2»:

    Backup via ISP-2
    /ip route add dst-address=0.0.0.0/0 gateway=192.0.2.1 distance=2

    Далее, для того, чтобы получать от провайдера «ISP-1» маршрут по-умолчанию, но прямо его не использовать, существует специальное значение «distance=255». Маршрут с таким значением distance попадет в системную таблицу маршрутизации, но никогда не станет активным.

    Код
    /ip dhcp-client add comment="ISP-1 dhcp" default-route-distance=255 dhcp-options=hostname,clientid interface=Ether1-isp1

    Такой маршрут нужен нам только для чтения присланных провайдером параметров и внедрением их в настройки рекурсивных маршрутов посредством скрипта.

    Из полученных параметров, нас более других интересует переменная $gateway-address. Как можно догадаться из названия, она содержит в себе адрес шлюза по-умолчанию в сети провайдера. Её мы и будем использовать, чтобы привести рекурсивные маршруты в актуальное состояние.
    Сами же рекурсивные маршруты должны быть корректно опознаны из скрипта. Для этого, на этапе их создания мы укажем уникальный «comment», который и будет использоваться для их поиска внутри таблицы. Код создания рекурсивной пары маршрутов:

    Создание пары маршрутов
    /ip route add dst-address=8.8.4.4 gateway=127.0.0.1 scope=30 target-scope=30 comment="isp1route" disabled=yes
    /ip route add dst-address=0.0.0.0/0 gateway=8.8.4.4 check-gateway=ping


    Первая строка должна (и будет!) указывать на настоящий шлюз в сети провайдера лишь после того, как провайдер выдаст параметры по dhcp и они будут обработаны посредством dhcp-client script:

    Упрощенный скрипт
    /ip route set [find comment="isp1route"] gateway=($"gateway-address") disabled=no

    Более продвинутый вариант
    :if ($bound=1) do={ /ip route set [find comment="isp1route"] gateway=($"gateway-address")disabled=no; :log warning ("New ISP1 gateway: ".($"gateway-address")) }

    Теперь, при получении от провайдера «ISP-1» IP-адреса для использования в качестве шлюза по-умолчанию, он будет внесен в маршрутную пару вместо «127.0.0.1».
    Вторая строка, где указан маршрут до 0.0.0.0/0, собственно и осуществляет всю магию. Указанный там в качестве шлюза узел 8.8.4.4 будет проверяться на отклик опцией «check-gateway=ping» именно через сеть ISP-1. В случае если узел 8.8.4.4 не ответит дважды на эхо-запросы в течение 20 секунд, маршрутизатор будет считать связь с Интернетом через этот маршрут (ISP-1) недоступной. Новые соединения в этом случае будут направлены через запасного провайдера ISP-2.

    Если всё сделано правильно, то в окне winbox /ip->routes около маршрута до 8.8.4.4 будет видно слова «resursive via...». Это значит маршрут построился именно как рекурсивный.

    В завершении, исключительно для примера — скрин окна винбокса:

    image
    Поделиться публикацией
    Комментарии 6
      0
      Тут habr.com/post/331544 есть скрипт который учитывает состояние гонки при работе DHCP cllient, да еще его можно использовать и без DHCP для формирования маршрутов.
        0
        Спасибо. Хороший скрипт. Много труда в него вложено. Но начинающие в нем заблудятся.
        Моя статья написана как раз для упрощения понимания решения проблемы с dhcp.
        0
        Уже давненько можно вешать скрипт на DHCP Client и этот огород с рекурсивными маршрутами не нужен.
          0
          и этот огород с рекурсивными маршрутами не нужен

          Похоже, Вы вообще не понимаете для чего нужна рекурсивная маршрутизация.
          Да, в dhcp-client скрипт появился давно, с выходом 6.39.rcxx Только многие его до сих пор «не заметили». Именно поэтому, такой вопрос возникает у людей с завидной периодичностью. О том и статья.
          0
          Почему бы просто с помощью скрипта не анализировать каналы, тем же пингом на 8.8.8.8 и на основе этих данных переключать провайдеров если надо. Реализовал себе такое и на динамическом айпи где шлюз и айпи может менятся и скрипт сам все меняет, и в mangle все конекты к провайдерам закинул, все работает как часы
            0
            Потому, что в RouterOS существует штатный инструмент «check-gateway», специально для этого созданный и не требуется городить костылей.

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

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