The (unofficial) Mikrotik site

Improved Netwatch-style script.

There have been a number of improved netwatch scripts listed on the mikrotik wiki in the past however many of these are hard to understand, broken or both.

I had a request from an associate to assist them finding a solution to fall over VPN traffic from one link to another in the event of an outage; in a network configuration where it wasn’t possible to use the local upstream router as an indication of the VPNs status, so I took the opportunity to revise a netwatch script based loosely on the one located here: http://wiki.mikrotik.com/wiki/Improved_Netwatch_II

My rewrite of this allows both the “up” and “down” scripts to be called from the same place (preferably a scheduler entry) and to be extra nice I’ve commented the whole script so you’re all welcome to modify as you see fit.

Pre-requisites:
– Script has been tested on v4.13
– Requires 2 routes to a set address/address range, one with a distance of 1 (preferred route) the other with a distance of 2

Note: If the address you’re trying to test to lies within the range you’re wanting to route to (eg: 192.168.1.1 and 192.168.1.0/24 as the test address and route respectively) you’ll want to add a static route for the test address (eg: 192.168.1.1 via 192.168.2.1) to ensure you always try the primary path to get to it (otherwise the testing would flap back and forth between the 2 links!)

Example configuration:

The netwatch route in this case would be:

/ip route add dst-address=192.168.2.0/24 gateway=192.168.4.2 distance=1 comment="Netwatch-Route"

The script:

#define variables
:local i 0

#Check for specific route with distance of 1
:if ([/ip route find comment="Netwatch-Route" distance=1]!="") do={

#add +1 to $i while checking that $i is lower than 5 and there is no ping response (ping command returns 0)
#if either of the 2 clauses are not met, the command will terminate - that is if a ping response is received (breaking one of the clauses), it'll terminate before 5 loops
	:do {:set i ($i + 1)} while  ($i < 5 &&  ([/ping 192.168.2.1 interval=3 count=1]=0))

#when this point is reached check if $i=5 and if so do the following
	:if ($i=5) do={
#add a log entry
		:log info "Netwatch-Route has gone down"
#set the route distance to 5 (putting it at a lower priority than the alternative)
		/ip route set [find comment="Netwatch-Route"] distance=3
	}
#route not found, so...
} else={
#Check for specific route with distance of 3
	:if ([/ip route find comment="Netwatch-Route" distance=3]!="") do={
#add +1 to $i while checking that $i is lower than 10 and there is a ping response (ping command returns 0)
#if either of the 2 clauses are not met, the command will terminate - that is if a ping response is received (breaking one of the clauses), it'll terminate before 10 loops
		:do {:set i ($i + 1)} while  ($i < 10 &&  ([/ping 192.168.2.1 interval=3 count=1]=1))

#when this point is reached, check if $i=10 and if so do the following
		:if ($i=10) do={
#add a log entry
			:log info "Netwatch-Route is back up"
#set the route distance to 1 (putting it back to the higher priority)
			/ip route set [find comment="Netwatch-Route"] distance=1
		}
#no matching route found
	} else={
#log failure of script
		:log info "Route Required does not exist"
#log failure to terminal (helpful for testing purposes)
		:error "Route Required does not exist"
	}
}

For Mikrotik 2, the check address would be 192.168.1.1 and route would be

/ip route add dst-address=192.168.1.0/24 gateway=192.168.4.1 distance=1 comment="Netwatch-Route"

Uncommented/untabbed version of the script for those copy-paste fanatics:

:local i 0
:if ([/ip route find comment="Netwatch-Route" distance=1]!="") do={
:do {:set i ($i + 1)} while  ($i < 5 &&  ([/ping 192.168.1.1 interval=3 count=1]=0))
:if ($i=5) do={
:log info "Netwatch-Route has gone down"
/ip route set [find comment="Netwatch-Route"] distance=3
}
} else={
:if ([/ip route find comment="Netwatch-Route" distance=3]!="") do={
:do {:set i ($i + 1)} while  ($i < 10 &&  ([/ping 192.168.1.1 interval=3 count=1]=1))
:if ($i=10) do={
:log info "Netwatch-Route is back up"
/ip route set [find comment="Netwatch-Route"] distance=1
}
} else={
:log info "Route Required does not exist"
:error "Route Required does not exist"
}
}
Advertisement
Exit mobile version