Наиболее часто задаваемый мне вопрос по использованию рекурсивной маршрутизации звучит так: «Что делать, если основной провайдер назначает нам ip-адрес через dhcp, при этом часто изменяется шлюз по-умолчанию?».
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) должно происходить тогда, когда доступ в Интернет через основного провайдера становится невозможным.
Изюминкой от провайдера для подобной схемы является периодическая произвольная смена не только IP-адреса клиента, но и default-gateway.
До версии 6.39 мне приходилось видеть весьма изощренные костыли в различных комбинациях sheduler, netwatch и тому подобных механизмов.
Начиная с версии 6.39 разработчики RouterOS пошли навстречу таким пользователям и создали возможность вызывать специальный скрипт при срабатывании dhcp-клиента на устройстве.
Собственно решение состоит из двух частей:
Итак, начнём с конца.
Создадим резервный маршрут через «ISP-2» со значением «distance» больше, чем у будущего основного. В данном примере я использовал «distance=2»:
Далее, для того, чтобы получать от провайдера «ISP-1» маршрут по-умолчанию, но прямо его не использовать, существует специальное значение «distance=255». Маршрут с таким значением distance попадет в системную таблицу маршрутизации, но никогда не станет активным.
Такой маршрут нужен нам только для чтения присланных провайдером параметров и внедрением их в настройки рекурсивных маршрутов посредством скрипта.
Из полученных параметров, нас более других интересует переменная $gateway-address. Как можно догадаться из названия, она содержит в себе адрес шлюза по-умолчанию в сети провайдера. Её мы и будем использовать, чтобы привести рекурсивные маршруты в актуальное состояние.
Сами же рекурсивные маршруты должны быть корректно опознаны из скрипта. Для этого, на этапе их создания мы укажем уникальный «comment», который и будет использоваться для их поиска внутри таблицы. Код создания рекурсивной пары маршрутов:
Первая строка должна (и будет!) указывать на настоящий шлюз в сети провайдера лишь после того, как провайдер выдаст параметры по dhcp и они будут обработаны посредством dhcp-client script:
Теперь, при получении от провайдера «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...». Это значит маршрут построился именно как рекурсивный.
В завершении, исключительно для примера — скрин окна винбокса:
Warning! материалы и схемы в данной статье упрощены до примитивизма с целью дать общее понятие о методе решения проблемы. Без углубления в частности.
Для чего нужна рекурсивная маршрутизация? Для мониторинга наличия интернета за шлюзом провайдера. Ведь нередко случается, что маршрутизатор провайдера прекрасно отвечает на эхо-запросы, но [ап]линк в глобальную сеть у провайдера о какой-то причине пропал.
Рекурсивная маршрутизация позволяет оценить наличие доступа в Интернет через выбранного провайдера и принять решение о маршрутизации трафика.
Однако, дело в том, что использование рекурсивной маршрутизации предполагает
Магия рекурсивной маршрутизации прячется за параметрами «scope» и «target-scope». Чтобы маршрут работал как рекурсивный, его «target-scope» должен быть больше или равен значению «scope» у статического маршрута на который он ссылается рекурсивно, а указанный в маршруте шлюз лежал вне прямой досягаемости через один из интерфейсов.
Рассмотрим простейшую схему Active/Backup. Наш маршрутизатор выполнятет NAT и подключен к двум провайдерам посредством интерфейсов Ether1-isp1 и Ether2-isp2. Основной провайдер (ISP-1) раздаёт своим клиентам IP-адреса посредством протокола DHCP и никак иначе. Второй провайдер предоставляет нам статический IP-адрес, но значительно меньшую скорость.
Переключение на запасного (ISP-2) должно происходить тогда, когда доступ в Интернет через основного провайдера становится невозможным.
Изюминкой от провайдера для подобной схемы является периодическая произвольная смена не только IP-адреса клиента, но и default-gateway.
До версии 6.39 мне приходилось видеть весьма изощренные костыли в различных комбинациях sheduler, netwatch и тому подобных механизмов.
Начиная с версии 6.39 разработчики RouterOS пошли навстречу таким пользователям и создали возможность вызывать специальный скрипт при срабатывании dhcp-клиента на устройстве.
Собственно решение состоит из двух частей:
- нужно получить по протоколу dhcp от провайдера IP-адрес и адрес шлюза для использования в рекурсивных маршрутах
- полученный от провайдера адрес шлюза из автоматического использования по возможности исключить.
Итак, начнём с конца.
Создадим резервный маршрут через «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...». Это значит маршрут построился именно как рекурсивный.
В завершении, исключительно для примера — скрин окна винбокса:
Комментарии (4)
simplix
31.10.2018 00:10Уже давненько можно вешать скрипт на DHCP Client и этот огород с рекурсивными маршрутами не нужен.
nkusnetsov Автор
31.10.2018 05:59и этот огород с рекурсивными маршрутами не нужен
Похоже, Вы вообще не понимаете для чего нужна рекурсивная маршрутизация.
Да, в dhcp-client скрипт появился давно, с выходом 6.39.rcxx Только многие его до сих пор «не заметили». Именно поэтому, такой вопрос возникает у людей с завидной периодичностью. О том и статья.
MagicGTS
Тут habr.com/post/331544 есть скрипт который учитывает состояние гонки при работе DHCP cllient, да еще его можно использовать и без DHCP для формирования маршрутов.
nkusnetsov Автор
Спасибо. Хороший скрипт. Много труда в него вложено. Но начинающие в нем заблудятся.
Моя статья написана как раз для упрощения понимания решения проблемы с dhcp.