📜 ⬆️ ⬇️

Mikrotik automatically switch to the backup channel for a dynamic ip address (issued by DHCP)



Greetings, Habr! Due to the poor quality of the line, I was asked to configure automatic switching to the backup channel. For this purpose, provided the router MikroTik RB 951Ui.

I thought that there would be no problems ... Just set up checking the channel and routes. But, unfortunately, both providers give out IP dynamically. At first I tried to substitute the interface name into the route, but the ping did not pass. After reading several articles, including foreign sites, but did not find a solution to the problem that would suit me. I had to get acquainted with RouterOS closer, and in particular with the creation of scripts ...
')

In this OS, you can create a route in two ways:

When creating a route manually, it will not be possible to update the gateway dynamically. To do this, you have to write some fairly large scripts and add a lot of checks. When writing them, I noticed that in RouterOS it is problematic to make complex scripts work. It is very difficult to track the logic of work, although logs and variables were used for verification. The scripts were written, but they were unstable, despite the optimization of the code and the addition of checks. When the number of checks began to grow exponentially and the repeated optimization of the logical scheme slightly improved the situation - I decided to abandon this option and try to use the script option in the script to automatically create a route by the DHCP client.

/ip dhcp-client set [/ip dhcp-client find interface=$Iface] add-default-route=yes [no] 

The option to automatically create a default route is set for the desired interface in the settings of the DHCP client.

So, the script will work according to this algorithm:



Algorithm explanation



A copy of the script will be launched for each interface. Each copy will autonomously create a default route. The priority of the route will depend on the distance. That is, when the connection “falls” on the route from Distance 10, the switching to 11. will occur. Due to this, the switching is seamless.

To start, the script pings the selected host on the Internet along the default route. If the ping is less than ($ PingCount- $ Margin) (Margin - sets the error for accuracy control), then we ping the test route to check whether the connection is “live”. In case of a negative result, check the route and the presence of problems with the settings:



The reaction rate to the state of the compound can be individually adjusted using the following variables:



Preparatory setting


I will not describe the default settings of the router for two reasons: firstly, this topic has been raised on the Internet more than once, including Habré, and secondly, the networks are distinguished by their configuration. Since the work of the script affects only the default routes and DHCP client settings, I think you will have no difficulty in adapting the script to your network.

For the script does not need to create routes by default - it will create them automatically. The only thing you need to choose the appropriate distance for test routes (you can both with $ Distance = 1) and $ DistanceDefault 10 and 11 for default routes (one for each provider). Also, do not need to create dhcp clients.

When configuring the router, I used SSH and Winbox (a specialized program for configuring devices managed by RouterOS, even works in * nix using Wine).

Let's get started

In Interfaces, we change the names of two interfaces to match the value of the $ Iface variable in the script (I have isp1, isp2):



Change DNS addresses to google-cue:



Create a script: System → Scripts → Add and paste the code below:



