Резервный канал и failover VPN без задержки
Настройка резервного канала
/routing table
add disabled=no fib name=ISP1
add disabled=no fib name=ISP2
/ip firewall mangle
add action=mark-connection chain=prerouting comment=ISP1 connection-state=new \
in-interface-list=ISP1 new-connection-mark=ISP1 passthrough=yes
add action=mark-routing chain=prerouting comment=ISP1 connection-mark=ISP1 \
in-interface-list=!ISP1 new-routing-mark=ISP1 passthrough=yes
add action=mark-routing chain=prerouting comment=ISP1 connection-mark=ISP2 \
in-interface-list=!ISP2 new-routing-mark=ISP2 passthrough=yes
add action=mark-connection chain=prerouting comment=ISP2 connection-state=new \
in-interface-list=ISP2 new-connection-mark=ISP2 passthrough=yes
add action=mark-routing chain=output comment=ISP1 connection-mark=ISP1 \
new-routing-mark=ISP1 passthrough=yes
add action=mark-routing chain=output comment=ISP2 connection-mark=ISP2 \
new-routing-mark=ISP2 passthrough=yes
add action=mark-connection chain=output comment=ISP1 new-connection-mark=ISP1 \
passthrough=yes src-address=203.0.113.102
add action=mark-connection chain=output comment=ISP2 new-connection-mark=ISP2 \
passthrough=yes src-address=192.168.1.10
/ip route
add comment=ISP1-main disabled=no distance=1 dst-address=0.0.0.0/0 gateway=203.0.113.101 pref-src="" routing-table=ISP1 scope=30 suppress-hw-offload=no target-scope=10
add comment=ISP2-rezerv disabled=no dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-table=ISP2 suppress-hw-offload=no
add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=203.0.113.101
add comment=RsrvGW disabled=no distance=2 dst-address=0.0.0.0/0 gateway=192.168.1.1
Создаем таблицы, маркировки и маршруты.
/routing table
add disabled=no fib name=ISP1
add disabled=no fib name=ISP2
Таблицы нужны для того чтобы мы могли проверять доступность двух каналов постоянно, далее мы маркируем трафик по данным таблицам, это нужно для корректной работы и проверок.
Далее идут роуты ISP1-main и ISP2-rezerv
add comment=ISP1-main disabled=no distance=1 dst-address=0.0.0.0/0 gateway=203.0.113.101 pref-src="" routing-table=ISP1 scope=30 suppress-hw-offload=no target-scope=10
add comment=ISP2-rezerv disabled=no dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-table=ISP2 suppress-hw-offload=no
Эти роуты требуются для постоянного доступа в интернет на таблицах ISP1 и ISP2.
Роуты MainGW и RsrvGW
add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=203.0.113.101
add comment=RsrvGW disabled=no distance=2 dst-address=0.0.0.0/0 gateway=192.168.1.1
Эти роуты требуются для доступа к интернету из локальной сети через определённого провайдера; как мы можем заметить, они имеют разные метрики, и трафик будет проходить через того провайдера, у которого метрика ниже.
Далее потребуется добавить скрипт на переключение и проверку доступности
/system script
add dont-require-permissions=no name=isp_check owner=adminuser policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#Main interface name\r\
\n:global MainIf ether1-wan\r\
\n#Failover interface name\r\
\n:global RsrvIf ether7\r\
\n#Minimall RTT for ping\r\
\n:local MinRtt \"00:00:00.200\"\r\
\n#Minimal ping cout for routeros 7 - 3\r\
\n:local PingCount 3\r\
\n#Ping targets\r\
\n:local PingTargets {1.1.1.1; 8.8.4.4;}\r\
\n:local host\r\
\n:local MainIfInetOk false\r\
\n:local RsrvIfInetOk false\r\
\n:local MainPings 0\r\
\n:local RsrvPings 0\r\
\n:local MainPingRtt 0\r\
\n:local RsrvPingRtt 0\r\
\n:local MainPingRtt 0\r\
\n:local MainPingRttSumm 0\r\
\n:local RsrvPingRtt 0\r\
\n:local RsrvPingRttSumm 0\r\
\n:local MainPingCont 0\r\
\n:local RsrvPingCont 0\r\
\n:local MainPingProblemNum 0\r\
\n:local RsrvPingProblemNum 0\r\
\n:foreach host in=\$PingTargets do={\r\
\n:local res [/ping \$host count=\$PingCount interface=\$MainIf]\r\
\n:set MainPings (\$MainPings + \$res)\r\
\n:local MainPingRttTest [/ping \$host count=\$PingCount interface=\$MainIf as-value]\r\
\n:foreach try in=\$MainPingRttTest do={:set MainPingRtt (\$MainPingRtt + (\$try->\"time\"))}\r\
\n:set MainPingRtt (\$MainPingRtt / [:len \$MainPingRttTest])\r\
\n:if ((\$MainPingRtt < \$MinRtt)) do={:set \$MainPingRtt 1} else={:set MainPingRtt 0}\r\
\n:set \$MainPingRttSumm (\$MainPingRttSumm + \$MainPingRtt)\r\
\n:set \$MainPingRtt 0\r\
\n:set \$MainPingCont (\$MainPingCont + 1)\r\
\n:local res [/ping \$host count=\$PingCount interface=\$RsrvIf]\r\
\n:set RsrvPings (\$RsrvPings + \$res)\r\
\n:local RsrvPingRttTest [/ping \$host count=\$PingCount interface=\$RsrvIf as-value]\r\
\n:foreach try in=\$RsrvPingRttTest do={:set RsrvPingRtt (\$RsrvPingRtt + (\$try->\"time\"))}\r\
\n:set RsrvPingRtt (\$RsrvPingRtt / [:len \$RsrvPingRttTest])\r\
\n:if ((\$RsrvPingRtt < \$MinRtt)) do={:set \$RsrvPingRtt 1} else={:set \$RsrvPingRtt 0}\r\
\n:set \$RsrvPingRttSumm (\$RsrvPingRttSumm + \$RsrvPingRtt)\r\
\n:set \$RsrvPingRtt 0\r\
\n:set \$RsrvPingCont (\$RsrvPingCont + 1)\r\
\n}\r\
\n:set \$MainPingProblemNum ((\$MainPingCont * \$PingCount + \$MainPingCont))\r\
\n:set MainIfInetOk ((\$MainPings + \$MainPingRttSumm) >= (\$MainPingProblemNum - \$MainPingCont))\r\
\n:set \$RsrvPingProblemNum ((\$RsrvPingCont * \$PingCount + \$RsrvPingCont))\r\
\n:set RsrvIfInetOk ((\$RsrvPings + \$RsrvPingRttSumm) >= (\$RsrvPingProblemNum - \$RsrvPingCont))\r\
\n:put \"MainIfInetOk=\$MainIfInetOk\"\r\
\n:put \"RsrvIfInetOk=\$RsrvIfInetOk\"\r\
\n:if (!\$MainIfInetOk) do={\r\
\n/log error \"Main gateway down\"\r\
\n}\r\
\n\r\
\n:if (!\$RsrvIfInetOk) do={\r\
\n/log error \"Reserve gateway error\"\r\
\n}\r\
\n:local MainGWDistance [/ip route get [find comment=\"MainGW\"] distance]\r\
\n:local RsrvGWDistance [/ip route get [find comment=\"RsrvGW\"] distance]\r\
\n:put \"MainGWDistance=\$MainGWDistance\"\r\
\n:put \"RsrvGWDistance=\$RsrvGWDistance\"\r\
\n:if (\$MainIfInetOk && (\$MainGWDistance >= \$RsrvGWDistance)) do={\r\
\n/ip route set [find comment=\"MainGW\"] distance=1\r\
\n/ip route set [find comment=\"RsrvGW\"] distance=2\r\
\n/log info \"switched to main internet connection\"\r\
\n}\r\
\n:if (!\$MainIfInetOk && \$RsrvIfInetOk && (\$MainGWDistance <= \$RsrvGWDistance)) do={\r\
\n/ip route set [find comment=\"MainGW\"] distance=2\r\
\n/ip route set [find comment=\"RsrvGW\"] distance=1\r\
\n/log info \"switched to reserve internet connection\"\r\
\n}"
Добавляем его в автоматическое выполнение
/system scheduler
add interval=30s name=schedule1 on-event=isp_check policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon start-time=startup