Script para realizar failover en balanceadores con conexiones dinámicas

Fuente: http://www.ryohnosuke.com/foros/index.php?threads/1648/

Autor: whernandez,

Publicado: 29 Dic 2011

Como dice el titulo les explicare un código desarrollado por mi para realizar el tan problemático failover que muchos no pueden lograr debido a que no se puede hacer con solo presionar clips. Es importante destacar que la idea no es solo copiar y pegar, sino leer para comprender lo que se hace para que así ud pueda aportar nuevas ideas para mejorar este u otro código.

Manos a la obra:

Como he mencionado este código aplica para conexiones dinámicas lo cual cada interfaz debe obtener su ip por el DHCP-CLIENT, recomiendo que solo una de las interfaces tenga add-default-route=yes la cual seria la que use el router por defecto para su uso.

Supondremos que todas sus interfaces para internet tienen el nombre wan1, wan2, wan3, …, wanX y sus new-routing-mark son to_wan1, to_wan2, to_wan3, …, to_wanX.

En routes las rutas deben estar definidas de la siguiente manera:

CODE, HTML o PHP Insertado:
/ip route
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=wan1 routing-mark=to_wan1 scope=30 target-scope=10
add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=wan2 routing-mark=to_wan2 scope=30 target-scope=10

add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=wanX routing-mark=to_wanX scope=30 target-scope=10

El valor de X sera el numero total de interfaces de salida que tiene su balanceador y el cual debe ser sustituido por su valor en la siguiente linea de código.

CODE, HTML o PHP Insertado:
:global X (valor de X);
:for i from=1 to=$X do={

El script se ejecutara tanta interfaces ud halla definido a X.

CODE, HTML o PHP Insertado:
   :local pingresultado [/ping 208.67.222.222 interface="wan$i" count=10];

La dirección para el ping puede ser de su elección.

CODE, HTML o PHP Insertado:
:if ($pingresultado>0) do={
            :local gatewayactivo [/ip route get [find routing-mark="to_wan$i"] gateway ];
            :if ($gatewayactivo != "to_wan$i") do={
            :log error "¡WAN$i Arriba!";
            /ip route set [find routing-mark="to_wan$i"] gateway="wan$i";
            :log info "WAN$i esta activo y se actualizo el Gateway" ;
            }   
    }

En esta parte del código si la interfaz funciona se verificara si el gateway que tiene asignada una ruoting-mark es la que le corresponde

CODE, HTML o PHP Insertado:
   :if ($pingresultado=0) do={
        :log error "¡WAN$i Caido!";
        :local status [/ip dhcp-client get [/ip dhcp-client find interface="wan$i"] status ];
        :if ($status="bound") do={
            /ip dhcp-client release [find interface="wan$i"];
        }

En el caso que la interfaz este caída y el status del dhcp este en bound haremos que esa interfaz tenga un release con el fin de renovar su conexión.

CODE, HTML o PHP Insertado:
        :global gatewayactivo;        
        :global j ($i);
        :do {
            :set j ($j+1);
            if ($j=$X+1) do={
                :set j 1;
            }            
            :local pingresultado [/ping 208.67.222.222 interface="wan$j" count=3];
            :if ($pingresultado>0) do={ 
                /ip route set [find routing-mark="to_wan$i"] gateway="wan$j";
                :log info "WAN$i esta inactivo se le asigno el Gateway del WAN$j" ;
            }    
            :set gatewayactivo [/ip route get [find routing-mark="wan$i"] gateway ];
        } while=($gatewayactivo != "wan$j");
    }
}

Luego por ultimo se buscara el gateway siguiente y que este activo para asignarle a esa routing-mark el cual su interfaz se cayo.

Como podrán ver el código puede ser usado para una cantidad infinita de interfaces donde verificara su estado y cambiara el gateway de la routing-mark al cual se halla caído.

El código completo:

CODE, HTML o PHP Insertado:
:global X (valor de X);
:for i from=1 to=$X do={
    :local pingresultado [/ping 208.67.222.222 interface="wan$i" count=10];
    :if ($pingresultado>0) do={
            :local gatewayactivo [/ip route get [find routing-mark="to_wan$i"] gateway ];
            :if ($gatewayactivo != "to_wan$i") do={
            :log error "¡WAN$i Arriba!";
            /ip route set [find routing-mark="to_wan$i"] gateway="wan$i";
            :log info "WAN$i esta activo y se actualizo el Gateway" ;
            }   
    }
    :if ($pingresultado=0) do={
        :log error "¡WAN$i Caido!";
        :local status [/ip dhcp-client get [/ip dhcp-client find interface="wan$i"] status ];
        :if ($status="bound") do={
            /ip dhcp-client release [find interface="wan$i"];
        }
        :global gatewayactivo;        
        :global j ($i);
        :do {
            :set j ($j+1);
            if ($j=$X+1) do={
                :set j 1;
            }            
            :local pingresultado [/ping 208.67.222.222 interface="wan$j" count=3];
            :if ($pingresultado>0) do={ 
                /ip route set [find routing-mark="to_wan$i"] gateway="wan$j";
                :log info "WAN$i esta inactivo se le asigno el Gateway del WAN$j" ;
            }    
            :set gatewayactivo [/ip route get [find routing-mark="wan$i"] gateway ];
        } while=($gatewayactivo != "wan$j");
    }
}

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *