Script de Fail-Over Mikrotik

      Comments Off on Script de Fail-Over Mikrotik

Descripción

Para lograr la redundancia a Internet, los ISPs y las empresas establecen múltiples conexiones a uno o varios proveedores de servicios. El problema nace cuando necesitamos monitorear la conectividad desde dentro de nuestra red hacia Internet. Para solucionar este problema se crea un script que opera sobre routers Mikrotik. El script de Fail-Over permite la automatización del control de estado de lineas de conexión a proveedores. Además se a incorporado la posibilidad de chequear la latencia de cada linea y disparar un alerta en caso de tener un delay por encima del permitido.

Características

El script actualmente presenta las siguientes funciones:

  • Chequeo de estado de interfaz de conexión a Internet.
  • Chequeo de alcance de gateway.
  • Chequeo de acceso a Internet en la conexión vía ping (2 destinos).
  • Chequeo de acceso a Internet en la conexión vía http (1 destino).
  • Chequeo de tráfico en interfaz.
  • Chequeo de latencia de cada interfaz (Solo a 1 servidor actualmente).
  • Notificación vía log de router.
  • Notificación vía Telegram.
  • Ejecución externa de script por peer.
  • Activar o desactivar notificaciones.
  • Activar o desactivar desactivación de rutas.
  • Activar o desactivar ejecución de script externo.
  • Contador de errores.

Instalación

La instalación del programa debe hacerse con mucho cuidado para evitar errores que puedan provocar la caída de conexiones, recordemos que el script desactiva rutas si las ve como “caídas”.

Pasos

  1. Copiar la sección de instalación y pegar en un terminal de Mikrotik.
  2. Crear la cantidad de peers que necesitemos monitorear.
  3. Cargar los datos necesarios para cada peer.
  4. Cargar información de notificaciones.
  5. Configurar interruptores de acción.

Tener en cuenta que la ruta de fail-over debe tener el comentario “fail-over” exactamente, ya que usa este dato para la identificacion de la misma.
Recordar que  el comentario de la ruta debe coincidir con el description dentro del array de isp.

Instalación desde 0

/system script
add name=probedns owner=admin policy=\
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
V3.0\r\
\n#\r\
\n##Declaracion de variable\r\
\n:global probedns\r\
\n##Seteo a null\r\
\n:set \$probedns \"\"\r\
\n##Verificar funcionamiento DNS\r\
\n:set \$probedns [:resolve example.com]"

