Два провайдера: отказоустойчивость и распределение нагрузки (Продолжение)

Раздел для тех, кто начинает знакомиться с MikroTik
Правила форума
Как правильно оформить вопрос.
Прежде чем начать настройку роутера, представьте, как это работает. Попробуйте почитать статьи об устройстве интернет-сетей. Убедитесь, что всё, что Вы задумали выполнимо вообще и на данном оборудовании в частности.
Не нужно изначально строить Наполеоновских планов. Попробуйте настроить простейшую конфигурацию, а усложнения добавлять в случае успеха постепенно.
Пожалуйста, не игнорируйте правила русского языка. Отсутствие знаков препинания и неграмотность автора топика для многих гуру достаточный повод проигнорировать топик вообще.

1. Назовите технологию подключения (динамический DHCP, L2TP, PPTP или что-то иное)
2. Изучите темку "Действия до настройки роутера".
viewtopic.php?f=15&t=2083
3. Настройте согласно выбранного Вами мануала
4. Дочитайте мануал до конца и без пропусков, в 70% случаев люди просто не до конца читают статью и пропускают важные моменты.
5. Если не получается, в Winbox открываем терминал и вбиваем там /export hide-sensitive. Результат в топик под кат, интимные подробности типа личных IP изменить на другие, пароль забить звездочками.
6. Нарисуйте Вашу сеть, рисунок (схему) сюда. На словах может быть одно, в действительности другое.
Аватара пользователя
Barvinok
Сообщения: 104
Зарегистрирован: 28 фев 2012, 23:21

Эта статья - прямое продолжение темы двух провайдеров, поднятой мною более восьми лет назад.
Тогда я подробно описал модель OSI и начальной настройки. Однако, полноценной отказоустойчивости и распределения нагрузки я тогда не достиг.
Задачка оказалась совсем не простой. Надо сказать, что спустя восемь лет я склоняюсь к мысли, что она не имеет полного и окончательного решения - чуть позже я объясню почему.
Но полагаю, что мне удалось приблизиться к заветной цели настолько, насколько это вообще возможно на сегодняшнем уровне развития RouterOS.

Важным граничным условием задачи было использование существующих механизмов - без скриптинга и множества правил маркировки.

Итак, приступим!
Вернее, продолжим.
Я рассмотрю три случая настроек подключения:
  • Static IP - вбиваем адреса, шлюз и DNS руками;
  • PPPoE - всё получаем от провайдера используя имя и пароль;
  • DHCP - просто получаем все настройки втыкая кабель в порт роутера.
Фигура первая, статическая
Укажем адреса на интерфейсах:

Код: Выделить всё

/ip address
add address=80.72.223.114/30 interface=ether1-TTK
add address=31.23.202.41/30 interface=ether2-Rostelecom 
Пропишем DNS

Код: Выделить всё

/ip dns
set allow-remote-requests=yes servers=80.72.225.2,80.72.230.2, 80.254.108.202,80.254.108.194
Первая пара относится к TTK, вторая - к Ростелекому. Чуть позже нам предстоит разрулить обращения к ним по соответствующим каналам.
Прописываем маршруты:

Код: Выделить всё

/ip route
add check-gateway=arp distance=1 gateway=80.72.224.115
add check-gateway=arp distance=2 gateway=31.23.202.42
add check-gateway=ping distance=1 gateway=31.23.202.42 routing-mark=RT_table
Что здесь происходит?
Во первой строке я назначил шлюз провайдера ТТК как маршрут по умолчанию в основной таблице маршрутизации (main).
Доступность шлюза я проверяю используя протокол уровня Ethernet.
Во-второй строкой я прописал шлюз Ростелекома, указав, что он менее предпочтителен, в сравнении с TTK (distance=2).
Третьей строкой я прописал шлюз Ростелекома маршрутом по умолчанию в таблице RT_table. Доступность шлюза проверяю через ping. Оба способа (arp и ping) будут работать одновременно. Все маршруты Ростелекома лягут независимо от того, на каком правиле первей сработает проверка.

Напомню, что в таблице маршрутизации может быть лишь один действующий маршрут по умолчанию.
При данной настройке весь трафик будет идти через ТТК. Если ТТК отвалится - трафик тут же потечёт через Ростелеком.
Отказоустойчивость есть, балансировки - нет.
Но мы же не зря написали третью строчку.
Надо завернуть в неё часть трафика правилами:

Код: Выделить всё

/ip route rule
add comment="DNS RT" dst-address=80.254.0.0/16 table=RT_table
add comment="Torrent NAS" src-address=192.168.25.240/32 table=RT_table
Я завернул в канал Ростелекома все обращения к DNS-серверам Ростелекома и трафик торрент-качалки.

