Встроенная в 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

Всё!