Script code
 :delay 10s :local Iface "isp1" :local StatusIface :local CurrentGateway :local pingInet :local pingLink :local pingGateway :local IPToPingInet "213.180.193.3" :local IPToPing "8.8.4.4" :local PingCount 5 :local Margin 1 :local Distance 1 :local DistanceDefault 10 :local RunTime 0 :local TimeToWait 20 #  while (true) do={ #    :set pingInet [/ping $IPToPingInet count=$PingCount interface=$Iface] :log debug "$pingInet $Iface $IPToPingInet" :if ($pingInet < ($PingCount-$Margin)) do={ :log error "No internet connection on $Iface." /ip dhcp-client set [/ip dhcp-client find interface=$Iface] add-default-route=no #   :while ($pingInet < ($PingCount-$Margin)) do={ #     :set pingLink [/ping $IPToPing count=$PingCount interface=$Iface] :log debug "$pingLink $Iface $IPToPing" :if ($pingLink < ($PingCount-$Margin)) do={ #   /interface ethernet disable $Iface; /interface ethernet enable $Iface :while ($pingLink < ($PingCount-$Margin)) do={ :log debug "$pingLink $Iface $IPToPing" :set RunTime ($RunTime + 1) :log debug $RunTime # Time to wait :if ( $RunTime = $TimeToWait ) do={ # Reboot interface :log info "reboot and release $Iface" /interface ethernet disable $Iface; /interface ethernet enable $Iface :set RunTime 0 } #    :if ([/interface ethernet get $Iface disabled] = false) do={ :log debug "Interface $Iface enabled" #   /interface ethernet monitor $Iface once do={ :set StatusIface $status } :if ($StatusIface = "link-ok") do={ :log debug "$Iface link-ok." #  dhcp :if ([/ip dhcp-client find interface=$Iface] != "") do={ :log debug "test1" #     DHCP :if ( [/ip dhcp-client get [/ip dhcp-client find interface=$Iface] invalid ] != true) do={ :log debug "test2" #   DHCP lease :set CurrentGateway [/ip dhcp-client get [/ip dhcp-client find interface=$Iface] gateway ] :log debug "Waiting DHCP lease" :if ($CurrentGateway != nil) do={ :set CurrentGateway [:put ("$CurrentGateway" . "%$Iface")] :log debug "CurrentGateway $CurrentGateway" # Looking for route test :log debug "Cheking test route for $Iface..." :local a [ /ip route find comment="$Iface" ] :if (($a) = "") do={ :log info ("Adding test route for $Iface...") /ip route add dst-address=$IPToPing gateway=$CurrentGateway comment="$Iface" distance=$Distance } else={ :local EstablishedGateway [/ip route get [/ip route find comment="$Iface"] gateway ] :log debug "EstablishedGateway $EstablishedGateway" :if ( $CurrentGateway = $EstablishedGateway ) do={ :log debug "No route changes needed for $Iface." } else={ :log info "Updating test route for $Iface..." /ip route set [/ip route find comment="$Iface" ] dst-address=$IPToPing gateway=$CurrentGateway comment="$Iface" distance=$Distance } } :set pingGateway [/ping [/ip dhcp-client get [/ip dhcp-client find interface=$Iface] gateway ] count=$PingCount interface=$Iface] :log debug "$pingGateway $Iface $IPToPing" :if ($pingGateway < ($PingCount-$Margin)) do={ :log error "route error on $Iface" :log debug [/ip dhcp-client get [/ip dhcp-client find interface=$Iface] gateway ] /ip dhcp-client release [/ip dhcp-client find interface=$Iface] } } else={ :log error "DHCP no lease." :delay 1s } } else={ :log error "DHCP failure on $Iface." :log info "reboot and release $Iface" /interface ethernet disable $Iface; /interface ethernet enable $Iface :delay 1s } } else={ :log info "adding DHCP client for $Iface" /ip dhcp-client add interface=$Iface disabled=no add-default-route=yes default-route-distance=$DistanceDefault use-peer-dns=no use-peer-ntp=no } } else={ :log debug "No-link on $Iface." :delay 1s } } else={ :log error "Interface $Iface disabled." } :set pingLink [/ping $IPToPing count=$PingCount interface=$Iface] } } else={ :log info "add default route= yes for $Iface" /ip dhcp-client set [/ip dhcp-client find interface=$Iface] add-default-route=yes } :set pingInet [/ping $IPToPingInet count=$PingCount interface=$Iface] } } else={ :log debug "Internet on $Iface connected." } } 



Repeat the previous step for the second interface, only changing the value of the $ Iface variable to “isp2”, also changing the $ DistanceDefault to the above values ​​(for me isp1 - 10, and for isp2 - 11).



Now you need to configure the scheduler to automatically run scripts when loading the router.
System → Scheduler->



This can also be done using ssh or from the console if you have problems with the Cyrillic alphabet in the date:

 /system scheduler add name=CheckTestRoute1 start-time=startup on-event=CheckTestRoute1 

We are overloading ...
I thought that there would be problems with NAT when switching routes, but for now
normal flight. If you have to write ...

That's all. I hope that this article will be useful for someone.

PS: Finally, RouterOS threw another puzzle ...



As you can see, despite the fact that the route is specified correctly, the ping does not pass.

To fix this, added another check (it has already been added above in the script code).

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


All Articles