Community discussions

MikroTik App
 
WoZeR
just joined
Topic Author
Posts: 17
Joined: Tue Jul 08, 2014 2:52 am

HA ISP Recursive Routing ISP Failover using DHCP

Fri May 12, 2023 1:53 am

This script should allow you to have multiple ISPs and failover to a backup ISP when the primary one fails while using DHCP instead of static gateways. If the DHCP address gateways change this script will automatically update the route table. You could use your main internet as primary and failback to LTE as an example. It also supports more than 2 ISP paths "ISPPriority".

Place the following code in the dhcp-client script section. When the dhcp-client retrieves an IP address it will automatically build the recursive routes and keep the gateways up to date if there are changes. For each dhcp-client used, you will need to pick a different IP to health check and configure the priority of which ISP will be used for primary and failover and the script will do the rest of the work.

Image

HealthCheckIP is the IP that will be pinged. If it fails then recursive routing will force the traffic to flow through the next ISP. You want to use different IPs to prevent both ISPs being marked down when that IP fails a check. Script defaults to 8.8.8.8 but you can use any address available on the internet.

ISPPriority is the order of ISPs you want to use as you failover. This controls the routes distance values. 1 is the highest priority.
#####APPLY TO /ip dhcp-client add script= section.

#IP to use to check if ISP path is working. Use different IPs for each ISP.
:global HealthCheckIP "8.8.8.8"

#Which ISP path to use first. 1 is the highest priority. Each ISP needs a different priority value.
:global ISPPriority "1"

#####
#This creates the comments for the routes and is used to find and change/delete the entries.
:global ISPName ("ISP_".$interface)

#Make sure to set Add Default Route to "no" on the DHCP Client.
/ip dhcp-client set [ find interface=$interface ] add-default-route=no

#Add Recursive Gateway Health Check IP Monitor
:local count [/ip route print count-only where comment=($ISPName."_Monitor")]
:if ($bound=1) do={
    :if ($count = 0) do={
        /ip route add comment=($ISPName."_Monitor") disabled=no distance=1 dst-address=($"HealthCheckIP"."/32") gateway=$"gateway-address" scope=10 target-scope=10
    } else={
        :if ($count = 1) do={
            :local test [/ip route find where comment=($ISPName."_Monitor")]
            :if ([/ip route get $test gateway] != $"gateway-address") do={
                /ip route set $test gateway=$"gateway-address"
            }
        } else={
            :error "Multiple routes found"
        }
    }
} else={
    /ip route remove [find comment=($ISPName."_Monitor")]
}


#Add 0.0.0.0/0 route to ISP Gateway
:local count2 [/ip route print count-only where comment=$ISPName]
:if ($bound=1) do={
    :if ($count2 = 0) do={
        /ip route add check-gateway=ping comment=$ISPName disabled=no distance=$ISPPriority dst-address=0.0.0.0/0 gateway=$"HealthCheckIP" scope=30 target-scope=11
    } 
} else={
    /ip route remove [find comment=$ISPName]
}
Last edited by WoZeR on Sat May 13, 2023 2:50 am, edited 1 time in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12001
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: HA ISP Recursive Routing ISP Failover using DHCP

Fri May 12, 2023 2:11 am

The code must be written well and without errors, or the others will not understand anything, be more orderly.

revised not tested code

:global HealthCheckIP 8.8.8.8
:global ISPPriority   1
:global ISPName       $interface

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

/ip route
:local count [:len [find where comment="$ISPName_Monitor"]]
:if ($bound = 1) do={
    :if ($count = 0) do={
        add comment="$ISPName_Monitor" disabled=no distance=1 dst-address="$HealthCheckIP/32" \
            gateway=$"gateway-address" scope=10 target-scope=10
    } else={
        :if ($count = 1) do={
            :local test [find where comment="$ISPName_Monitor"]
            :if ([get $test gateway] != $"gateway-address") do={
                set $test gateway=$"gateway-address"
            }
        } else={
            :error "Multiple routes found"
        }
    }
} else={
    remove [find where comment="$ISPName_Monitor"]
}

:local count2 [:len [find where comment=$ISPName]]
:if ($bound = 1) do={
    :if ($count2 = 0) do={
        add check-gateway=ping comment=$ISPName disabled=no distance=$ISPPriority dst-address=0.0.0.0/0 \
            gateway=$HealthCheckIP scope=30 target-scope=11
    }
} else={
    remove [find where comment=$ISPName]
}
 
WoZeR
just joined
Topic Author
Posts: 17
Joined: Tue Jul 08, 2014 2:52 am

Re: HA ISP Recursive Routing ISP Failover using DHCP

Sat May 13, 2023 3:02 am

I understand what you are trying to convey but you could be more professional about it. Posting broken untested revised code is breaking your own rules. You removed all the comments and converted the concat variables into a single variable that doesn't exist breaking the script.

For everyone else, the original script posted was tested on v7.8 RouterOS and is working correctly in a GNS3 test lab. If you run into any issues please let me know and I'll see what I can do to fix it.
Thanks!
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12001
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: HA ISP Recursive Routing ISP Failover using DHCP

Sat May 13, 2023 10:34 am

you could be more professional about it
I don't get paid, so it's free advice for everyone

Posting broken untested revised code is breaking your own rules.
1) Where is broken?
2) It is correct to indicate that it is not tested. It's just an example to show how you can code more neatly for everyone (and it doesn't pretend to be the best way)
3) What rule should i break? I didn't open the topic and post your code....

You removed all the comments
What's the problem with putting them back?

