📜 ⬆️ ⬇️

Mikrotik OS and automatic switching to the backup channel

In the recent past, in connection with the transition from ADSL to Ethernet, there was an excellent opportunity to try Mikrotik equipment. In this connection, the router RB750GL was purchased. The piece of iron turned out to be excellent both externally and in terms of functionality and reliability.
As a result, I still had both channels and it was decided to set up a reservation with automatic switching. Standard means of switching gateways do not cover all the variety of failures, so you need to write your own scripts.

Network configuration


1. The Ehernet channel from NLink is plugged into the first port of the router, receives IP via DHCP and raises the pptp connection, called nlink. This will be the main connection.
2. The ADSL channel from the Domolink provider passes through the DLink-2500 in bridge mode and is plugged into the second port of the router, the pppoe connection called domolink rises. This will be a backup connection.
3. Ports 3-5 of the router are used to connect devices to the local network.

Router settings


Setting up connections and masquerading for computers on the local network is trivial and is described in detail in the official wiki .

When configuring ppp connections, you need to disable adding routes by default, and then create static routes with different metrics and appropriate comments:
/ip route
add comment=MainGW disabled=no distance=1 dst-address=0.0.0.0/0 gateway=nlink scope=30 target-scope=10
add comment=RsrvGW disabled=no distance=2 dst-address=0.0.0.0/0 gateway=domolink scope=30 target-scope=10

Now to switch channels it is enough to change the distance parameter. Traffic will go through the channel with a smaller value for this parameter.
')

Scripts


Setting global parameters when starting a router


The script is called set_global_parameters
#Main interface name
:global MainIf nlink
#Reserve interface name
:global RsrvIf domolink
#Main interface ip address
:global MainIfAddress ""
#Reserve interface ip address
:global RsrvIfAddress ""

Determination of interface IP addresses


Determining the IP address of the main interface


The script is called define_main_if_ip
:global MainIf
:global MainIfAddress ""
:set MainIfAddress [/ip address get [find interface=$MainIf] address]

This script defines the IP address of the main interface for Internet access. If this interface is missing, the script will fail with an error, and the MainIfAddress variable will contain an empty string.

Determining the IP Address of the Backup Interface


The script is called define_reserved_if_ip
:global RsrvIf
:global RsrvIfAddress ""
:set RsrvIfAddress [/ip address get [find interface=$RsrvIf] address]

The definition of these addresses is rendered into separate scripts, since I use these values ​​in a number of scripts on the router (for example, updating records in DynDNS), and user functions cannot be created here. It should be noted that direct address determination commands cannot be used in other scripts, since in case of problems with the interface, they generate an error and lead to the completion of the script.

Channel switching


The script is called connection_check
:global MainIf
:global RsrvIf
:global MainIfAddress
:global RsrvIfAddress

:local PingCount 3

#www.ru
:local PingTarget1 194.87.0.50

#ya.ru
:local PingTarget2 87.250.250.203

#google dns
:local PingTarget3 8.8.8.8

#Check main internet connection
:local MainIfInetOk false;

if ($MainIfAddress="") do={delay 5}

if ($MainIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$MainIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$MainIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$MainIf]

:set MainIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

#Check reserved internet connection
:local RsrvIfInetOk false;

if ($RsrvIfAddress="") do={delay 5}

if ($RsrvIfAddress!="") do={
:local PingResult1 [/ping $PingTarget1 count=$PingCount interface=$RsrvIf]
:local PingResult2 [/ping $PingTarget2 count=$PingCount interface=$RsrvIf]
:local PingResult3 [/ping $PingTarget3 count=$PingCount interface=$RsrvIf]

:set RsrvIfInetOk (($PingResult1 + $PingResult2 + $PingResult3) >= (2 * $PingCount))
}

:put "MainIfInetOk=$MainIfInetOk"
:put "RsrvIfInetOk=$RsrvIfInetOk"

if (!$MainIfInetOk) do={
/log error "Main internet connection error"
}

if (!$RsrvIfInetOk) do={
/log error "Reserve internet connection error"
}

:local MainGWDistance [/ip route get [find comment="MainGW"] distance]
:local RsrvGWDistance [/ip route get [find comment="RsrvGW"] distance]
:put "MainGWDistance=$MainGWDistance"
:put "RsrvGWDistance=$RsrvGWDistance"

#SetUp gateways
if ($MainIfInetOk && ($MainGWDistance >= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=1
/ip route set [find comment="RsrvGW"] distance=2
/log info "Switch to main internet connection"
}

if (!$MainIfInetOk && $RsrvIfInetOk && ($MainGWDistance <= $RsrvGWDistance)) do={
/ip route set [find comment="MainGW"] distance=2
/ip route set [find comment="RsrvGW"] distance=1
/log warning "Switch to reserve internet connection"
}


Pay attention to the ping through a specific interface, as well as the criterion for the recognition of a channel as faulty. I ping three different sites and I believe that the Internet on this interface does not work if less than 2/3 of the responses arrive.

Scheduler


1. The set_global_parameters script is run once when the router is started.
2. IP address detection scripts run every 27 seconds. This value is chosen to minimize the number of simultaneous starts with the main script.
3. The connection_check script runs every minute.

findings


The resulting solution at a minimum cost significantly increased the reliability of my home network and successfully copes with the most sophisticated failures of local providers, while it is sufficiently protected from failures of external network nodes.

Source: https://habr.com/ru/post/141785/


All Articles