/system script
add name=FaOvConf owner=admin policy=\
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
V3.0\r\
\n#\r\
\n##Definicion de variables, relacion gateway-interfaz.\r\
\n:global peer1 {gifname=\"ether2\"; gdescription=\"W1-R1-N1-RE\"; ggatewa\
y=\"138.0.154.1\"; gtable=\"W1-R1-N1-RE\"; gnotificationen=1; gdisgaten=1;\
\_glatencyen=0; gextexecen=0; gmaxdelay=30; gbandwidth=30000; gextexecname\
up=\"UPEvent_peer1\"; gextexecnamedown=\"DownEvent_peer1\"; gdelaystatus=1\
; gstatus=1; gexexstatus=0; gerrorscount=0}\r\
\n#\r\
\n:global peer2 {gifname=\"pppoe-out1\"; gdescription=\"W2-R1-N1-RE\"; gga\
teway=\"pppoe-out1\"; gtable=\"W2-R1-N1-RE\"; gnotificationen=1; gdisgaten\
=0; glatencyen=0; gextexecen=1; gmaxdelay=30; gbandwidth=30000; gextexecna\
meup=\"UPEvent_peer2\"; gextexecnamedown=\"DownEvent_peer2\"; gdelaystatus\
=1; gstatus=1; gexexstatus=0; gerrorscount=0}\r\
\n#\r\
\n#------------------------------------#\r\
\n##Activar o desactivar globalmente las notificaciones\r\
\n:global notificationset 1;\r\
\n##Configuraci\F3n de notificaciones\r\
\n:global bot 295689019:AAH_YCsgsdg51vsdhUk7jP5e-DPizkhuMaXL0;\r\
\n:global chatid \"1545452523207\";\r\
\n:global devicename \"Dpto\";\r\
\n#\r\
\n##Activar o desactivar globalmente deshabilitacion de ruta marcada\r\
\n:global disgatset 1;\r\
\n#\r\
\n##Activar/Desactivar control de latencia (Si el valor es 1 esta activado\
\_si es 0 desactivado)\r\
\n:global latencyset 0;\r\
\n#\r\
\n##Activar o desactivar globalmente scripts que se ejecutan externamente \
en caso de caida y reactivaci\F3n de linea.\r\
\n:global extexecset 0;"

/system scheduler
add disabled=yes interval=3m name=fail-over on-event=fail-over

/ip route
add comment=fail-over distance=1 dst-address=1.0.0.1/32 gateway=192.168.0.1

/system script
add name=fail-over owner=admin policy=\
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
Llamado a matriz de control\r\
\n:execute script=\"FaOvConf\"\r\
\n:global peer1\r\
\n:global peer2\r\
\n##Array que carga al loop\r\
\n:local peers {\$peer1;\$peer2};\r\
\n#------------------------------------------#\r\
\n#V3.0\r\
\n#\r\
\n##Notificaciones\r\
\n:global notificationset\r\
\n:global disgatset\r\
\n:global bot\r\
\n:global chatid\r\
\n:global devicename\r\
\n#\r\
\n##Activar/Desactivar control de latencia (Si el valor es 1 esta activado\
\_si es 0 desactivado)\r\
\n:global latencyset\r\
\n#\r\
\n##Nombre de scripts que se ejecutan externamente en caso de caida y reac\
tivaci\F3n de linea.\r\
\n:global extexecset\r\
\n\r\
\n##Ping a...\r\
\n:local serv1 1.0.0.1\r\
\n:local serv2 4.2.2.1\r\
\n#\r\
\n##Check DNS\r\
\n:execute script=\"probedns\"\r\
\n:delay 3\r\
\n:global probedns\r\
\n:if ([:len \$probedns] <= 0) do {\r\
\n:log warning \"Falla en DNS\"\r\
\n/ip dns set server=8.8.8.8,1.1.1.1\r\
\n}\r\
\n#\r\
\n##Fetch. Cargar url y mode sin \"\"\r\
\n:local ipfetch1 93.184.216.34\r\
\n:local furl1 http://example.com/index.html;\r\
\n:local fmode1 http;\r\
\n#\r\
\n##Loop de chequeo.\r\
\n:foreach check in=\$peers do={\r\
\n#:put \$check\r\
\n\t#\r\
\n\t###Extraccion de variables\r\
\n\t:local ifname (\$check->\"gifname\")\r\
\n\t:local description (\$check->\"gdescription\")\r\
\n\t:local gateway (\$check->\"ggateway\")\r\
\n\t:local table (\$check->\"gtable\")\r\
\n\t:local notificationen (\$check->\"gnotificationen\")\r\
\n\t:local disgaten (\$check->\"gdisgaten\")\r\
\n\t:local latencyen (\$check->\"glatencyen\")\r\
\n\t:local extexecen (\$check->\"gextexecen\")\r\
\n\t:local maxdelay (\$check->\"gmaxdelay\")\r\
\n\t:local bandwidth (\$check->\"gbandwidth\")\r\
\n\t:local extexecnameup (\$check->\"gextexecnameup\")\r\
\n\t:local extexecnamedown (\$check->\"gextexecnamedown\")\r\
\n\t:local delaystatus (\$check->\"gdelaystatus\")\r\
\n\t:local status (\$check->\"gstatus\")\r\
\n\t:local exexstatus (\$check->\"gexexstatus\")\r\
\n\t:local errorscount (\$check->\"gerrorscount\")\r\
\n\t#\r\
\n\t##Resultado de ping se almacena en esta variable\r\
\n\t#\r\
\n\t:local pingresultserv1\r\
\n\t:local pingresultserv2\r\
\n\t:local avgserv1\r\
\n\t:local avgserv2\r\
\n\t#Declaracion de variable de error\r\
\n\t:local err 0\r\
\n\t#\r\
\n\t##Notificaciones de caida y levantada.\r\
\n\t#No puede contener espacios\r\
\n\t:local infoifdown \"Interface-\$ifname-\$description-caida.-(Interfaz \
down)-\$devicename\"\r\
\n\t:local infoun \"Interface-\$ifname-\$description-caida.-(Gateway unrea\
chable)-\$devicename\"\r\
\n\t:local infointernet \"Interface-\$ifname-\$description-caida.-(Linea s\
in internet)-\$devicename\"\r\
\n\t:local infoup \"Interface-\$ifname-\$description-arriba.-(Linea con in\
ternet)-\$devicename\"\r\
\n\t#\r\
\n\t##Informacion de linea\r\
\n\t:put (\"ifname\" . \" | \" . \"description\" . \" | \" . \"gateway\" \
. \" | \" . \"table\" . \" | \" . \"status\" . \" | \" . \"delaystatus\
\");\r\
\n\t:put (\"\$ifname\" . \" \" . \"\$description\" . \" \" . \"\$gateway\
\" . \" \" . \"\$table\" . \" \" . \"\$status\" . \" \" . \"\$delaystat\
us\");\r\
\n\t###Control de Interfaz\r\
\n\t#\r\
\n\t##Detecta estado de interface\r\
\n\t#\r\
\n\t:local ifrunn [interface get \$ifname running]\r\
\n\t#\r\
\n\t##Chequea estado de interface #Si el estado de la interface es running\
=false la marca como caida.\r\
\n\t:if (\$ifrunn = false) do={\r\
\n\t\t:set \$err 1\r\
\n\t\t:if (\$status = 1) do={\r\
\n \t#Setea isp como caido\r\
\n\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t#log\r\
\n\t\t\t:log warning \$infoifdown\r\
\n\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMessag\
e\\\?chat_id=\$chatid&text=\$infoifdown\" keep-result=no\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t##Detecta estado del gateway\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t:foreach existgw in=[/ip route find comment=\$description] do={\r\
\n\t\t\t:local gwstat [/ip route get \$existgw gateway-status]\r\
\n\t\t\t#\r\
\n\t\t\t##Chequea estado del gateway #Si el estado del gateway es \"unreac\
hable\" la marca como caida.\r\
\n\t\t\t:if (\$gwstat = \"\$gateway unreachable\") do={\r\
\n\t\t\t\t:set \$err 1\r\
\n\t\t\t\t:if (\$status = 1) do={\r\
\n\t\t\t\t\t#Setea isp como caido\r\
\n\t\t\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t\t\t#log\r\
\n\t\t\t\t\t:log warning \$infoun\r\
\n\t\t\t\t\t#Incrementar contador de error\r\
\n\t\t\t\t\t:set (\$check->\"gerrorscount\") (\$errorscount+1);\r\
\n\t\t\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t\t\t/ip route disable [/ip route find routing-mark=\$table]\r\
\n\t\t\t\t\t\t\t/ip route disable [/ip route find comment=\$description]\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMe\
ssage\\\?chat_id=\$chatid&text=\$infoun\" keep-result=no\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t##Comprobacion de acceso a Internet en conexion\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t##Seteo ruta con server1\r\
\n\t\t:put \"Comprobacion a \$serv1\"\r\
\n\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address=\$s\
erv1 gateway=\$gateway;\r\
\n\t\t##Seteo la variable de estado a false\r\
\n\t\t:set \$pingresultserv1 false;\r\
\n\t\t##Espera fijacion de ruta\r\
\n\t\t:delay 2\r\
\n\t\t##Hago ping y carga la variable de respuesta de ping.\r\
\n\t\t/tool flood-ping \$serv1 count=10 size=38 do={\r\
\n \t:if (\$\"received\" >= 8) do={\r\
\n \t\t:set \$pingresultserv1 true;\r\
\n \t\t:set \$avgserv1 \$\"avg-rtt\";\r\
\n \t\t}\r\
\n \t}\r\
\n\t\t##Chequeo de resultado de ping e informe de prblemas en lineas.\r\
\n\t\t:if (\$pingresultserv1 != true) do={\r\
\n\t\t\t##Si falla el primer server seteo el segundo\r\
\n\t\t\t:put \"Comprobacion a \$serv2\"\r\
\n\t\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address=\
\$serv2 gateway=\$gateway;\r\
\n\t\t\t##Seteo la variable de estado a false\r\
\n\t\t\t:set \$pingresultserv2 false;\r\
\n\t\t\t##Espera fijacion de ruta\r\
\n\t\t\t:delay 2\r\
\n\t\t\t##Hago ping y carga la variable de respuesta de ping.\r\
\n\t\t\t/tool flood-ping \$serv2 count=10 size=38 do={\r\
\n \t\t:if (\$\"received\" >= 8) do={\r\
\n\t \t\t:set \$pingresultserv2 true;\r\
\n\t \t\t:set \$avgserv2 \$\"avg-rtt\";\r\
\n\t \t\t}\r\
\n\t \t}\r\
\n\t\t\t:if (\$pingresultserv2 != true) do={\r\
\n\t\t\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address\
=\$ipfetch1 gateway=\$gateway;\r\
\n\t\t\t\t##Espera fijacion de ruta\r\
\n\t\t\t\t:delay 2\r\
\n\t\t\t\t:do {/tool fetch url=\"\$furl1\" mode=\$fmode1} \\\r\
\n\t\t\t\ton-error={\r\
\n\t\t\t\t\t##Monitor traffic\r\
\n\t\t\t\t\t/interface monitor-traffic \$ifname once do={ \r\
\n\t\t\t\t\t\t:if (\$\"rx-bits-per-second\" < \$bandwidth) do={\r\
\n\t\t\t\t\t\t\t:set \$err 1\r\
\n\t\t\t\t\t\t\t:if (\$status = 1) do={\r\
\n\t\t\t\t\t\t\t\t#Setea isp como caido\r\
\n\t\t\t\t\t\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t\t\t\t\t\t#log\r\
\n\t\t\t\t\t\t\t\t:log warning \$infointernet\r\
\n\t\t\t\t\t\t\t\t#Incrementar contador de error\r\
\n\t\t\t\t\t\t\t\t:set (\$check->\"gerrorscount\") (\$errorscount+1);\r\
\n\t\t\t\t\t\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t\t\t\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t/ip route disable [/ip route find routing-mark=\$tab\
le]\r\
\n\t\t\t\t\t\t\t\t\t\t/ip route disable [/ip route find comment=\$descript\
ion]\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t#Ejecuta script externo. Ejemplo de uso: Bloquear pagina\
s de alto consumo.\r\
\n\t\t\t\t\t\t\t\t:if (\$extexecset = 1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$extexecen = 1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t:execute script=\$extexecnamedown\r\
\n\t\t\t\t\t\t\t\t\t\t:set (\$check->\"gexexstatus\") 1\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/\
sendMessage\\\?chat_id=\$chatid&text=\$infointernet\" keep-result=no\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\t\r\
\n\t\t\t\t\t\t\t}\t\t\t\t\t\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t} \r\
\n\t\t}\r\
\n\t}\r\
\n\t##Accion ante cambio\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t:if (\$status = 0) do={\r\
\n\t\t\t#Setea isp como caido\r\
\n\t\t\t:set (\$check->\"gstatus\") 1\r\
\n\t\t\t#log\r\
\n\t\t\t:log warning \$infoup\r\
\n\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t/ip route enable [/ip route find routing-mark=\$table]\r\
\n\t\t\t\t\t/ip route enable [/ip route find comment=\$description]\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t\t#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto \
consumo.\r\
\n\t\t\t:if (\$extexecset = 1) do={\r\
\n\t\t\t\t:if (\$extexecen = 1) do={\r\
\n\t\t\t\t\t:execute script=\$extexecnameup\r\
\n\t\t\t\t\t:set (\$check->\"gexexstatus\") 0\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMessag\
e\\\?chat_id=\$chatid&text=\$infoup\" keep-result=no\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t#Control de latencia\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t##Latency habilitado\?\r\
\n\t\t:if (\$latencyset = 1) do={\r\
\n\t\t\t:if (\$latencyen = 1) do={\r\
\n\t\t\t\t##Notificaciones de latencia\r\
\n\t\t\t\t:local infohlatency \"Interface-\$ifname-\$description-con-alta-\
latencia-\$avgserv1.\"\r\
\n\t\t\t\t:local infonlatency \"Interface-\$ifname-\$description-con-laten\
cia-normal-\$avgserv1.\"\r\
\n\t\t\t\t##Comprobacion de delay\r\
\n\t\t\t\t:if (\$avgserv1 > \$maxdelay) do={\r\
\n\t\t\t\t\t:if (\$delaystatus = 1) do={\r\
\n\t\t\t\t\t\t:set (\$check->\"gdelaystatus\") 0\r\
\n\t\t\t\t\t\t:log warning \$infohlatency\r\
\n\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/send\
Message\\\?chat_id=\$chatid&text=\$infohlatency\" keep-result=no\r\
\n\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t\t:if (\$avgserv1 <= \$maxdelay) do={\r\
\n\t\t\t\t\t:if (\$delaystatus = 0) do={\r\
\n\t\t\t\t\t\t:set (\$check->\"gdelaystatus\") 1\r\
\n\t\t\t\t\t\t:log warning \$infonlatency\r\
\n\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/send\
Message\\\?chat_id=\$chatid&text=\$infonlatency\" keep-result=no\r\
\n\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t:set \$err 0\r\
\n}"

Instalación ProbeDNS

/system script
add name=probedns source="#V3.0\r\
\n#\r\
\n##Declaracion de variable\r\
\n:global probedns\r\
\n##Seteo a null\r\
\n:set \$probedns \"\"\r\
\n##Verificar funcionamiento DNS\r\
\n:set \$probedns [:resolve example.com]"

Instalación FaOvConf

/system script
add name=FaOvConf owner=admin policy=\
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
V3.0\r\
\n#\r\
\n##Definicion de variables, relacion gateway-interfaz.\r\
\n:global peer1 {gifname=\"ether2\"; gdescription=\"W1-R1-N1-RE\"; ggatewa\
y=\"138.0.154.1\"; gtable=\"W1-R1-N1-RE\"; gnotificationen=1; gdisgaten=1;\
\_glatencyen=0; gextexecen=0; gmaxdelay=30; gbandwidth=30000; gextexecname\
up=\"UPEvent_peer1\"; gextexecnamedown=\"DownEvent_peer1\"; gdelaystatus=1\
; gstatus=1; gexexstatus=0; gerrorscount=0}\r\
\n#\r\
\n:global peer2 {gifname=\"pppoe-out1\"; gdescription=\"W2-R1-N1-RE\"; gga\
teway=\"pppoe-out1\"; gtable=\"W2-R1-N1-RE\"; gnotificationen=1; gdisgaten\
=0; glatencyen=0; gextexecen=1; gmaxdelay=30; gbandwidth=30000; gextexecna\
meup=\"UPEvent_peer2\"; gextexecnamedown=\"DownEvent_peer2\"; gdelaystatus\
=1; gstatus=1; gexexstatus=0; gerrorscount=0}\r\
\n#\r\
\n#------------------------------------#\r\
\n##Activar o desactivar globalmente las notificaciones\r\
\n:global notificationset 1;\r\
\n##Configuraci\F3n de notificaciones\r\
\n:global bot 295689019:AAH_YCsgOp7ua15adsjP5e-DPizkhuMaXL0;\r\
\n:global chatid \"1594187307\";\r\
\n:global devicename \"Dpto\";\r\
\n#\r\
\n##Activar o desactivar globalmente deshabilitacion de ruta marcada\r\
\n:global disgatset 1;\r\
\n#\r\
\n##Activar/Desactivar control de latencia (Si el valor es 1 esta activado\
\_si es 0 desactivado)\r\
\n:global latencyset 0;\r\
\n#\r\
\n##Activar o desactivar globalmente scripts que se ejecutan externamente \
en caso de caida y reactivaci\F3n de linea.\r\
\n:global extexecset 0;"

Instalación Scheduler

/system scheduler
add disabled=no interval=3m name=fail-over on-event=fail-over

Instalación ruta

/ip route
add comment=fail-over distance=1 dst-address=1.0.0.1/32 gateway=192.168.0.1

Instalación Fail-Over

/system script
add name=fail-over owner=admin policy=\
ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\
Llamado a matriz de control\r\
\n:execute script=\"FaOvConf\"\r\
\n:global peer1\r\
\n:global peer2\r\
\n##Array que carga al loop\r\
\n:local peers {\$peer1;\$peer2};\r\
\n#------------------------------------------#\r\
\n#V3.0\r\
\n#\r\
\n##Notificaciones\r\
\n:global notificationset\r\
\n:global disgatset\r\
\n:global bot\r\
\n:global chatid\r\
\n:global devicename\r\
\n#\r\
\n##Activar/Desactivar control de latencia (Si el valor es 1 esta activado\
\_si es 0 desactivado)\r\
\n:global latencyset\r\
\n#\r\
\n##Nombre de scripts que se ejecutan externamente en caso de caida y reac\
tivaci\F3n de linea.\r\
\n:global extexecset\r\
\n\r\
\n##Ping a...\r\
\n:local serv1 1.0.0.1\r\
\n:local serv2 4.2.2.1\r\
\n#\r\
\n##Check DNS\r\
\n:execute script=\"probedns\"\r\
\n:delay 3\r\
\n:global probedns\r\
\n:if ([:len \$probedns] <= 0) do {\r\
\n:log warning \"Falla en DNS\"\r\
\n/ip dns set server=8.8.8.8,1.1.1.1\r\
\n}\r\
\n#\r\
\n##Fetch. Cargar url y mode sin \"\"\r\
\n:local ipfetch1 93.184.216.34\r\
\n:local furl1 http://example.com/index.html;\r\
\n:local fmode1 http;\r\
\n#\r\
\n##Loop de chequeo.\r\
\n:foreach check in=\$peers do={\r\
\n#:put \$check\r\
\n\t#\r\
\n\t###Extraccion de variables\r\
\n\t:local ifname (\$check->\"gifname\")\r\
\n\t:local description (\$check->\"gdescription\")\r\
\n\t:local gateway (\$check->\"ggateway\")\r\
\n\t:local table (\$check->\"gtable\")\r\
\n\t:local notificationen (\$check->\"gnotificationen\")\r\
\n\t:local disgaten (\$check->\"gdisgaten\")\r\
\n\t:local latencyen (\$check->\"glatencyen\")\r\
\n\t:local extexecen (\$check->\"gextexecen\")\r\
\n\t:local maxdelay (\$check->\"gmaxdelay\")\r\
\n\t:local bandwidth (\$check->\"gbandwidth\")\r\
\n\t:local extexecnameup (\$check->\"gextexecnameup\")\r\
\n\t:local extexecnamedown (\$check->\"gextexecnamedown\")\r\
\n\t:local delaystatus (\$check->\"gdelaystatus\")\r\
\n\t:local status (\$check->\"gstatus\")\r\
\n\t:local exexstatus (\$check->\"gexexstatus\")\r\
\n\t:local errorscount (\$check->\"gerrorscount\")\r\
\n\t#\r\
\n\t##Resultado de ping se almacena en esta variable\r\
\n\t#\r\
\n\t:local pingresultserv1\r\
\n\t:local pingresultserv2\r\
\n\t:local avgserv1\r\
\n\t:local avgserv2\r\
\n\t#Declaracion de variable de error\r\
\n\t:local err 0\r\
\n\t#\r\
\n\t##Notificaciones de caida y levantada.\r\
\n\t#No puede contener espacios\r\
\n\t:local infoifdown \"Interface-\$ifname-\$description-caida.-(Interfaz \
down)-\$devicename\"\r\
\n\t:local infoun \"Interface-\$ifname-\$description-caida.-(Gateway unrea\
chable)-\$devicename\"\r\
\n\t:local infointernet \"Interface-\$ifname-\$description-caida.-(Linea s\
in internet)-\$devicename\"\r\
\n\t:local infoup \"Interface-\$ifname-\$description-arriba.-(Linea con in\
ternet)-\$devicename\"\r\
\n\t#\r\
\n\t##Informacion de linea\r\
\n\t:put (\"ifname\" . \" | \" . \"description\" . \" | \" . \"gateway\" \
. \" | \" . \"table\" . \" | \" . \"status\" . \" | \" . \"delaystatus\
\");\r\
\n\t:put (\"\$ifname\" . \" \" . \"\$description\" . \" \" . \"\$gateway\
\" . \" \" . \"\$table\" . \" \" . \"\$status\" . \" \" . \"\$delaystat\
us\");\r\
\n\t###Control de Interfaz\r\
\n\t#\r\
\n\t##Detecta estado de interface\r\
\n\t#\r\
\n\t:local ifrunn [interface get \$ifname running]\r\
\n\t#\r\
\n\t##Chequea estado de interface #Si el estado de la interface es running\
=false la marca como caida.\r\
\n\t:if (\$ifrunn = false) do={\r\
\n\t\t:set \$err 1\r\
\n\t\t:if (\$status = 1) do={\r\
\n \t#Setea isp como caido\r\
\n\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t#log\r\
\n\t\t\t:log warning \$infoifdown\r\
\n\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMessag\
e\\\?chat_id=\$chatid&text=\$infoifdown\" keep-result=no\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t##Detecta estado del gateway\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t:foreach existgw in=[/ip route find comment=\$description] do={\r\
\n\t\t\t:local gwstat [/ip route get \$existgw gateway-status]\r\
\n\t\t\t#\r\
\n\t\t\t##Chequea estado del gateway #Si el estado del gateway es \"unreac\
hable\" la marca como caida.\r\
\n\t\t\t:if (\$gwstat = \"\$gateway unreachable\") do={\r\
\n\t\t\t\t:set \$err 1\r\
\n\t\t\t\t:if (\$status = 1) do={\r\
\n\t\t\t\t\t#Setea isp como caido\r\
\n\t\t\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t\t\t#log\r\
\n\t\t\t\t\t:log warning \$infoun\r\
\n\t\t\t\t\t#Incrementar contador de error\r\
\n\t\t\t\t\t:set (\$check->\"gerrorscount\") (\$errorscount+1);\r\
\n\t\t\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t\t\t/ip route disable [/ip route find routing-mark=\$table]\r\
\n\t\t\t\t\t\t\t/ip route disable [/ip route find comment=\$description]\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMe\
ssage\\\?chat_id=\$chatid&text=\$infoun\" keep-result=no\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t##Comprobacion de acceso a Internet en conexion\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t##Seteo ruta con server1\r\
\n\t\t:put \"Comprobacion a \$serv1\"\r\
\n\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address=\$s\
erv1 gateway=\$gateway;\r\
\n\t\t##Seteo la variable de estado a false\r\
\n\t\t:set \$pingresultserv1 false;\r\
\n\t\t##Espera fijacion de ruta\r\
\n\t\t:delay 2\r\
\n\t\t##Hago ping y carga la variable de respuesta de ping.\r\
\n\t\t/tool flood-ping \$serv1 count=10 size=38 do={\r\
\n \t:if (\$\"received\" >= 8) do={\r\
\n \t\t:set \$pingresultserv1 true;\r\
\n \t\t:set \$avgserv1 \$\"avg-rtt\";\r\
\n \t\t}\r\
\n \t}\r\
\n\t\t##Chequeo de resultado de ping e informe de prblemas en lineas.\r\
\n\t\t:if (\$pingresultserv1 != true) do={\r\
\n\t\t\t##Si falla el primer server seteo el segundo\r\
\n\t\t\t:put \"Comprobacion a \$serv2\"\r\
\n\t\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address=\
\$serv2 gateway=\$gateway;\r\
\n\t\t\t##Seteo la variable de estado a false\r\
\n\t\t\t:set \$pingresultserv2 false;\r\
\n\t\t\t##Espera fijacion de ruta\r\
\n\t\t\t:delay 2\r\
\n\t\t\t##Hago ping y carga la variable de respuesta de ping.\r\
\n\t\t\t/tool flood-ping \$serv2 count=10 size=38 do={\r\
\n \t\t:if (\$\"received\" >= 8) do={\r\
\n\t \t\t:set \$pingresultserv2 true;\r\
\n\t \t\t:set \$avgserv2 \$\"avg-rtt\";\r\
\n\t \t\t}\r\
\n\t \t}\r\
\n\t\t\t:if (\$pingresultserv2 != true) do={\r\
\n\t\t\t\t/ip route set [/ip route find comment=\"fail-over\"] dst-address\
=\$ipfetch1 gateway=\$gateway;\r\
\n\t\t\t\t##Espera fijacion de ruta\r\
\n\t\t\t\t:delay 2\r\
\n\t\t\t\t:do {/tool fetch url=\"\$furl1\" mode=\$fmode1} \\\r\
\n\t\t\t\ton-error={\r\
\n\t\t\t\t\t##Monitor traffic\r\
\n\t\t\t\t\t/interface monitor-traffic \$ifname once do={ \r\
\n\t\t\t\t\t\t:if (\$\"rx-bits-per-second\" < \$bandwidth) do={\r\
\n\t\t\t\t\t\t\t:set \$err 1\r\
\n\t\t\t\t\t\t\t:if (\$status = 1) do={\r\
\n\t\t\t\t\t\t\t\t#Setea isp como caido\r\
\n\t\t\t\t\t\t\t\t:set (\$check->\"gstatus\") 0\r\
\n\t\t\t\t\t\t\t\t#log\r\
\n\t\t\t\t\t\t\t\t:log warning \$infointernet\r\
\n\t\t\t\t\t\t\t\t#Incrementar contador de error\r\
\n\t\t\t\t\t\t\t\t:set (\$check->\"gerrorscount\") (\$errorscount+1);\r\
\n\t\t\t\t\t\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t\t\t\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t/ip route disable [/ip route find routing-mark=\$tab\
le]\r\
\n\t\t\t\t\t\t\t\t\t\t/ip route disable [/ip route find comment=\$descript\
ion]\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t#Ejecuta script externo. Ejemplo de uso: Bloquear pagina\
s de alto consumo.\r\
\n\t\t\t\t\t\t\t\t:if (\$extexecset = 1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$extexecen = 1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t:execute script=\$extexecnamedown\r\
\n\t\t\t\t\t\t\t\t\t\t:set (\$check->\"gexexstatus\") 1\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/\
sendMessage\\\?chat_id=\$chatid&text=\$infointernet\" keep-result=no\r\
\n\t\t\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t\t\t}\t\r\
\n\t\t\t\t\t\t\t}\t\t\t\t\t\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t} \r\
\n\t\t}\r\
\n\t}\r\
\n\t##Accion ante cambio\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t:if (\$status = 0) do={\r\
\n\t\t\t#Setea isp como caido\r\
\n\t\t\t:set (\$check->\"gstatus\") 1\r\
\n\t\t\t#log\r\
\n\t\t\t:log warning \$infoup\r\
\n\t\t\t#Deshabilita rutas con tablas del isp\r\
\n\t\t\t:if (\$disgatset=1) do={\r\
\n\t\t\t\t:if (\$disgaten=1) do={\r\
\n\t\t\t\t\t/ip route enable [/ip route find routing-mark=\$table]\r\
\n\t\t\t\t\t/ip route enable [/ip route find comment=\$description]\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t\t#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto \
consumo.\r\
\n\t\t\t:if (\$extexecset = 1) do={\r\
\n\t\t\t\t:if (\$extexecen = 1) do={\r\
\n\t\t\t\t\t:execute script=\$extexecnameup\r\
\n\t\t\t\t\t:set (\$check->\"gexexstatus\") 0\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/sendMessag\
e\\\?chat_id=\$chatid&text=\$infoup\" keep-result=no\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t#Control de latencia\r\
\n\t:if (\$err = 0) do={\r\
\n\t\t##Latency habilitado\?\r\
\n\t\t:if (\$latencyset = 1) do={\r\
\n\t\t\t:if (\$latencyen = 1) do={\r\
\n\t\t\t\t##Notificaciones de latencia\r\
\n\t\t\t\t:local infohlatency \"Interface-\$ifname-\$description-con-alta-\
latencia-\$avgserv1.\"\r\
\n\t\t\t\t:local infonlatency \"Interface-\$ifname-\$description-con-laten\
cia-normal-\$avgserv1.\"\r\
\n\t\t\t\t##Comprobacion de delay\r\
\n\t\t\t\t:if (\$avgserv1 > \$maxdelay) do={\r\
\n\t\t\t\t\t:if (\$delaystatus = 1) do={\r\
\n\t\t\t\t\t\t:set (\$check->\"gdelaystatus\") 0\r\
\n\t\t\t\t\t\t:log warning \$infohlatency\r\
\n\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/send\
Message\\\?chat_id=\$chatid&text=\$infohlatency\" keep-result=no\r\
\n\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t\t:if (\$avgserv1 <= \$maxdelay) do={\r\
\n\t\t\t\t\t:if (\$delaystatus = 0) do={\r\
\n\t\t\t\t\t\t:set (\$check->\"gdelaystatus\") 1\r\
\n\t\t\t\t\t\t:log warning \$infonlatency\r\
\n\t\t\t\t\t\t#Envia aviso a Telegram si esta activo\r\
\n\t\t\t\t\t\t:if (\$notificationset=1) do={\r\
\n\t\t\t\t\t\t\t:if (\$notificationen=1) do={\r\
\n\t\t\t\t\t\t\t\t/tool fetch url=\"https://api.telegram.org/bot\$bot/send\
Message\\\?chat_id=\$chatid&text=\$infonlatency\" keep-result=no\r\
\n\t\t\t\t\t\t\t}\r\
\n\t\t\t\t\t\t}\r\
\n\t\t\t\t\t}\r\
\n\t\t\t\t}\r\
\n\t\t\t}\r\
\n\t\t}\r\
\n\t}\r\
\n\t:set \$err 0\r\
\n}"

Sección de actualización

Ésta sección del script es la que se modifica sin modificar los datos propios del rotuer donde está instalado. Es decir en esta versión no se encuentran las variables globales de configuración. Solo es el código de ejecución.

#------------------------------------------#
#V3.0
#
##Notificaciones
:global notificationset
:global disgatset
:global bot
:global chatid
:global devicename
#
##Activar/Desactivar control de latencia (Si el valor es 1 esta activado si es 0 desactivado)
:global latencyset
#
##Nombre de scripts que se ejecutan externamente en caso de caida y reactivación de linea.
:global extexecset

##Ping a...
:local serv1 1.0.0.1
:local serv2 4.2.2.1
#
##Check DNS
:execute script="probedns"
:delay 3
:global probedns
:if ([:len $probedns] <= 0) do {
:log warning "Falla en DNS"
/ip dns set server=8.8.8.8,1.1.1.1
}
#
##Fetch. Cargar url y mode sin ""
:local ipfetch1 93.184.216.34
:local furl1 http://example.com/index.html;
:local fmode1 http;
#
##Loop de chequeo.
:foreach check in=$peers do={
#:put $check
#
###Extraccion de variables
:local ifname ($check->"gifname")
:local description ($check->"gdescription")
:local gateway ($check->"ggateway")
:local table ($check->"gtable")
:local notificationen ($check->"gnotificationen")
:local disgaten ($check->"gdisgaten")
:local latencyen ($check->"glatencyen")
:local extexecen ($check->"gextexecen")
:local maxdelay ($check->"gmaxdelay")
:local bandwidth ($check->"gbandwidth")
:local extexecnameup ($check->"gextexecnameup")
:local extexecnamedown ($check->"gextexecnamedown")
:local delaystatus ($check->"gdelaystatus")
:local status ($check->"gstatus")
:local exexstatus ($check->"gexexstatus")
:local errorscount ($check->"gerrorscount")
#
##Resultado de ping se almacena en esta variable
#
:local pingresultserv1
:local pingresultserv2
:local avgserv1
:local avgserv2
#Declaracion de variable de error
:local err 0
#
##Notificaciones de caida y levantada.
#No puede contener espacios
:local infoifdown "Interface-$ifname-$description-caida.-(Interfaz down)-$devicename"
:local infoun "Interface-$ifname-$description-caida.-(Gateway unreachable)-$devicename"
:local infointernet "Interface-$ifname-$description-caida.-(Linea sin internet)-$devicename"
:local infoup "Interface-$ifname-$description-arriba.-(Linea con internet)-$devicename"
#
##Informacion de linea
:put ("ifname" . " | " . "description" . " | " . "gateway" . " | " . "table" . " | " . "status" . " | " . "delaystatus");
:put ("$ifname" . " " . "$description" . " " . "$gateway" . " " . "$table" . " " . "$status" . " " . "$delaystatus");
###Control de Interfaz
#
##Detecta estado de interface
#
:local ifrunn [interface get $ifname running]
#
##Chequea estado de interface #Si el estado de la interface es running=false la marca como caida.
:if ($ifrunn = false) do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infoifdown
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoifdown" keep-result=no
}
}
}
}
##Detecta estado del gateway
:if ($err = 0) do={
:foreach existgw in=[/ip route find comment=$description] do={
:local gwstat [/ip route get $existgw gateway-status]
#
##Chequea estado del gateway #Si el estado del gateway es "unreachable" la marca como caida.
:if ($gwstat = "$gateway unreachable") do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infoun
#Incrementar contador de error
:set ($check->"gerrorscount") ($errorscount+1);
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route disable [/ip route find routing-mark=$table]
/ip route disable [/ip route find comment=$description]
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoun" keep-result=no
}
}
}
}
}
}
##Comprobacion de acceso a Internet en conexion
:if ($err = 0) do={
##Seteo ruta con server1
:put "Comprobacion a $serv1"
/ip route set [/ip route find comment="fail-over"] dst-address=$serv1 gateway=$gateway;
##Seteo la variable de estado a false
:set $pingresultserv1 false;
##Espera fijacion de ruta
:delay 2
##Hago ping y carga la variable de respuesta de ping.
/tool flood-ping $serv1 count=10 size=38 do={
:if ($"received" >= 8) do={
:set $pingresultserv1 true;
:set $avgserv1 $"avg-rtt";
}
}
##Chequeo de resultado de ping e informe de prblemas en lineas.
:if ($pingresultserv1 != true) do={
##Si falla el primer server seteo el segundo
:put "Comprobacion a $serv2"
/ip route set [/ip route find comment="fail-over"] dst-address=$serv2 gateway=$gateway;
##Seteo la variable de estado a false
:set $pingresultserv2 false;
##Espera fijacion de ruta
:delay 2
##Hago ping y carga la variable de respuesta de ping.
/tool flood-ping $serv2 count=10 size=38 do={
:if ($"received" >= 8) do={
:set $pingresultserv2 true;
:set $avgserv2 $"avg-rtt";
}
}
:if ($pingresultserv2 != true) do={
/ip route set [/ip route find comment="fail-over"] dst-address=$ipfetch1 gateway=$gateway;
##Espera fijacion de ruta
:delay 2
:do {/tool fetch url="$furl1" mode=$fmode1} \
on-error={
##Monitor traffic
/interface monitor-traffic $ifname once do={ 
:if ($"rx-bits-per-second" < $bandwidth) do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infointernet
#Incrementar contador de error
:set ($check->"gerrorscount") ($errorscount+1);
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route disable [/ip route find routing-mark=$table]
/ip route disable [/ip route find comment=$description]
}
}
#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto consumo.
:if ($extexecset = 1) do={
:if ($extexecen = 1) do={
:execute script=$extexecnamedown
:set ($check->"gexexstatus") 1
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infointernet" keep-result=no
}
} 
} 
}
}
}
} 
}
}
##Accion ante cambio
:if ($err = 0) do={
:if ($status = 0) do={
#Setea isp como caido
:set ($check->"gstatus") 1
#log
:log warning $infoup
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route enable [/ip route find routing-mark=$table]
/ip route enable [/ip route find comment=$description]
}
}
#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto consumo.
:if ($extexecset = 1) do={
:if ($extexecen = 1) do={
:execute script=$extexecnameup
:set ($check->"gexexstatus") 0
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoup" keep-result=no
}
}
}
}
#Control de latencia
:if ($err = 0) do={
##Latency habilitado?
:if ($latencyset = 1) do={
:if ($latencyen = 1) do={
##Notificaciones de latencia
:local infohlatency "Interface-$ifname-$description-con-alta-latencia-$avgserv1."
:local infonlatency "Interface-$ifname-$description-con-latencia-normal-$avgserv1."
##Comprobacion de delay
:if ($avgserv1 > $maxdelay) do={
:if ($delaystatus = 1) do={
:set ($check->"gdelaystatus") 0
:log warning $infohlatency
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infohlatency" keep-result=no
}
}
}
}
:if ($avgserv1 <= $maxdelay) do={
:if ($delaystatus = 0) do={
:set ($check->"gdelaystatus") 1
:log warning $infonlatency
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infonlatency" keep-result=no
}
}
}
}
}
}
}
:set $err 0
}

