Balanceo de Carga entre Gateways con un Router Linux

por Rubén Urrieta

si tienen varias conexiones a Internet y quieres usarlas todas al mismo tiempo este yuca es para ti, lo que debes tener en cuenta es que no vas a poder usarlas todas en la misma descarga, debido a que cada conexión tiene un rango de direcciones ip diferente y ningún servidor soporta una conexión desde múltiples IP’s, lo que si se puede, es descargar desde varios servidores, o varios archivos del mismo servidor.

lo primero que debemos tener es un router con Linux funcionando y eliminar (o comentar) del archivo /etc/network/interfaces las lineas gateway.

luego definir en /etc/iproute2/rt_tables una tabla de rutas por cada conexión a internet que tengas

echo 200 tabla1 » /etc/iproute2/rt_tables
echo 201 tabla2 » /etc/iproute2/rt_tables

donde 200 y 201 son identificadores internos que no deben repetirse, los desarrolladores del kernel recomiendan que este sea un numero mayor o igual a 200; y tabla1 y tabla2 es el nombre que usaremos para referirnos a esta.

luego nos valemos de un script (que esta bien comentado) para realizar el balanceo de carga.

#!/bin/bash  

c=0 #dos variables que usaremos mas adelante  
max=2  

if1=eth0 #interface donde tenemos conectada la primera la conexión 
ip1=200.20.110.194 # ip que esta configurada en esta interface  
gw1=200.20.110.193 #gateway de esta conexión 
net1=200.20.110.192/29 #red de esta conexión 

#estos son los mismos datos pero de la otra conexión  
if2=eth2  
ip2=190.202.85.201  
gw2=190.202.85.202  
net2=190.202.85.200/29  

case "$1" in 
#un case para recibir un parámetro 
        start)  
                #adicionar la red publica del e1 a la tarjeta de red conectada al e1 en la tabla de enrutado con nombre tabla1  
                ip route add $net1 dev $if1 src $ip1 table tabla1  
                #gateway para la tabla tabla1  
                ip route add default via $gw1 table tabla1  
                ip route add $net1 dev $if1 src $ip1 table tabla2  
                #lo mismo de arriba pero para la tabla2  

                ip route add $net2 dev $if2 src $ip2 table tabla1 
                ip route add $net2 dev $if2 src $ip2 table tabla2  

                ip rule add from $ip1 table table1  
                ip rule add from $ip2 table table2  
                ip route add default scope global nexthop via $gw1 dev $if1 weight 1 nexthop via $gw2 dev $if2 weight 2

                ip route add 172.16.0.0/24  via         172.18.197.2         #aqui agragamos una red a la que accedemos utilizando otro router (si no tenemos otra red podemos quitar esta linea)  

                ip route |grep proto >> ip_route_main.autotmp   #agregamos en un archivo todas las rutas directamente conectadas a nuestro router  

                while [ "$c" -lt "$max" ]; #hacemos un ciclo cuyas iteraciones están definidas por las variables que definimos al principio del script  
                do  
                   case "$c" in  
                       0)  
                               table=tabla1  
                               ip route add default via $gw1 table $table  
                       ;;
                       1)  
                               table=tabla2  
                               ip route add default via $gw2 table $table  
                       ;;  
                       *)  
                echo "aqui hay un error"  
                       ;;  
                   esac  
                   c=$(( c + 1 )) # amuntamos el valor de la variable c  
                   ip route add 172.16.0.0/24   via         172.18.197.2        table $table  # agregamos la red externa a las nuevas tablas (si no tenemos otra red podemos quitar esta linea)  
                   echo "configurando la tabla de enrrutado para: $table"  # un mensaje para saber donde esta  

                   while read red dev eth proto kernel scope link src ip  #un ciclo para agregar las rutas del main en las nuevas tablas 
                   do  
                        ip route add $red dev $eth src $ip table $table #agrega la red la tabla que toque segun el primer ciclo...   
                   done < ip_route_main.autotmp #aqui definimos el archivo que usara para agregar las redes    
              done  #fin del primer ciclo  


        ip rule add from 172.16.1.229   table tabla1  #aqui podemos definir si queremos que una dirección ip de la red local use una tabla de rutas especifica  
        ip rule add from 172.16.1.230   table tabla2  


    ;; #fin para cuando se ingresa con el parametro start  
       #aqui ya el balanceador esta totalmente activo, si queremos 
       #detenerlo colocamos el parametro stop y se ejecutaran las 
       #siguientes lineas...
        stop)
                    while [ "$c" -lt "$max" ];  
                    do  

                           case "$c" in
                                0)
                                            table=tabla1  
                                ;;  
                                1)  
                                            table=tabla2  
                                ;;  
                                *)  
                                            echo "aqui hay un error"  
                                ;;  
                           esac  

                           c=$(( $c + 1 ))   

                          /sbin/ip route |grep -v 169.254.0.0|grep \/ >> ip_route.autotmp #tomamos las rutas de la tabla main  
                          while read red dev nic proto kernel escope link src ip metric metricnun  
                          do  
                                ip route del $red table $table #borramos las redes de las nuevas tablas
                          done < ip_route.autotmp  
                          ip route del default table $table #borramos la ruta por defecto de la tabla  
                        done  
                    done  

                    /sbin/ip rule |grep lookup |grep -v all >> rule.autotmp  
                    while read nun from parametro look table2  
                    do  
                                ip rule del from $parametro table $table2 #borramos las reglas para las direcciones especificas  
                    done < rule.autotmp  

                    echo " el balanceador a sido detenido "  
        ;;  
        restart)  

                    #si hacemos algun cambio en la parte de start y queremos que 
                    #estos cambios tengan efecto ejecutamos el script con el parametro 
                    #restart para que se detenga y se inicie de nuevo  

                    $0 stop  
                    $0 start  
                    echo "el balanceador se a reiniciado"  
        ;;  
        *)  
                    echo "parametros permitidos { start | stop | restart | status [ tabla1 | tabla2 |  * ] }"  
        ;;  
esac #fin para cuando se recibe un parametro  
rm -rf *.autotmp #borramos los archivos creados dentro del script  

aqui les dejo unos enlaces que les pueden ser de utilidad…

primer enlace
segundo enlace
libro de enrutamiento avanzado en GNU/Linux