Балансировка каналов и резервирование mikrotik

Работа с двумя и больше каналами/настройка логики
Балансировка по тарифам/сегментам/от загруженности трафика на каналах
Резервирование (проверка на наличие интернета и переключение на другой канал)
Разработка логики работы с реальными IP (в случае отвала их канала переход на серые IP другого канала)
Исключения исходящих пакетов (нужные внутренние IP отправляются в нужный канал)
Исключения по точке назначения (настройка доступа к определенному ресурсу через свой канал)
Настройка входящих соединений при работе нескольких каналов

Имеем:
Внешние интерфейсы
ether11=30 mb (основной канал) пример шлюза 10.0.0.1 (240000000 bit) isp1
PCT=100 mb (запасной) пример шлюза 172.16.25.1 (800000000 bit) isp2
Локальный интерфейс 
ether13 local3=10.90.90.0/24 
30.30.30.0/28 подсеть реальников

Задача:
Загружать сначала полностью WAN1, потом новые подключения делать на WAN2
Обеспечить входящим соединениям возврат через свой канал
Сделать доступ к некоторым ресурсам только через свой канал
Настроить резервирование каналов и работу балансировщика в связи с отключением одного из каналов
Обеспечить работу белых IP (нат в случае отвала их канала)
Настроить адрес листы для отправления на адрес назначение через указанный канал и для отправления в указанный канал указанный локальный адрес

Настраиваем входящий трафик:
/ip firewall mangle
add action=mark-connection chain=input comment="Input isp1" in-interface=\
    ether11 new-connection-mark=cin_ISP1 passthrough=no

add action=mark-connection chain=input comment="input isp2" in-interface=PCT \
    new-connection-mark=cin_ISP2 passthrough=no

add action=mark-routing chain=output comment="output isp1" connection-mark=\
    cin_ISP1 new-routing-mark="input isp1" passthrough=no

add action=mark-routing chain=output comment="output isp2" connection-mark=\
    cin_ISP2 new-routing-mark="input isp2" passthrough=no
и прописываем маршруты
/ip routes
add check-gateway=ping distance=1 gateway=10.0.0.1 routing-mark="input isp1"

add check-gateway=ping distance=1 gateway=172.16.25.1 routing-mark="input isp2"

Теперь входящий трафик будет уходить всегда по своему маршруту