Script completo

#Llamado a matriz de control
:execute script="FaOvConf"
:global peer1
:global peer2
##Array que carga al loop
:local peers {$peer1;$peer2};
#------------------------------------------#
#V3.0
#
##Notificaciones
:global notificationset
:global disgatset
:global bot
:global chatid
:global devicename
#
##Activar/Desactivar control de latencia (Si el valor es 1 esta activado si es 0 desactivado)
:global latencyset
#
##Nombre de scripts que se ejecutan externamente en caso de caida y reactivación de linea.
:global extexecset

##Ping a...
:local serv1 1.0.0.1
:local serv2 4.2.2.1
#
##Check DNS
:execute script="probedns"
:delay 3
:global probedns
:if ([:len $probedns] <= 0) do {
:log warning "Falla en DNS"
/ip dns set server=8.8.8.8,1.1.1.1
}
#
##Fetch. Cargar url y mode sin ""
:local ipfetch1 93.184.216.34
:local furl1 http://example.com/index.html;
:local fmode1 http;
#
##Loop de chequeo.
:foreach check in=$peers do={
#:put $check
#
###Extraccion de variables
:local ifname ($check->"gifname")
:local description ($check->"gdescription")
:local gateway ($check->"ggateway")
:local table ($check->"gtable")
:local notificationen ($check->"gnotificationen")
:local disgaten ($check->"gdisgaten")
:local latencyen ($check->"glatencyen")
:local extexecen ($check->"gextexecen")
:local maxdelay ($check->"gmaxdelay")
:local bandwidth ($check->"gbandwidth")
:local extexecnameup ($check->"gextexecnameup")
:local extexecnamedown ($check->"gextexecnamedown")
:local delaystatus ($check->"gdelaystatus")
:local status ($check->"gstatus")
:local exexstatus ($check->"gexexstatus")
:local errorscount ($check->"gerrorscount")
#
##Resultado de ping se almacena en esta variable
#
:local pingresultserv1
:local pingresultserv2
:local avgserv1
:local avgserv2
#Declaracion de variable de error
:local err 0
#
##Notificaciones de caida y levantada.
#No puede contener espacios
:local infoifdown "Interface-$ifname-$description-caida.-(Interfaz down)-$devicename"
:local infoun "Interface-$ifname-$description-caida.-(Gateway unreachable)-$devicename"
:local infointernet "Interface-$ifname-$description-caida.-(Linea sin internet)-$devicename"
:local infoup "Interface-$ifname-$description-arriba.-(Linea con internet)-$devicename"
#
##Informacion de linea
:put ("ifname" . " | " . "description" . " | " . "gateway" . " | " . "table" . " | " . "status" . " | " . "delaystatus");
:put ("$ifname" . " " . "$description" . " " . "$gateway" . " " . "$table" . " " . "$status" . " " . "$delaystatus");
###Control de Interfaz
#
##Detecta estado de interface
#
:local ifrunn [interface get $ifname running]
#
##Chequea estado de interface #Si el estado de la interface es running=false la marca como caida.
:if ($ifrunn = false) do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infoifdown
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoifdown" keep-result=no
}
}
}
}
##Detecta estado del gateway
:if ($err = 0) do={
:foreach existgw in=[/ip route find comment=$description] do={
:local gwstat [/ip route get $existgw gateway-status]
#
##Chequea estado del gateway #Si el estado del gateway es "unreachable" la marca como caida.
:if ($gwstat = "$gateway unreachable") do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infoun
#Incrementar contador de error
:set ($check->"gerrorscount") ($errorscount+1);
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route disable [/ip route find routing-mark=$table]
/ip route disable [/ip route find comment=$description]
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoun" keep-result=no
}
}
}
}
}
}
##Comprobacion de acceso a Internet en conexion
:if ($err = 0) do={
##Seteo ruta con server1
:put "Comprobacion a $serv1"
/ip route set [/ip route find comment="fail-over"] dst-address=$serv1 gateway=$gateway;
##Seteo la variable de estado a false
:set $pingresultserv1 false;
##Espera fijacion de ruta
:delay 2
##Hago ping y carga la variable de respuesta de ping.
/tool flood-ping $serv1 count=10 size=38 do={
:if ($"received" >= 8) do={
:set $pingresultserv1 true;
:set $avgserv1 $"avg-rtt";
}
}
##Chequeo de resultado de ping e informe de prblemas en lineas.
:if ($pingresultserv1 != true) do={
##Si falla el primer server seteo el segundo
:put "Comprobacion a $serv2"
/ip route set [/ip route find comment="fail-over"] dst-address=$serv2 gateway=$gateway;
##Seteo la variable de estado a false
:set $pingresultserv2 false;
##Espera fijacion de ruta
:delay 2
##Hago ping y carga la variable de respuesta de ping.
/tool flood-ping $serv2 count=10 size=38 do={
:if ($"received" >= 8) do={
:set $pingresultserv2 true;
:set $avgserv2 $"avg-rtt";
}
}
:if ($pingresultserv2 != true) do={
/ip route set [/ip route find comment="fail-over"] dst-address=$ipfetch1 gateway=$gateway;
##Espera fijacion de ruta
:delay 2
:do {/tool fetch url="$furl1" mode=$fmode1} \
on-error={
##Monitor traffic
/interface monitor-traffic $ifname once do={ 
:if ($"rx-bits-per-second" < $bandwidth) do={
:set $err 1
:if ($status = 1) do={
#Setea isp como caido
:set ($check->"gstatus") 0
#log
:log warning $infointernet
#Incrementar contador de error
:set ($check->"gerrorscount") ($errorscount+1);
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route disable [/ip route find routing-mark=$table]
/ip route disable [/ip route find comment=$description]
}
}
#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto consumo.
:if ($extexecset = 1) do={
:if ($extexecen = 1) do={
:execute script=$extexecnamedown
:set ($check->"gexexstatus") 1
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infointernet" keep-result=no
}
} 
} 
}
}
}
} 
}
}
##Accion ante cambio
:if ($err = 0) do={
:if ($status = 0) do={
#Setea isp como caido
:set ($check->"gstatus") 1
#log
:log warning $infoup
#Deshabilita rutas con tablas del isp
:if ($disgatset=1) do={
:if ($disgaten=1) do={
/ip route enable [/ip route find routing-mark=$table]
/ip route enable [/ip route find comment=$description]
}
}
#Ejecuta script externo. Ejemplo de uso: Bloquear paginas de alto consumo.
:if ($extexecset = 1) do={
:if ($extexecen = 1) do={
:execute script=$extexecnameup
:set ($check->"gexexstatus") 0
}
}
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infoup" keep-result=no
}
}
}
}
#Control de latencia
:if ($err = 0) do={
##Latency habilitado?
:if ($latencyset = 1) do={
:if ($latencyen = 1) do={
##Notificaciones de latencia
:local infohlatency "Interface-$ifname-$description-con-alta-latencia-$avgserv1."
:local infonlatency "Interface-$ifname-$description-con-latencia-normal-$avgserv1."
##Comprobacion de delay
:if ($avgserv1 > $maxdelay) do={
:if ($delaystatus = 1) do={
:set ($check->"gdelaystatus") 0
:log warning $infohlatency
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infohlatency" keep-result=no
}
}
}
}
:if ($avgserv1 <= $maxdelay) do={
:if ($delaystatus = 0) do={
:set ($check->"gdelaystatus") 1
:log warning $infonlatency
#Envia aviso a Telegram si esta activo
:if ($notificationset=1) do={
:if ($notificationen=1) do={
/tool fetch url="https://api.telegram.org/bot$bot/sendMessage\?chat_id=$chatid&text=$infonlatency" keep-result=no
}
}
}
}
}
}
}
:set $err 0
}

Scripts de bloqueos

Ésto es un ejemplo de los scripts de ejecución externa que pueden ser utilizados con el script de fail-over.

DownEvent

add name=DownEvent_peer1 owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/ip firewall filter\r\
\nadd action=drop chain=forward comment=FailOver content=youtube.com dst-port=80,443 protocol=tcp\r\
\nadd action=drop chain=forward comment=FailOver content=youtube.com dst-port=80,443 protocol=udp\r\
\nadd action=drop chain=forward comment=FailOver content=googlevideo.com dst-port=80,443 protocol=tcp\r\
\nadd action=drop chain=forward comment=FailOver content=googlevideo.com dst-port=80,443 protocol=udp\r\
\nadd action=drop chain=forward comment=FailOver content=netflix.com dst-port=80,443 protocol=tcp\r\
\nadd action=drop chain=forward comment=FailOver content=windowsupdate.com dst-port=80,443 protocol=tcp\r\
\nadd action=drop chain=forward comment=FailOver content=microsoft.com dst-port=80,443 protocol=tcp\r\
\n"

UPEvent

add name=UPEvent_peer1 owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\
"/ip firewall filter remove [/ip firewall filter find comment=\"FailOver\"]"