Встроенная в MikroTik RouterOS функция обеспечения отказоустойчивости доступа в Интернет(имеется ввиду check-gateway=ping), имеет огромный недостаток: она проверяет доступность шлюза провайдера, а не доступность сети Интернет через этого провайдера.
Подобное решение для Linux я уже описывал, и это можно сказать его «порт» на RouterOS
Имеем 3 канала в Интернет и один в локальную сеть(тут называется DMZ):
/ip address
add address=172.16.16.2/24 broadcast=172.16.16.255 comment=DMZ disabled=no \
interface=ether1-dmz network=172.16.16.0
add address=80.X.255.130/26 broadcast=80.X.255.191 comment=RialKom \
disabled=no interface=ether3-rialkom network=80.X.255.128
add address=212.152.X.55/26 broadcast=212.152.X.63 comment=Inet disabled=\
no interface=ether5-inet network=212.152.X.0
add address=62.X.7.242/29 broadcast=62.X.7.247 comment=Beeline \
disabled=no interface=ether4-beeline network=62.X.7.240
Основные маршруты, которые мы и будем переключать:
/ip route
add comment=GW_1 disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
80.X.255.129 scope=30 target-scope=10
add comment=GW_2 disabled=no distance=2 dst-address=0.0.0.0/0 gateway=\
62.X.7.241 scope=30 target-scope=10
add comment=GW_3 disabled=no distance=3 dst-address=0.0.0.0/0 gateway=\
212.152.X.1 scope=30 target-scope=10
Клиенты должны маскарадиться:
/ip firewall nat
add action=masquerade chain=srcnat comment="" disabled=no src-address=172.16.16.0/24
Сам скрипт, называется CheckINET:
###################################################################
#Name: CheckINET
#Version: 1.0.1
#Created: Andrey Orlov
#Email: tangarus(a)gmail.com
#Web: http://www.tangarus.ru/
#Date: 10.2009
#Description:Автоматическое переключение каналов на RouterOS
####################################################################
#set variables
:local PingCount 3
# www.ya.ru
:local IPToPing 77.88.21.8
:local SrcAddrA 80.X.255.130
:local SrcAddrB 62.X.7.242
:local SrcAddrC 212.152.X.55
#ping gateways with src
:local pingresultA [/ping $IPToPing count=$PingCount src-address=$SrcAddrA]
:local pingresultB [/ping $IPToPing count=$PingCount src-address=$SrcAddrB]
#if link_A is DOWN and link_B is UP then:
:if (($pingresultA=0) && ($pingresultB=$PingCount)) do={
:if ((([/ip route get [find comment="GW_2"] distance]=1)&&([/ip route get [find comment="GW_1"] distance]=2)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "set routes to B"
/ip route set [find comment="GW_2"] distance=1
/ip route set [find comment="GW_1"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
#if link_A is UP and link_B is DOWN then:
:if (($pingresultA=$PingCount) && ($pingresultB=0)) do={
:if ((([/ip route get [find comment="GW_2"] distance]=2)&&([/ip route get [find comment="GW_1"] distance]=1)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "Set routes to A"
/ip route set [find comment="GW_1"] distance=1
/ip route set [find comment="GW_2"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
#if link_A is DOWN and link_B is DOWN:
:if (($pingresultA=0) && ($pingresultB=0)) do={
:if ((([/ip route get [find comment="GW_2"] distance]=3)&&([/ip route get [find comment="GW_1"] distance]=2)&&([/ip route get [find comment="GW_3"] distance]=1))=false) do={
:log warning "Set routes to C"
/ip route set [find comment="GW_3"] distance=1
/ip route set [find comment="GW_1"] distance=2
/ip route set [find comment="GW_2"] distance=3
}
}
# Link A or Link B both are UP:
:if (($pingresultA=$PingCount) && ($pingresultB=$PingCount)) do={
:if ((([/ip route get [find comment="GW_2"] distance]=2)&&([/ip route get [find comment="GW_1"] distance]=1)&&([/ip route get [find comment="GW_3"] distance]=3))=false) do={
:log warning "Set routes to A"
/ip route set [find comment="GW_1"] distance=1
/ip route set [find comment="GW_2"] distance=2
/ip route set [find comment="GW_3"] distance=3
}
}
выполняем его раз в 30 секунд:
/system scheduler
add comment="" disabled=no interval=30s name=CheckINET on-event="/system script run CheckINET" policy=\
reboot,read,write,policy,test,password,sniff,sensitive start-date=jan/01/1970 start-time=00:00:00
Казалось-бы всё, но есть один подводный камень: сейчас выполняя пинг /ping www.ya.ru src-address=212.152.X.55, RouterOS не будет обращать внимания на параметр 212.152.X.55 если этот шлюз недоступен.
Т.е. если он доступен то пакеты будут идти чрез него, но если нет, то через текущий default gw.
Чтобы избежать этого, необходимо помечать соединения на входе интерфейса соответствующей routing mark.
Параллельно это решит проблему «отвечать на тот интерфейс, на который
пришел запрос»: сейчас пингуя интерфейс №2 ответы пойдут через интерфейс
которому принадлежит default gw, и ответа мы не получим.
Добавляем маршруты в именованные таблицы маршрутизации:
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
80.X.255.129 routing-mark=rialkom scope=30 target-scope=10
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
62.X.7.241 routing-mark=beeline scope=30 target-scope=10
add comment="" disabled=no distance=1 dst-address=0.0.0.0/0 gateway=\
212.152.X.1 routing-mark=inet scope=30 target-scope=10
Правила маршрутазиции:
/ip route rule
add action=lookup comment="" disabled=no src-address=212.152.X.55/32 \
table=inet
add action=lookup comment="" disabled=no src-address=62.X.7.242/32 table=\
beeline
add action=lookup comment="" disabled=no src-address=80.X.255.130/32 \
table=rialkom
эти правила нужны, чтобы из внутренней сети были всегда (в не зависимости от текущего рабочего канала) доступны сети провайдеров, я использую для мониторинга:
/ip route rule
add action=lookup comment="" disabled=no dst-address=62.X.7.240/29 table=\
beeline
add action=lookup comment="" disabled=no dst-address=80.X.255.128/26 \
table=rialkom
add action=lookup comment="" disabled=no dst-address=212.152.X.0/26 table=\
inet
Обращаю внимание: routing-mark которые видны через WinBOX в MANGLE,
это таблицы маршрутизации из /ip route (routing-table) и routing-mark'и,
а routing-table там напрямую использовать нельзя!
Т.е. там по непонятным причинам отображаються как routing-mark, так и routing-table.
(UPD: А вот на другом роутере работает и так и так... Хм...)
Нужно их сопоставить:
/ip route rule
add action=lookup comment="" disabled=no routing-mark=rialkom table=rialkom
add action=lookup comment="" disabled=no routing-mark=beeline table=beeline
add action=lookup comment="" disabled=no routing-mark=inet table=inet
Помечаем белый краской спинки пакетиков:
/ip firewall mangle
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=beeline \
passthrough=yes src-address=62.X.7.242
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=inet passthrough=\
yes src-address=212.152.X.55
add action=mark-routing chain=output comment="Local answer to correct if" disabled=no new-routing-mark=rialkom \
passthrough=yes src-address=80.X.255.130
Всё!
Отличное решение...
А если у меня два провайдера и один из них статика а второй PPPoE ?
Если только два канала, то необходимо повыкидывать из скрипта все упоминания о третьем провайдере, это не сложно.
По поводу PPPOE, ему-же тоже выдается какой-то ипишник, а значит данная схема тоже может работать. Необходимо только отдельно обеспечить автоматическое пере подключение PPPOE.
Готовое решение для случая с PPPOE дать не получиться, т.к. надо тестировать и отлаживать.
Вообще практически с любым провайдером можно договориться о другой схеме авторизации, не требующей PPPOE/PPTP.
Интересует такой вопрос, в данной конфигурации происходит ли распределение нагрузки по трем каналам, или остальные два используются как резервные.
Нет, в данном сценарии распределение не происходит.
Примеры с распределением нагрузки есть в документации, например:
wiki.mikrotik.com/wiki/EC..._with_masquerade
wiki.mikrotik.com/wiki/NT..._with_masquerade
wiki.mikrotik.com/wiki/NT...ther_approach%29
wiki.mikrotik.com/wiki/Lo...ultiple_Gateways
У меня версия 2.9.27. 2 канала поднято, оба по 3 Мбит. Расспределяю нагрузку тупо по роутам и адресс-листам. Кому какой исспользовать сам выбираю. Все вроде бы ничего и проверка доступности каналов тоже есть, скрипт как у Вас почти. Только в качестве условия доступности выбраны непосредственно шлюзы провов. А вот чтобы пинговать сайты за этими шлюзами не получается((((( ваш способ попробовал, не выходит, да вообще никак не выходит!!! нехочет оно маркировать output с роутера!!!!! а вот если просто указать в качестве макр роута \main\ то работает. Люди помогите! Маркировка в мангл не работает у меня, все сводится к этому, хотя пакеты prerouting от клиентов отлично маркируются, роутю куда хачу клиентов! а пакеты с самих интерфейсов нет!
По моему, «да вообще никак не выходит!!!» говорит о какой-то системной ошибке: маски где-то перепутаны, или адреса...
Точнее сложно сказать...
Также стоит проверить следующее:
1. Пакеты действительно не помечаются или метка затирается.
Нужно обратить внимание на параметр passthrough и порядок правил в которых происходит установка меток.
2. Пакеты помечаются, но по этим меткам ничего не происходит.
Что-то не так с таблицами маршрутизации или их метками(опечатка в метке?)
Спасибо, очень помогло в настройке у себя.
Только добавил пинг на два хоста, если вдруг один лежит. В итоге есть:
:local IPToPing1 xx.xx.xx.xx
:local IPToPing2 yy.yy.yy.yy
:local pingresultA ([/ping $IPToPing1 count=$PingCount src-address=$SrcAddrA] + [/ping $IPToPing2 count=$PingCount src-address=$SrcAddrA])
:local pingresultB ([/ping $IPToPing1 count=$PingCount src-address=$SrcAddrB] + [/ping $IPToPing2 count=$PingCount src-address=$SrcAddrB])
Ну и при проверке (на примере первого):
:if (($pingresultA=0) && ($pingresultB>=$PingCount)) do={...