Скрипт балансировки (balancingConnections):
:global rx1 "0"
/interface monitor ether11 once do={ 
   :global rx1 $("rx-bits-per-second"); 

:local one 8000000
#/log info message=$rx1

: global MARK

if ($rx1<$one) do={
if ($MARK!=1) do={
/ip firewall mangle set [find comment=multiConnectons] new-connection-mark=inet_con_isp1
/log info message="new connections in isp1"
: global MARK 1
}
} else={
if ($MARK!=2) do={
/ip firewall mangle set [find comment=multiConnectons] new-connection-mark=inet_con_isp2
/log info message="new connections in isp2"
: global MARK 2
}
}

Логика работы:
При превышении порога "one" (в битах) загруженности канала "ether11" скрипт переключает маркировку новых подключений на  "inet_con_isp2", и при нагрузке канала меньше порогового значения ставит метку "inet_con_isp1"
Глобальная переменная MARK нужна, чтобы не перезаписывать каждый раз одинаковые данные.

Добавляем правила маркировки для скрипта
/ip firewall mangle
add action=mark-connection chain=prerouting comment=multiConnectons connection-mark=no-mark dst-address=!10.90.90.0/24 in-interface="ether13 local3" new-connection-mark=inet_con_isp1


add action=mark-routing chain=prerouting comment="for multiConnectons" connection-mark=inet_con_isp1 new-routing-mark=isp1 passthrough=no

add action=mark-routing chain=prerouting comment="for multiConnectons" connection-mark=inet_con_isp2 new-routing-mark=isp2 passthrough=no

Первое правило маркирует новые подключения в зависимости от отработки скрипта balancingConnections, второе и третье отправляет промаркированные соединения по своему маршруту

Маршруты для балансировки:
pref-src -тут и ниже наш IP на mikrotik через который идет маршрутизация, адрес в adddress-list
/ip route 
add check-gateway=ping comment=isp1 distance=1 gateway=10.0.0.1 routing-mark=isp1
add check-gateway=ping comment=isp2 distance=1 gateway=172.16.25.1 routing-mark=isp2

add check-gateway=ping comment=gw1 distance=1 gateway=10.0.0.1
add check-gateway=ping comment=gw2 distance=2 gateway=172.16.25.1

add distance=1 dst-address=10.90.90.0/24 gateway="ether13 local3" pref-src=10.90.90.1 routing-mark=isp1 scope=10
add distance=1 dst-address=10.90.90.0/24 gateway="ether13 local3" pref-src=10.90.90.1 routing-mark=isp2 scope=10

#Отправляем белые IP на свой интерфейс
add distance=1 dst-address=30.30.30.0/28 gateway=iLO routing-mark=isp1 scope=10

Дополнительные правила
/ ip firewall mangle
add action=mark-routing chain=prerouting comment=RealIP disabled=yes new-routing-mark=isp2 passthrough=no src-address=30.30.30.0/28
(это правило нужно для ната белых IP, его будет включать и выключать скрипт резервирования при падении основного канала)


add action=mark-routing chain=prerouting comment="SRC address list to isp1" new-routing-mark=isp1 passthrough=no src-address=!30.30.30.0/28 src-address-list="src to isp1"

add action=mark-routing chain=prerouting comment="SRC address list to isp2" new-routing-mark=isp2 passthrough=no src-address=!30.30.30.0/28 src-address-list="src to isp2"

(эти два правила нужны для исключений, отправляют ип из адрес листов SRC address list to isp1 и SRC address list to isp2 на свой канал(не участвуют в балансировке))


add action=mark-routing chain=prerouting comment="address list to isp1" dst-address-list="to isp1" new-routing-mark=isp1 passthrough=no

add action=mark-routing chain=prerouting comment="address list to isp2" dst-address-list="to isp2" new-routing-mark=isp2 passthrough=no


(эти два правила нужны для исключений, по указанным адресам в адрес листах address list to isp1 и address list to isp2 отправляют на свой канал (не участвуют в балансировке))


add action=mark-routing chain=output comment="address list to isp1 output for check ping" dst-address-list="to isp1" new-routing-mark=isp1 passthrough=no
(это правило нужно для проверки доступности интернета через канал ether11)



Скрипт резервирования (check)
:local IP1 8.8.8.8
:local IP2 91.219.241.37
:local IP3 213.59.5.110
:local IP4 80.68.243.243
:local IP5 213.180.193.3
:local IP6 8.8.4.4

:local COUNT 3
:local INTERFACE1 ether11
:local INTERFACE2 PCT

:local RESULT1 false;
if ([/ interface get $INTERFACE1 disabled]) do={
/ log info message="$INTERFACE1 disabled"
} else {
:local STATUS1 ([/ping $IP1 interface=$INTERFACE1 count=$COUNT])
:local STATUS2 ([/ping $IP2 interface=$INTERFACE1 count=$COUNT])
:local STATUS3 ([/ping $IP3 interface=$INTERFACE1 count=$COUNT])
:set RESULT1 (($STATUS1 + $STATUS2 + $STATUS3) >= (2 * $COUNT))
}
:local RESULT2 false;
if ([/ interface get $INTERFACE2 disabled]) do={
/ log info message="$INTERFACE2 disabled"
} else {
if ([/ interface get $INTERFACE2 running]) do={
:local STATUS1 ([/ping $IP4 interface=$INTERFACE2 count=$COUNT])
:local STATUS2 ([/ping $IP5 interface=$INTERFACE2 count=$COUNT])
:local STATUS3 ([/ping $IP6 interface=$INTERFACE2 count=$COUNT])
:set RESULT2 (($STATUS1 + $STATUS2 + $STATUS3) >= (2 * $COUNT))
} else {
/ log error message="$INTERFACE2 not running"
}
}
#Для быстрого переключения
#:local RESULT1 false;
#:local RESULT2 false;

#Для теста результатов проверки адресов
#/ log info message=$RESULT1
#/ log info message=$RESULT2

:global STATUSBALANCING
#Если доступны оба канала 
if ($RESULT1 && $RESULT2 && $STATUSBALANCING!=1) do={
/ ip route set [find comment="gw1"] distance=1
/ ip route set [find comment="gw2"] distance=2
/ ip firewall mangle set [find comment=RealIP]  disabled=yes
/ system scheduler enable balancingConnections
/ log warning message="balancing enabled"
/ ip firewall mangle set [find comment="address list to isp1"] disabled=no
/ ip firewall mangle set [find comment="address list to isp2"] disabled=no
/ ip firewall mangle set [find comment="SRC address list to isp1"] disabled=no
/ ip firewall mangle set [find comment="SRC address list to isp2"] disabled=no
/ ip firewall mangle set [find comment=multiConnectons] new-connection-mark=inet_con_isp1
: global MARK 2
:global STATUSBALANCING 1
} else {

#ISP1 недоступен, ISP2 доступен
if (!$RESULT1 && $RESULT2 && $STATUSBALANCING!=2) do={
/ ip route set [find comment="gw1"] distance=2
/ ip route set [find comment="gw2"] distance=1
/ log error message="internet for $INTERFACE1 not working"
/ ip firewall mangle set [find comment=RealIP]  disabled=no
/ log error message="Real IP NAT for $INTERFACE2"
/ system scheduler disable balancingConnections
/ log error message="balancing disabled"
/ ip firewall mangle set [find comment=multiConnectons] new-connection-mark=inet_con_isp2
/ ip firewall mangle set [find comment="address list to isp1"] disabled=yes
/ ip firewall mangle set [find comment="address list to isp2"] disabled=no
/ ip firewall mangle set [find comment="SRC address list to isp1"] disabled=yes
/ ip firewall mangle set [find comment="SRC address list to isp2"] disabled=no
/ interface disable $INTERFACE1
/ ip firewall connection tracking set enabled=no
#/ ip firewall connection {:foreach r in=[find connection-mark="inet_con_isp1"] do={remove $r}}
/ delay 5
/ ip firewall connection tracking set enabled=yes
/ interface enable $INTERFACE1
:global STATUSBALANCING 2
} else {

#ISP1 доступен, ISP2 недоступен
if ($RESULT1 && !$RESULT2 && $STATUSBALANCING!=3) do={
/ ip route set [find comment="gw1"] distance=1
/ ip route set [find comment="gw2"] distance=2
/ log error message="internet for $INTERFACE2 not working"
/ ip firewall mangle set [find comment=RealIP]  disabled=yes
/ system scheduler disable balancingConnections
/ log error message="balancing disabled"
/ ip firewall mangle set [find comment="address list to isp1"] disabled=no
/ ip firewall mangle set [find comment="address list to isp2"] disabled=yes
/ ip firewall mangle set [find comment="SRC address list to isp1"] disabled=no
/ ip firewall mangle set [find comment="SRC address list to isp2"] disabled=yes
/ ip firewall mangle set [find comment=multiConnectons] new-connection-mark=inet_con_isp1
/ interface disable $INTERFACE2
/ ip firewall connection tracking set enabled=no
#/ ip firewall connection {:foreach r in=[find connection-mark="inet_con_isp2"] do={remove $r}}
/ delay 5
/ ip firewall connection tracking set enabled=yes
/ interface enable $INTERFACE2
: global STATUSBALANCING 3
}
}
}

Описание работы скрипта check:
Настройки
local IP1-6 - сюда заносим 6 адресов в интернете по которым будет проверка доступности интернета через каналы (1-3 для первого канала, 4-6 для второго канала)
:local COUNT 3 - количество пакетов посылаемых на каждый адрес
:local INTERFACE1 - пишем название первого канала
:local INTERFACE2 - пишем название второго канала
Канал считается рабочим, если 2/3 и более пакетов дошло

#Для быстрого переключения
#:local RESULT1 false;
#:local RESULT2 false;
раскоменчиваем для теста каналов, какой раскоментили, тот и будет считаться недоступным

:global STATUSBALANCING глобальная переменная отвечает за срабатывание логики скрипта только в момент произошедших изменений (избежание ненужных повторов)
STATUSBALANCING=1 - доступны оба канала
STATUSBALANCING=2 - ISP1 недоступен, ISP2 доступен
STATUSBALANCING=3 - ISP1 доступен, ISP2 недоступен

#/ ip firewall connection {:foreach r in=[find connection-mark="inet_con_isp1"] do={remove $r}}
#/ ip firewall connection {:foreach r in=[find connection-mark="inet_con_isp2"] do={remove $r}}
эти строки должны были сбрасывать подключения по нерабочим каналам, но не все подключения сбрасывались, поэтому было сделано по другому,
/ interface disable $INTERFACE2
/ ip firewall connection tracking set enabled=no
/ delay 5

/ ip firewall connection tracking set enabled=yes
то есть сбрасываются все подключения на микротике

Логика работы:
доступны оба канала
выставить маршруты
выключить нат белых ип
включить балансировку
включить правило исключений для доступа к адресу из листа с определенного канала
включить правило исключений для доступа определенного ип к сети интернет через          определенной канал исключая балансировку
выставить глобальный переменные

ISP1 недоступен, ISP2 доступен
выставить дистанцию маршрутов
включить нат белых ип
отключить балансировку
отключить правила исключений которые посылают на канал ISP1
включить маркировку новых соединений только через канал ISP2
сбросить все текущие подключения
выставить глобальный переменные

#ISP1 доступен, ISP2 недоступен
выставить дистанцию маршрутов
выключить нат белых ип
отключить балансировку
отключить правила исключений которые посылают на канал ISP2
включить маркировку новых соединений только через канал ISP1
сбросить все текущие подключения
выставить глобальный переменные


Настройка System-Sheduler
/system scheduler
add disabled=yes interval=5s name=balancingConnections on-event=\
    "/system script run balancingConnections" policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive start-tim
    startup
add interval=3m name=check on-event="/system script run check" policy=\
    ftp,reboot,read,write,policy,test,password,sniff,sensitive start-tim
    startup

**********************************************************************************
Дополнительно

Скрипт для проверки шлюза реальников и переключения на другой канал

:local GATEWAY "217.8.237.104"
:local COUNT "2"
:local REPLY "1"
:local STATUS  ([/ping $GATEWAY interface=ether11 count=$COUNT]-$REPLY);
:if ($STATUS<0) do={
/log error message="script Real ip check isp1 $GATEWAY is down"
/ip firewall mangle set [find comment=RealIP]  disabled=no
} else {
/ip firewall mangle set [find comment=RealIP]  disabled=yes}




Статья с которой была взята основа решения
https://habrahabr.ru/post/190352/
и вторая, с которой взята настройка входящего трафика
https://habrahabr.ru/post/244385/
тут настройка балансировки двух каналов одного провайдера
http://lanmarket.ua/stats/rasshirennye-nastroyki-Mikrotik-RouterOS:-dva-vneshnih-kanala-ot-odnogo-provaydera-


Опросник:
скорость каналов
тип подключения
реальники на абонах, каких каналов
логика балансировки по тарифам/сегментам/от загруженности трафика на каналах

исключения и индивидуальная логика для исходящих запросов и адресов назначения

Комментарии

Отправить комментарий

Популярные сообщения из этого блога

Accel-ppp команды

mikbill расшифровка завершений сессий

Zabbix agent установка и настройка