Для внешнего подключения к минорному интерфейсу (где distance=2) придётся использовать метку соединений:

Код: Выделить всё

/ip firewall mangle
add action=mark-connection chain=input connection-state=new dst-address=31.23.202.41 new-connection-mark=RT_conn
add action=mark-routing chain=output connection-mark=RT_conn new-routing-mark=RT_table
Можно сделать чуть по другому:

Код: Выделить всё

/ip route
add check-gateway=arp distance=1 gateway=80.72.224.115 routing-mark=TTK_table
add check-gateway=ping distance=1 gateway=31.23.202.42 routing-mark=RT_table
add check-gateway=ping distance=1 gateway=80.72.224.115%ether1-TTK,31.23.202.42%ether2-Rostelecom
Прописываем маршруты по умолчанию для таблиц TTK_table и RT_table.
В основной таблице пишем оба маршрута через запятую включая ECMP (равномерное распределение соединений).
Это не значит, что трафик будет распределён равномерно. Никто и никогда заранее не угадает через какое соединение вдруг пойдёт закачка большого файла или просмотр видео.
Равномерно распределятся именно соединения.

Разрулим обращения к DNS-серверам:

Код: Выделить всё

/ip route rule
add comment="DNS RT" dst-address=80.254.0.0/16 table=RT_table
add comment="DNS TTK" dst-address=80.72.0.0/16 table=TTK_table
Понятно, что так же можно направить трафик произвольных хостов или подсетей.
Или исходящие подключения туннелей (VPN работает лучше внутри сети одного провайдера).

И ещё два слова про NAT.
Вы можете создать список WAN-интерфейсов и сказать:

Код: Выделить всё

/ip firewall nat
add action=masquerade chain=srcnat out-interface-list=WAN src-address=192.168.25.0/24
Но лучше так не делать. Если у вас статика - используйте src-nat, а не masquerade.

Код: Выделить всё

/ip firewall nat
add action=src-nat chain=srcnat out-interface=ether1-TTK src-address=192.168.25.0/24 to-addresses=80.72.223.114
[... и таки да - отдельное правило для каждого интерфейса]
Фигура вторая, двуточечная

Код: Выделить всё

/interface pppoe-client
add name=TTK add-default-route=yes default-route-distance=1 interface=ether1-TTK use-peer-dns=yes user=yyyyyyyy password=xxxxxxx 
add name=RT add-default-route=yes default-route-distance=2 interface=ether2-Rostelecom use-peer-dns=yes user=yyyyyyyy password=xxxxxxx 
При подключении PPPoE провайдер выдаёт адрес и все настройки (Gateway, DNS, NTP...). Хотелось бы использовать всё это богатство, а не прописывать руками.
К тому же все означенные настройки могут время от времени меняться.
Но как в таком случае задать routing-mark и check-gateway?
Есть два способа. Первый - виртуальная таблица маршрутизации:

Код: Выделить всё

/ip route vrf
add interfaces=RT routing-mark=RT_table
Так мы сделали для интерфейса RT отдельную таблицу маршрутизации.
В /ip route наше PPPoE подключение к Ростелекому будет с меткой routing-mark=RT_table
Мы можем направить туда часть трафика с помощью правил /ip route rule, но если канал Ростелекома упадёт - то опаньки.
Переключения на ТТК не случится. Поэтому для целей отказоустойчивости используем второй способ:

Код: Выделить всё

/routing filter
add chain=dynamic-in distance=2 set-check-gateway=ping set-routing-mark=RT_table
Мы находим динамические подключения с distance=2 (в нашем примере это PPPoE Ростелекома) и назначаем ему метку маршрута (сиречь отдельную таблицу маршрутизации) и проверку шлюза.
В /ip route всё будет выглядеть и работать ровно так же, как при VRF. Но если маршрут помрёт - назначенный ему трафик пойдёт через таблицу main, где основным маршрутом будет ТТК.

В данном случае ECMP будет работать по имени интерфейса:

Код: Выделить всё

/ip route
add check-gateway=ping distance=1 gateway=TTK,TTK,RT
Так два из трёх соединений будет идти через ТТК.
Понятно, в основной таблице не должно быть других маршрутов с distance=1.
Значит ТТК надо убрать в отдельную таблицу маршрутизации

Код: Выделить всё

/routing filter
add chain=dynamic-in distance=1 set-check-gateway=ping set-routing-mark=TTK_table
Либо сделать default-route-distance=3 в /interface pppoe-client

Фигура третья, динамическая
Мы получаем от провайдера произвольный адрес и прочие настройки по DHCP.
Не только выдаваемый вам адрес, но и gateway и DNS могут менять время от времени.
Да, мы умеем назначать разные таблицы маршрутизации при помощи /routing filter и направлять в них трафик при помощи правил /ip route rule.
Но как включить ECMP?
Имена интерфейсов в данном случае не работают. Только прямое указание ip шлюза (и желательно с указанием интерфейса, через который он достижим - будет работать быстрее):

