balancing y failover

20 de enero de 2010

Tengo hasta 5 conexiones de salida a Internet, entre caudales garantizados, ADSL, SDSL, etc.
La idea es centralizar todas estas salidas bajo un único gateway de forma que podamos hacer balanceo de carga y failover. Con el balanceo de carga conseguimos que unas peticiones vayan por una línea y otras por otra de forma automática y transparente para el usuario. Con el failover conseguimos que en caso de caída de una conexión de salida, todo el tráfico continuará saliendo por otra conexión.
Hay que tener presente que esta solución no hace una suma de anchos de banda, simplemente reparte las peticiones sobre una u otra conexión.

En el siguiente ejemplo utilizaremos dos conexiones a Internet ADSL, las dos de 6Mb. Utilizaremos una maquina Linux con tres interfaces Ethernet. Una conectada a una ADSL, otra conectada a otra ADSL y por último una interfaz conectada a nuestra red interna. Esta máquina hará de gateway de todos nuestros usuarios de la red interna.

En vez de utilizar una ruta por defecto, configuraremos una ruta por defecto que es multicamino o "multi-path route". Por defecto el kernel equilibrará las rutas sobre los dos posibles proveedores.


Para realizar balanceo utilizaremos iproute y para realizar el failover utilizaremos el siguiente script gwping que es un daemon (escrito en bash) que lo que hace es comprobar cada cierto tiempo el estado de la línea. Si la línea cae automáticamente realiza el switch. Cuando las dos líneas están activas continua haciendo el balancing.

Lo primero que hacemos es añadir estas instrucciones dentro de nuestro /etc/rc.local:

# activamos el forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# le decimos que todos los paquetes que vienen por una ADSL vuelven por la misma.
ip route add 192.168.1.0/24 dev eth0 src 192.168.1.10 table ADSL1
ip route add default via 192.168.1.1 table ADSL1
ip route add 192.168.0.0/24 dev eth1 src 192.168.0.10 table ADSL2
ip route add default via 192.168.0.1 table ADSL2
ip rule add from 192.168.1.10 table ADSL1
ip rule add from 192.168.0.10 table ADSL2

# la carga se reparte (equitativamente) por diferentes gateway.
ip route add default scope global nexthop via 192.168.1.1 dev eth0 weight 1 
   nexthop via 192.168.0.1 dev eth1 weight 1

# activamos el nat en el gateway
iptables -F
iptables -t nat -F
iptables --delete-chain
iptables -t nat --delete-chain
iptables -t nat -A POSTROUTING --out-interface eth1 -j MASQUERADE
iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
iptables -A INPUT -p ICMP -j ACCEPT
iptables -A INPUT -p TCP -m state --state RELATED -j ACCEPT
iptables -A FORWARD --in-interface eth2 -j ACCEPT

nohup /usr/sbin/gwping &
Observar como se utiliza el parámetro “weight” para decir que las dos adsl tienen la misma importancia. Tienen la misma velocidad. Si tuviéramos una ADSL 4 veces más rápida que otra pondríamos algo como:
ip route add default scope global nexthop via 192.168.1.1 dev eth0 weight 1 
   nexthop via 192.168.0.1 dev eth1 weight 4
El siguiente paso es añadir las tablas ADSL1 y ADSL2 dentro del iproute. Para ello editamos el /etc/iptables2/rt_tables:
root@failover:~# cat /etc/iproute2/rt_tables 
255     local
254     main
253     default
0       unspec
1 ADSL1
2 ADSL2
Ahora copiamos nuestro script gwping a /usr/sbin y le damos permisos de ejecución:
# chmod 755 /usr/sbin/gwping
Si editamos el script gwping podemos configurar los primeros parámetros para ajustarlos a nuestra configuración.

+ EXTIF1 y EXTIF: nombre de la interfaces externas
+ IP1 e IP2: IP de las interfaces
+GW1 y GW2: IP de las ADSLs
+ W1 y W2: peso de cada una de las ADSLs
+ NAME1 y NAME2: nombre de las ADSLs

Una vez reiniciada la maquina debería correr en fondo el daemon gwping (ps –xa | grep gwping). Para comprobar que todo está funcionando debería crearse un fichero de log llamado /var/log/failover donde es posible comprobar como se va realizando el switch entre las ADSLs:
root@failover:/var/log# tail -f failover 
Ping status changed for ADSL2 from 1 to 0
Uptime status will be changed for ADSL1 from 1
Uptime status will be changed for ADSL2 from 1
Restoring default load balancing
ADSL2 Down
Ping status changed for ADSL2 from 0 to 1
Uptime status will be changed for ADSL2 from 0
Ping status changed for ADSL2 from 1 to 0
Uptime status will be changed for ADSL2 from 1
Restoring default load balancing
ADSL1 Down
Ping status changed for ADSL1 from 0 to 1
Uptime status will be changed for ADSL1 from 0
Switching to ADSL2
ADSL1 Down
ADSL1 Down
Ping status changed for ADSL1 from 1 to 0
Uptime status will be changed for ADSL1 from 1
Restoring default load balancing
ADSL1 Down
Para comprobar que todo funciona podéis hacer diferentes consultas desde diferentes usuarios de la red interna a paginas web como http://www.whatismyip.com y comprobar vosotros mismos como se obtienen IPs diferentes dependiendo de si la petición HTTP ha ido por una ADSL u otra.

Más información:
+ Routing por diferentes proveedores
+ Linux Advanced Routing & Traffic Control HOWTO

2 comentarios:

Anónimo dijo...

Yo antes usaba este tipo de scripts, pero desde que descubrí pfSense tardo 5 minutos en armas un servidor completo. Os recomiendo que visiteis este software.

Fabricio Palacios dijo...

Hola Amperis!!!

Tu blog es realmente bueno y te felicito de antemano.

Tengo una duda con este tutorial... debo configurar previamente el gateway de los dos isp en las interfaces?

Saludos,
Fabricio