Фоновая информация: На удалённом объекте у меня есть два подключения. Подключение 1: AT&T Uverse DSL. Подключение 2: Verizon LTE через Cradlepoint в режиме моста. IP-адреса изменены из соображений конфиденциальности. Поскольку Uverse нельзя перевести в мостовой режим, пришлось настроить его с публичными статическими IP на LAN-стороне и включить каскадный маршрутизатор. Эта опция даёт нам наш /29, но при этом ломает проверку шлюза, потому что шлюз всегда "вверх", даже если провайдер отключился. LTE-шлюз находится далеко от устройства, поэтому он работает как надо, но я не хочу, чтобы он стал основным провайдером, если первичный работает. Я настроил правила mangle для маркировки трафика, чтобы он входил и выходил через одного и того же провайдера, и нашёл на вики скрипт для WAN failover, который вроде работает. Если я на первичном подключении, могу выбрать пинг и интерфейс — пинг нормальный, а если выбрать вторичный — пинг задерживается, как и должно быть на LTE. Скрипт запускается каждые 10 секунд, переключается на вторичный при отвале, но не переключается обратно на первичный после восстановления. После переключения не могу пинговать первичный интерфейс — пинги не восстанавливаются, скрипт не возвращает расстояние на шлюзах. Может, кто поможет исправить эту проблему?
/ip firewall mangle
add action=mark-connection chain=input in-interface=ether1-WAN new-connection-mark=isp1-in
add action=mark-routing chain=output connection-mark=isp1-in new-routing-mark=isp1-out passthrough=no
add action=mark-connection chain=input in-interface=ether2-WAN new-connection-mark=isp2-in
add action=mark-routing chain=output connection-mark=isp2-in new-routing-mark=isp2-out passthrough=no
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1-WAN
add action=masquerade chain=srcnat out-interface=ether2-WAN
/ip route
add distance=1 gateway=10.0.0.1 routing-mark=isp1-out
add distance=2 gateway=172.16.0.1 routing-mark=isp2-out
add distance=2 gateway=172.16.0.1
add distance=1 gateway=10.0.0.1
/system scheduler
add interval=10s name=DualWanFailover on-event=DualWanFailover policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=nov/18/2015 start-time=21:51:02
/system script
add name=DualWanFailover owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive source=“# ---- --------------- header -------------------
# Скрипт от Tomas Kirnak, версия 1.0.7
# Если используете этот скрипт, или редактируете и
# используете повторно, пожалуйста, оставьте шапку без изменений.
#
# Подробности и информация на странице вики:
#
# ------------------- header -------------------
# ------------- начало редактирования -------------
# Отредактируйте переменные ниже под свои нужды
# Заполните имена WAN-интерфейсов
:local InterfaceISP1 ether1-WAN
:local InterfaceISP2 ether2-WAN
# Заполните IP-шлюзы (или имена интерфейсов для PPP)
:local GatewayISP1 10.0.0.1
:local GatewayISP2 172.16.0.1
# Заполните адрес для пинга – сейчас: resolver1.opendns.com
:local PingTarget 208.67.222.222
# Сколько пинг-просадок допускается перед переключением
:local FailTreshold 20
# Увеличение расстояния маршрута при сбое
:local DistanceIncrease 2
# Редактировать скрипт ниже не рекомендуется
# -------------- конец редактирования --------------
# Объявляем глобальные переменные
:global PingFailCountISP1
:global PingFailCountISP2
# Инициализируем счётчики, если скрипт запускается первый раз
:if ([:typeof $PingFailCountISP1] = "nothing") do={:set PingFailCountISP1 0}
:if ([:typeof $PingFailCountISP2] = "nothing") do={:set PingFailCountISP2 0}
# Переменная для хранения результата отдельного пинга
:local PingResult
# Проверяем ISP1
:set PingResult [ping $PingTarget count=1 interface=$InterfaceISP1]
:put $PingResult
:if ($PingResult = 0) do={
:if ($PingFailCountISP1 < ($FailTreshold+2)) do={
:set PingFailCountISP1 ($PingFailCountISP1 + 1)
:if ($PingFailCountISP1 = $FailTreshold) do={
:log warning "У ISP1 проблемы с доступом до $PingTarget — увеличиваем дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP1 && static] do={
/ip route set $i distance=([/ip route get $i distance] + $DistanceIncrease)
}
:log warning "Увеличение дистанции маршрутов завершено."
}
}
}
:if ($PingResult = 1) do={
:if ($PingFailCountISP1 > 0) do={
:set PingFailCountISP1 ($PingFailCountISP1 - 1)
:if ($PingFailCountISP1 = ($FailTreshold -1)) do={
:log warning "ISP1 снова доступен на $PingTarget — возвращаем прежнюю дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP1 && static] do={
/ip route set $i distance=([/ip route get $i distance] - $DistanceIncrease)
}
:log warning "Восстановление дистанции маршрутов завершено."
}
}
}
# Проверяем ISP2
:set PingResult [ping $PingTarget count=1 interface=$InterfaceISP2]
:put $PingResult
:if ($PingResult = 0) do={
:if ($PingFailCountISP2 < ($FailTreshold+2)) do={
:set PingFailCountISP2 ($PingFailCountISP2 + 1)
:if ($PingFailCountISP2 = $FailTreshold) do={
:log warning "У ISP2 проблемы с доступом до $PingTarget — увеличиваем дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP2 && static] do={
/ip route set $i distance=([/ip route get $i distance] + $DistanceIncrease)
}
:log warning "Увеличение дистанции маршрутов завершено."
}
}
}
:if ($PingResult = 1) do={
:if ($PingFailCountISP2 > 0) do={
:set PingFailCountISP2 ($PingFailCountISP2 - 1)
:if ($PingFailCountISP2 = ($FailTreshold -1)) do={
:log warning "ISP2 снова доступен на $PingTarget — возвращаем прежнюю дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP2 && static] do={
/ip route set $i distance=([/ip route get $i distance] - $DistanceIncrease)
}
:log warning "Восстановление дистанции маршрутов завершено."
}
}
}”
/ip firewall mangle
add action=mark-connection chain=input in-interface=ether1-WAN new-connection-mark=isp1-in
add action=mark-routing chain=output connection-mark=isp1-in new-routing-mark=isp1-out passthrough=no
add action=mark-connection chain=input in-interface=ether2-WAN new-connection-mark=isp2-in
add action=mark-routing chain=output connection-mark=isp2-in new-routing-mark=isp2-out passthrough=no
/ip firewall nat
add action=masquerade chain=srcnat out-interface=ether1-WAN
add action=masquerade chain=srcnat out-interface=ether2-WAN
/ip route
add distance=1 gateway=10.0.0.1 routing-mark=isp1-out
add distance=2 gateway=172.16.0.1 routing-mark=isp2-out
add distance=2 gateway=172.16.0.1
add distance=1 gateway=10.0.0.1
/system scheduler
add interval=10s name=DualWanFailover on-event=DualWanFailover policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive start-date=nov/18/2015 start-time=21:51:02
/system script
add name=DualWanFailover owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive source=“# ---- --------------- header -------------------
# Скрипт от Tomas Kirnak, версия 1.0.7
# Если используете этот скрипт, или редактируете и
# используете повторно, пожалуйста, оставьте шапку без изменений.
#
# Подробности и информация на странице вики:
#
# ------------------- header -------------------
# ------------- начало редактирования -------------
# Отредактируйте переменные ниже под свои нужды
# Заполните имена WAN-интерфейсов
:local InterfaceISP1 ether1-WAN
:local InterfaceISP2 ether2-WAN
# Заполните IP-шлюзы (или имена интерфейсов для PPP)
:local GatewayISP1 10.0.0.1
:local GatewayISP2 172.16.0.1
# Заполните адрес для пинга – сейчас: resolver1.opendns.com
:local PingTarget 208.67.222.222
# Сколько пинг-просадок допускается перед переключением
:local FailTreshold 20
# Увеличение расстояния маршрута при сбое
:local DistanceIncrease 2
# Редактировать скрипт ниже не рекомендуется
# -------------- конец редактирования --------------
# Объявляем глобальные переменные
:global PingFailCountISP1
:global PingFailCountISP2
# Инициализируем счётчики, если скрипт запускается первый раз
:if ([:typeof $PingFailCountISP1] = "nothing") do={:set PingFailCountISP1 0}
:if ([:typeof $PingFailCountISP2] = "nothing") do={:set PingFailCountISP2 0}
# Переменная для хранения результата отдельного пинга
:local PingResult
# Проверяем ISP1
:set PingResult [ping $PingTarget count=1 interface=$InterfaceISP1]
:put $PingResult
:if ($PingResult = 0) do={
:if ($PingFailCountISP1 < ($FailTreshold+2)) do={
:set PingFailCountISP1 ($PingFailCountISP1 + 1)
:if ($PingFailCountISP1 = $FailTreshold) do={
:log warning "У ISP1 проблемы с доступом до $PingTarget — увеличиваем дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP1 && static] do={
/ip route set $i distance=([/ip route get $i distance] + $DistanceIncrease)
}
:log warning "Увеличение дистанции маршрутов завершено."
}
}
}
:if ($PingResult = 1) do={
:if ($PingFailCountISP1 > 0) do={
:set PingFailCountISP1 ($PingFailCountISP1 - 1)
:if ($PingFailCountISP1 = ($FailTreshold -1)) do={
:log warning "ISP1 снова доступен на $PingTarget — возвращаем прежнюю дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP1 && static] do={
/ip route set $i distance=([/ip route get $i distance] - $DistanceIncrease)
}
:log warning "Восстановление дистанции маршрутов завершено."
}
}
}
# Проверяем ISP2
:set PingResult [ping $PingTarget count=1 interface=$InterfaceISP2]
:put $PingResult
:if ($PingResult = 0) do={
:if ($PingFailCountISP2 < ($FailTreshold+2)) do={
:set PingFailCountISP2 ($PingFailCountISP2 + 1)
:if ($PingFailCountISP2 = $FailTreshold) do={
:log warning "У ISP2 проблемы с доступом до $PingTarget — увеличиваем дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP2 && static] do={
/ip route set $i distance=([/ip route get $i distance] + $DistanceIncrease)
}
:log warning "Увеличение дистанции маршрутов завершено."
}
}
}
:if ($PingResult = 1) do={
:if ($PingFailCountISP2 > 0) do={
:set PingFailCountISP2 ($PingFailCountISP2 - 1)
:if ($PingFailCountISP2 = ($FailTreshold -1)) do={
:log warning "ISP2 снова доступен на $PingTarget — возвращаем прежнюю дистанцию маршрутов."
:foreach i in=[/ip route find gateway=$GatewayISP2 && static] do={
/ip route set $i distance=([/ip route get $i distance] - $DistanceIncrease)
}
:log warning "Восстановление дистанции маршрутов завершено."
}
}
}”