Код: Выделить всё

/ip route
add check-gateway=ping comment="Main Gateway" distance=1 gateway=80.72.224.115%ether1-TTK,31.23.202.42%ether2-Rostelecom
Провайдер время от времени меняет адреса шлюзов. И тут нам, к сожалению, не обойтись без скриптов (это подтвердила техподдержка Микротика).
Создадим скрипт SetGW4ECMP следующего содержания:

Код: Выделить всё

:local TTK_GW [/ip dhcp-client get [find interface=ether1-TTK] gateway]
:local RT_GW [/ip dhcp-client get [find interface=ether2-Rostelecom] gateway]
/ip route set [find comment ="Main Gateway"] gateway="$TTK_GW%ether1-TTK,$RT_GW%ether2-Rostelecom"
Будем запускать скрипт при получении/обновлении адреса на обоих интерфейсах:

Код: Выделить всё

/ip dhcp-client
set 0,1 script=SetGW4ECMP
Не забываем разруливать обращения к DNS ну и всякое, о чём я писал выше.

Post scriptum
Так же не могу не упомянуть про новый механизм detect-internet.

Код: Выделить всё

/interface list
add name=WAN
add name=LAN
add name=Inet

/interface list member
add interface=ether1-TTK list=WAN
add interface=ether2-Rostelecom list=WAN

/interface detect-internet
set detect-interface-list=WAN internet-interface-list=Inet wan-interface-list=WAN
Пока он просто показывает наличие интернета на интерфейсе, что можно использовать в скриптах

Код: Выделить всё

:put [/interface detect-internet state get [find name=ether1-TTK] state]
ineternet
Но микротиковцы работают над этим и кто знает, может в ближайшее время нас ожидает check-gateway=detect-internet или что-то подобное.

За сим разрешите откланяться.
Удачи на маршрутах ;)
Последний раз редактировалось Barvinok 27 апр 2021, 22:45, всего редактировалось 4 раза.


xvo
Сообщения: 4230
Зарегистрирован: 25 фев 2018, 22:41
Откуда: Москва

Barvinok писал(а): 22 апр 2021, 01:50 Запускать скрипт достаточно раз в сутки:
Ну то есть если у провайдера авария, и после нее он выдал новый адрес (а возможно и новый шлюз), то при известной доле невезения интернет через этот канал появится только на следующий день? :-)

Этот скрипт вообще нужно запускать не через scheduler, а напрямую через dhcp-клиента: получил новый адрес - обновил все маршруты, роутинг-правила, src или local адреса на туннелях (ну в общем везде, где адрес фигурировал), и то же самое про gateway - сменился, обновить, нет - не трогать.


Telegram: @thexvo
Аватара пользователя
Barvinok
Сообщения: 104
Зарегистрирован: 28 фев 2012, 23:21

Не.. Просто некоторое время интернет будет гулять только через второй канал.
Конечно, можно и чаще обновлять хоть каждый час: хозяин - барин.
Я не в восторге от такого решения, но другого не нашёл (

Запуск скрипта из DHCP-клиента - класс, я не знал о таком!
У нас многие провайдеры выдают адрес на 3 -5 часов. Хорошо бы встроить проверку, что бы он не вносил запись, если адрес шлюза не менялся? Или есть некий механизм - что бы скрипт даже не запускался в этом случае?
Читаю...

Я вообще открыл вторю часть, что бы глубже изучить малоизвестные механизмы RouterOS, позволяющие избавиться от скриптинга и десятков правил...


xvo
Сообщения: 4230
Зарегистрирован: 25 фев 2018, 22:41
Откуда: Москва

Проверки вы сами делаете.

Вот пример минимального скрипта, который при необходимости меняет:
1) local-address у gre-туннеля и правило в route-rule при смене адреса (чтобы туннель строился через нужный wan с обновленным адресом);
2) gateway в маршруте, при смене gateway.

Код: Выделить всё

{
    :if ($bound=1) do={
       :local test1[/interface gre find where name="название_туннеля"]
       :if ([/interface gre get $test1 local-address] != $"lease-address") do={
          :local test2 [/ip route find where comment="комментарий_к_маршруту"]
          :if ([/ip route get $test2 gateway] != $"gateway-address") do={
              /ip route set $test2 gateway=$"gateway-address"
          }
           /interface gre set $test1 local-address=$"lease-address" disabled=yes
           /ip route rule set  [find where comment="комментарий_к_правилу"] src-address=$"lease-address"
           :delay 30
           /interface gre set $test1 disabled=no
        }
    } 
}
На самом деле там скрипт больше, и он меняет много разных правил и много разных туннелей, но я сократил для наглядности.

