How to properly use detect-internet for ISP failover

Hello,
I understand how to use netwatch for ISP failover. New functionality pretending to be easier and more straightforward named “detect-internet” is enigma for me.
My question is: how to properly use interface list to influence on IP routing, where is no configurable dependency on interface list?
Maybe a small hint can be enough.
Thanks for your patience

That’s a question, if it can be used for that. According to manual, you give it a list of interfaces and you get back three lists with interfaces sorted by status. You can use them to e.g. allow or block something in firewall. But to influence routing, maybe it’s just sudden lack of imagination on my side, but I don’t see how.

My situation:
I have two ISP connections, ISP1 has higher throughput, ISP2 has lower throughput. I clearly prefer ISP1, but in case of problem with connectivity there I want to rebalance data flow over ISP2.
Both ISPs give me dynamic IPV4 address using dhcp.

I did attempt to form scripts using output of detect-internet work for ISP failover. Result looks like this:

/ip dhcp-client
add comment=ISP1 default-route-distance=110 disabled=no interface=ether1 use-peer-ntp=no
add comment=ISP2 default-route-distance=111 disabled=no interface=ether5 use-peer-ntp=no

/interface list
...
add name=INTERNET
add name=INETCHECK
/interface list member
...
add interface=ether5 list=INETCHECK
add interface=ether1 list=INETCHECK

/interface detect-internet
set detect-interface-list=INETCHECK internet-interface-list=INTERNET lan-interface-list=LAN wan-interface-list=WAN

/system script
add dont-require-permissions=no name=set_default_route_ISP2 owner=cmartin policy=read,write,policy,test source=":global myDetectInternetResultISP2 [/interface list\
    \_member print count-only where list=\"INTERNET\" and interface=\"ether5\"];\r\
    \n                                                                                          \r\
    \n:if (\$myDetectInternetResultISP2 = 0) do={ /ip dhcp-client set [/ip dhcp-client find comment=ISP2] default-route-distance=120 } else={ /ip dhcp-client set [\
    /ip dhcp-client find comment=ISP2] default-route-distance=111 }"
add dont-require-permissions=no name=set_default_route_ISP1 owner=cmartin policy=read,write,policy,test source=":global myDetectInternetResultISP1 [/interface list\
    \_member print count-only where list=\"INTERNET\" and interface=\"ether1\"];\r\
    \n                                                                                          \r\
    \n:if (\$myDetectInternetResultISP1 = 0) do={ /ip dhcp-client set [/ip dhcp-client find comment=ISP1] default-route-distance=120 } else={ /ip dhcp-client set [\
    /ip dhcp-client find comment=ISP1] default-route-distance=110 }"
    
/system scheduler
add interval=1m name=schedule_set_default_route_ISP1 on-event=set_default_route_ISP1 policy=read,write,policy,test start-date=jun/08/2020 \
    start-time=10:04:17
add interval=1m name=schedule_set_default_route_ISP2 on-event=set_default_route_ISP2 policy=read,write,policy,test start-date=jun/08/2020 \
    start-time=10:10:09

Let me explain the result and ideas behind:

  • Because ip addresses are not known in advance, I can’t create static default gateway routes nor assign them route distance, which is how I control outgoing traffic path. Dhcp client “default-route-distance” does this work after establishing connection to ISPx and is able to indirectly propagate change of configuration to running routing table.


  • Interface names of interfaces facing the ISP connections are listed in interface list “INETCHECK”, processed by detect-internet machine.


  • I created two scripts, each of them checks presence of one interface name in interface list called “INTERNET”. Absence of interface name here does mean, that internet is not accessible this way, so dhcp client configuration parameter “default-route-distance” of particular ISP connection is modified accordingly to propagate route distance change to OS routing table.


  • Slightly shorter route distance is hardcoded for ISP1 - this way I prefer this connection in normal situation


  • System scheduler entries are created for both scripts, to run them every minute or whichever interval time is wanted.

This does work for me :wink:

Final note: normally, solution outlined above will rewrite dhcp client configuration of ISP interfaces every minute. I’m not sure if change to the same value which is actually configured will or will not result to a write to NAND flash storage in RouterBoard. Because I don’t want to wear out bulit in RouterBoard storage too early, I plan to create procedure able to check current configuration before attempt to change it and omit this step if configuration is the same as after intended change.
Setup shown above can be used without any changes on CHR, where flash storage is probably not a problem.

Not exactly true, you could easily create config like:

Advanced Routing Failover without Scripting

which relies on known gateways, but you can update those from DHCP client’s lease script (the example is in fact more complicated than necessary, it’s possible to use much simpler variant).

What I don’t like about linked config is that it usually relies on random third-party addresses like Google’s public DNS servers, so it’s kind of abuse. It would be also loads of fun, if they one day decided to block ping. :smiling_imp: From this point, using MikroTik’s internet detection is cleaner solution, as it’s made for this. But it would be even better, if they added an event which would fire when something changes, same way as lease script does.