and converted the concat variables into a single variable that doesn't exist breaking the script.
Obviously you don't know what you write.
In your opinion I would have made this stupid mistake, it's you that don't know how to program.

I may have made other mistakes, but not this one.
And by the way, do you want forum users not to notice that you changed the script in the first post???
There is also the posthumous modification date of 39 minutes compared to my answer.
Any subsequent changes, obvious that can not match your rewritten code.

A simple example:

real output code

[] > :global test "this is a test for the _ that do not count as variable name"
[] > :put "$test_suffix"
this is a test for the _ that do not count as variable name_suffix
As anyone can see, this works perfectly, because _ is not a valid character in the variable name (unless you use the syntax $"variable_name"
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12001
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: HA ISP Recursive Routing ISP Failover using DHCP

Sat May 13, 2023 10:57 am

Version of the 13 May 2023, 01:50

revised not tested code

# APPLY TO /ip dhcp-client add script= section.

:global HealthCheckIP 8.8.8.8          ; # IP to use to check if ISP path is working. Use different IPs for each ISP.
:global ISPPriority   1                ; # Which ISP path to use first. 1 is the highest priority. Each ISP needs a different priority value.
:global ISPName       "ISP_$interface" ; # This creates the comments for the routes and is used to find and change/delete the entries.

# Make sure to set Add Default Route to "no" on the DHCP Client.
/ip dhcp-client
set [find where interface=$interface] add-default-route=no

/ip route

# Add Recursive Gateway Health Check IP Monitor
:local count [:len [find where comment="$ISPName_Monitor"]]
:if ($bound = 1) do={
    :if ($count = 0) do={
        add comment="$ISPName_Monitor" disabled=no distance=1 dst-address="$HealthCheckIP/32" \
            gateway=$"gateway-address" scope=10 target-scope=10
    } else={
        :if ($count = 1) do={
            :local test [find where comment="$ISPName_Monitor"]
            :if ([get $test gateway] != $"gateway-address") do={
                set $test gateway=$"gateway-address"
            }
        } else={
            :error "Multiple routes found"
        }
    }
} else={
    remove [find where comment="$ISPName_Monitor"]
}

# Add 0.0.0.0/0 route to ISP Gateway
:local count2 [:len [find where comment=$ISPName]]
:if ($bound = 1) do={
    :if ($count2 = 0) do={
        add check-gateway=ping comment=$ISPName disabled=no distance=$ISPPriority dst-address=0.0.0.0/0 \
            gateway=$HealthCheckIP scope=30 target-scope=11
    } 
} else={
    remove [find where comment=$ISPName]
}
 
joshhboss
Member Candidate
Member Candidate
Posts: 273
Joined: Thu Aug 01, 2019 2:13 pm

Re: HA ISP Recursive Routing ISP Failover using DHCP

Sat Jul 29, 2023 4:49 am

Version of the 13 May 2023, 01:50

revised not tested code

# APPLY TO /ip dhcp-client add script= section.

:global HealthCheckIP 8.8.8.8          ; # IP to use to check if ISP path is working. Use different IPs for each ISP.
:global ISPPriority   1                ; # Which ISP path to use first. 1 is the highest priority. Each ISP needs a different priority value.
:global ISPName       "ISP_$interface" ; # This creates the comments for the routes and is used to find and change/delete the entries.

# Make sure to set Add Default Route to "no" on the DHCP Client.
/ip dhcp-client
set [find where interface=$interface] add-default-route=no

/ip route

# Add Recursive Gateway Health Check IP Monitor
:local count [:len [find where comment="$ISPName_Monitor"]]
:if ($bound = 1) do={
    :if ($count = 0) do={
        add comment="$ISPName_Monitor" disabled=no distance=1 dst-address="$HealthCheckIP/32" \
            gateway=$"gateway-address" scope=10 target-scope=10
    } else={
        :if ($count = 1) do={
            :local test [find where comment="$ISPName_Monitor"]
            :if ([get $test gateway] != $"gateway-address") do={
                set $test gateway=$"gateway-address"
            }
        } else={
            :error "Multiple routes found"
        }
    }
} else={
    remove [find where comment="$ISPName_Monitor"]
}

# Add 0.0.0.0/0 route to ISP Gateway
:local count2 [:len [find where comment=$ISPName]]
:if ($bound = 1) do={
    :if ($count2 = 0) do={
        add check-gateway=ping comment=$ISPName disabled=no distance=$ISPPriority dst-address=0.0.0.0/0 \
            gateway=$HealthCheckIP scope=30 target-scope=11
    } 
} else={
    remove [find where comment=$ISPName]
}
This is amazing.. Worked very very very well..

Is there a way to get this kind of script to run on an lte1 interface.. whenever the Lte modem is not connected there is nowhere to work on it, but yeah super impressive, im going to start adding this to all my routers.. with multiple WANs to.. pretty nice how you can just write scripts to automate all this..
 
cyayon
Frequent Visitor
Frequent Visitor
Posts: 68
Joined: Wed Aug 24, 2022 9:39 am

Re: HA ISP Recursive Routing ISP Failover using DHCP

Sun Jul 30, 2023 3:28 pm

Hi,

Very cool script ! Thanks !
I am currently using nested recursive routing to check ISP health.
I am really dubitative if only one check (not nested) is sufficient in real life to check ISP health.
I have currently 3 nested recursive route, It is perhaps too much…

I am looking to replace my recursive routing with a a script called by Netwatch or just scheduled.
viewtopic.php?t=198207
What do you think about this ? Is it a good idea or not ?

Who is online

Users browsing this forum: diamuxin and 15 guests