В данном случае для хранения текущего адреса используется поле в туннеле (все равно он там нужен), но это не самое fool-proof решение - туннель может перестать быть нужным, а если его удалить - скрипт отрабатывать перестанет.
Правильнее хранить текущий адрес создав запись в layer7.

Маршрут, само собой, не динамический, а создан руками.


Telegram: @thexvo
xvo
Сообщения: 4230
Зарегистрирован: 25 фев 2018, 22:41
Откуда: Москва

Barvinok писал(а): 22 апр 2021, 11:06 Не.. Просто некоторое время интернет будет гулять только через второй канал.
А при внезапном падении второго канала? :-)
В общем такое решение вообще не катит.


Telegram: @thexvo
Аватара пользователя
Barvinok
Сообщения: 104
Зарегистрирован: 28 фев 2012, 23:21

Если внезапно откажут оба канала - доступа в интернет не будет!
===Искренне Ваш, Капитан Очевидность===

Вопрос в том, как сделать ECMP при DHCP без скриптов.
Ну или что бы скрит срабатывал только в случае изменения адреса шлюза, а не дёргать попусту (неважно, по расписанию или по истечении срока аренды).


xvo
Сообщения: 4230
Зарегистрирован: 25 фев 2018, 22:41
Откуда: Москва

Barvinok писал(а): 22 апр 2021, 15:59 Если внезапно откажут оба канала - доступа в интернет не будет!
===Искренне Ваш, Капитан Очевидность===
Да, но только один из каналов то по факту рабочий будет, и только из-за кривизны скрипта не будет работать.

Barvinok писал(а): 22 апр 2021, 15:59 Вопрос в том, как сделать ECMP при DHCP без скриптов.
Ну или что бы скрит срабатывал только в случае изменения адреса шлюза, а не дёргать попусту (неважно, по расписанию или по истечении срока аренды).
А зачем?
Чем вам скрипт в DHCP не угодил?
И если б вы его почитали, то увидели, что он проверяет и если адрес (шлюз) не меняется, то он и делает ничего.

Да и вообще, вы как-то много вопросов задаете для человека, который решил писать статью по теме... :-)


Telegram: @thexvo
Аватара пользователя
Barvinok
Сообщения: 104
Зарегистрирован: 28 фев 2012, 23:21

Поправил.
Пусть запускает скрипт при обновлении IP на любом интерфейсе.
Без всяких проверок - думаю, большой беды не будет.


Аватара пользователя
Barvinok
Сообщения: 104
Зарегистрирован: 28 фев 2012, 23:21

Ещё одна задача, которая не давала мне покоя несколько лет.
Как направить клиентов WiFi через определённого провайдера?
Напрашивается настройка mark-connection или mark-routing в /interface wireless, но её нет.

Обычно в таких случаях делают отдельную подсеть. И ещё одну для гостевого WiFi.
Выглядит безрадостно.
Ещё можно включить use-ip-firewall в /interface bridge settings, что позволит помечать соединения в mangle по признаку интерфейса. Но это существенная нагрузка на процессор.

Собственно, мне просто нужен список адресов клиентов, подключенных по WiFi!
Но как его получить?
В разделе /interface wireless registration-table отображаются MAC-адреса. Инструмента для разрешения MAC в IP (типа как resolve для DNS) нет!
Значит придётся находить их в разделе /ip arp и вытаскивать адреса скриптом.

В итоге сделал так:

Код: Выделить всё

/ip dhcp-server set 0 lease-script=WiFilist
Скрипт состоит из одной строки:

Код: Выделить всё

:if [/interface wireless registration-table find mac-address=$leaseActMAC] do={/ip firewall address-list add list=src_to_Dom.ru address=$leaseActIP comment="Added by DHCP-server}
В /ip firewall mangle запись

Код: Выделить всё

chain=prerouting action=mark-routing new-routing-mark=DOM.RU_route src-address-list=src_to_Dom.ru
Ну и, естественно, маршрут с routing-mark=DOM.RU_route в /ip route.

Для разового добавления всего списка WiFi-клиентов написал короткий, но не очень то простой скрипт:

Код: Выделить всё

:foreach i in=[/interface wireless registration-table find] do={/ip firewall address-list add list=src_to_Dom.ru address=[/ip arp get [find where mac-address=[/interface wireless registration-table get "$i" mac-address]] address]}


krishtovets
Сообщения: 16
Зарегистрирован: 02 апр 2023, 10:37

Всем привет!
Подкл в роутер 2 провайдера hap ac 2 все работает на отлично с автоматической балансировкой, но не работает удаленное подкл к другому роутеру hap ac lite через протокол wireguard. Что посоветуете?


Ответить