01 diciembre 2012

De como conectar 13 ADSL en balanceo de carga (o Linux load balancing and multipath HOWTO)

Antes que nada para los despistados que caigan acá y estén buscando una solución con un .exe y botón [siguiente]: bueno... buena suerte :-) !
Supongamos que viene el dueño de una empresa y les dice:
dueño- hola joven, mire usted, para el tipo de negocio que llevo necesito mucho ancho de banda
geek- bueno... existe speedy 5Megas, con eso debería bastarle
dueño: bien, pude funcionar... me llevo 13.
geek: (plop?!)
Esto les puede pasar en cualquier momento (el numero puede variar) así que estén atentos, yo por mi parte les dejo unos tips de como no morir en el intento.

1-Objetivos

  • Balancear los ADSL en una única conexión lógica (conntrack aware), pudiendo tener enlaces de distintas velocidades y proveedores, incluso conexiones no ADSL.
  • Que el número de ADSL pueda ir de 2 a N.
  • Monitorizar los ADSL para usar solo los que tengan servicio, y poder dar aviso o tomar otras medidas en caso de que haya enlaces caídos.
  • Que la solución sea genérica y facilmente replicable en otros servidores.
  • Que todo lo anterior sea automático 100%, es decir una vez hecho el setup que ya no requiera de intervención.
  • Ver gráficos del uso parcial y total (queda para otro post)
  • Controlar ancho de banda, para usuarios que están detrás (idem arriba :-)

2-Requisitos

  • Linux >=2.6.12 (Usé Ubuntu Hardy Server LTS, grosso ya le dedicaré un post)
  • Bash >=2
  • Iptables
  • Iproute2

3-Desarrollo

geek- hola, buen día, necesito 13 placas de red PCI
empleado(casa de computación)- bien aquí tiene
geek- bien, ahora necesito un mother para usarlas todas juntas
empleado- (plop?!)
Por ahora vamos a imaginar que encontramos un mother con 13 ports PCI así nos focalizamos en hacer funcionar el load balancing y una vez resuelto eso, retomaremos el tema de las 13 placas de red.
3.1-Primer paso: configurar los routers/modems ADSL
Una vez contratados los ADSL (conviene usar distintos providers para minimizar los cortes), se presenta la primer decisión clave:
  1. Levantar PPPOE con Linux (modem ADSL bridgeando)
  2. Levantar PPPOE con el propio modem (modem ADSL routeando)
En 1 estamos agregando una capa más de complejidad(pon,poff,cambio de IP), y estamos haciendo la solución ADSL-dependiente(o PPP dependiente).
Levantando los ADSL desde el router/modem, puedo usar una ip y un gw fijo en mi linux y eso hará que pueda usar el script con cualquier conexión que tenga ip fija y ya no importa si es ADSL o no.
Hoy por hoy es bastante común que el modem que nos entregan(siempre que sea ethernet) sea modem y router, y venga preconfigurado como router.
Dentro de los modems/routers que vi x ahí(todos low-cost) la mejor experiencia la tuve con los Zyxel, demostraron funcionar bastante bien, y tienen una interfaz via telnet bastante amena.
Así que entonces vamos a configurar cada modem en modo router, es decir con la interfaz WAN levantando PPP y la interfaz LAN apuntando hacia el linux.
Elegimos subredes /24 para que visualmente sea más intuitivo y en este caso elegí el rango de 10.0.0.0 porque la red LAN del Linux era en el rango 192.168.0.0/16 y separo así(visual y lógicamente) las dos redes.
Este es el esquema de lo que estamos buscando(*):
IP LAN modem/router ADSL                    IP "WAN" Linux
10.0.2.1                                    10.0.2.2
10.0.3.1                                    10.0.3.2
10.0.4.1                                    10.0.4.2
...                                         ... 
10.0.14.1                                   10.0.14.2

(*) empezamos desde 2, porque el 1 es un VLAN ID reservado, y me dio miedo usarlo :-S
3.2-Segundo paso: configurar el Linux
Para la configuración del linux necesitaba algo generico y sencillo de replicar,fundamentalmente para que el próximo cliente me amortice todo lo que no pude cobrar en este :-), y porque todo lo que hago trato de hacerlo así .
La solución fue ordenar el caos en un solo bash script (o casi). El script se llama firewall.sh porque en los servidores que administro las reglas de firewall siempre las pongo en ese archivo. En este caso veremos reglas de firewall(iptables) comandos de tc y otras yerbas en ese mismo script.
Lo más simple para entender la solución es analizar el script paso a paso.
Primero tenemos las variables de configuración, esto es lo que hace al script genérico la idea es tocar solo aquí cada vez que lo movemos a otro escenario.
  1. #!/bin/bash  
  2. ############ CONF GRAL ############  
  3. adsl_ifaces=(eth0.2     eth0.3          ...     eth0.14)  
  4. adsl_ips=(10.0.2.2      10.0.3.2        ...     10.0.14.2)  
  5. adsl_gws=(10.0.2.1      10.0.3.1        ...     10.0.14.1)  
  6. adsl_weight=(1          1               ...     1)  
  7. adsl_upload=(256        256             ...     256)  
Después comienza realmente el script, así que llegamos a la linea divisoria, si estás buscando una solución Copy and Paste, podés saltar todo esto y luchar directamente con el script completo.
Si, en cambio, querés entender un poco como funciona (y si en algún momento hay problemas vas a querer saber),seguí leyendo.
Estas lineas hacen al funcionamiento del script en si, para que pueda llamarlo con parámetros especiales para debugear o para ver lo que va a hacer sin que haga efectivamente nada. Pueden saltearse sanamente estas lineas e ir directamente al próximo parrafo.
  1. ############ THE SCRIPT ############  
  2. #PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"  
  3. test "$1" == "debug" && set -x  
  4. test "$1" == "show"  && iptables() { echo iptables "$@"} && ip() { echo ip "$@"} && tc() { echo tc "$@"} && ifconfig() { echo ifconfig "$@"}  
  5. test "$1" == "loadvars" && return 0  
  6.     
Por cada conexión necesitamos:
  • configurar la IP en cada interfaz
  • configurar una tabla de ruteo exclusiva para esa conexión, y una regla de ruteo.
    Esto lo necesitamos para:
    • hacer salir por esa conexión lo que entra por esa conexión
    • bindearnos a la interfaz y hacer pruebas de conectividad (ping -I, wget –bind-address)
  • poner una queue para limitar el ancho de banda (upload) por cada interfaz (esto lo hacemos porque los modems de ADSL tienen buffers muy grandes y si no limitamos el buffer se llena y tenemos varios segundos de delay)
Como dijimos vamos a crear una tabla de ruteo por cada conexión, por una cuestión visual vamos a usar nombres como adsl1,adsl2,etc. para identificar la tabla de cada conexión ADSL. Pero Linux, internamente, no maneja las tablas de ruteo por nombre sino por número, así que existe un lugar en donde vamos a tener que mapear nuestros nombres de tablas a números. Ese lugar es /etc/iproute2/rt_tables.
El formato es muy sencillo, les dejo un ejemplo:
11 adsl1
12 adsl2
13 adsl3
...
24 adsl14
Ahora nos toca hacer todo lo que enumeramos por cada conexión.
  1. # por cada conexión  
  2. for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
  3.         # doy de alta la interfaz  
  4.         ifconfig ${adsl_ifaces[n]} ${adsl_ips[n]} netmask 255.255.255.0 up  
  5.         # borro lo viejo  
  6.         ip route flush table adsl$((n+1)) 2>/dev/null  
  7.         ip rule del from ${adsl_ips[n]} table adsl$((n+1)) 2>/dev/null  
  8.         tc qdisc del dev ${adsl_ifaces[n]} root 2>/dev/null  
  9.         # baja latencia y queue en los adsl , usamos tbf que rulea para esto  
  10.         tc qdisc add dev ${adsl_ifaces[n]} root tbf rate ${adsl_upload[n]}kbit latency 50ms burst 1540  
  11.         # armo la tabla de ruteo “adsl$n” copiando la tabla main y cambiando el default gateway  
  12.         while read line ;do  
  13.                 test -z "${line##default*}" && continue  
  14.                 test -z "${line##nexthop*}" && continue  
  15.                 ip route add $line table adsl$((n+1))  
  16.         done < \  
  17.         <(/sbin/ip route ls table main)  
  18.         ip route add default table adsl$((n+1)) proto static via ${adsl_gws[n]} dev ${adsl_ifaces[n]}  
  19.         # creo la regla de ruteo para salir por esta talba si tenga esta source address  
  20.         ip rule add from ${adsl_ips[n]} table adsl$((n+1))  
  21.         # guardo para crear el balanceo  
  22.         multipath="$multipath nexthop via ${adsl_gws[n]} dev ${adsl_ifaces[n]} weight ${adsl_weight[n]}"  
  23. done  
  24. # ahora creo el default gw con multipath en la tabla main  
  25. ip route del default 2>/dev/null  
  26. ip route add default proto static $multipath  
  27. # flush de cache de ruteo  
  28. ip route flush cache  
Ahora viene la parte de configurar iptables, pero, ¿Porqué necesitamos iptables, si multipath es una cuestión de rutas y no de firewall?
Dos potenetes razones
  • porque necesitamos un balanceo connection-aware o un como también se le dice un router statefull. Es decir a medida que se generen nuevas conexiones (paginas web, chat de messenger, clientes p2p, sesiones ftp, etc) cada una de estas va a tomar un rumbo distinto, pero tenemos que asegurarnos de que cada conexión una vez establecida, siga saliendo siempre por el mismo enlace, de otra manera su ip de origen cambiaría y la conexión se perdería.
  • porque quizá querramos NATear los paquetes salientes.
Antes de escribir una sola regla de iptables, borro todo lo previo para arrancar de cero, como normalmente uso este archivo para cargar todas mis reglas de firewall esta bien que así sea, porque enseguida las voy a recrear.
  1. ############ IPTABLES ############  
  2. iptables -F  
  3. iptables -X  
  4. iptables -t nat -F  
  5. iptables -t nat -X  
  6. iptables -t mangle -F  
  7. iptables -t mangle -X  
  8.     
To NAT or not to NAT, he ahí el dilema.
Hay que elegir entre natear dos veces (en el linux y en el router) o complicarnos un poco más la vida por el bien de nuestros usuarios y natear solo una vez en el modem, y con el linux simplemente routear.
Para hacer esto en el linux solo necesitamos tener ip_forward activado, el famoso
echo 1 > /proc/sys/net/ipv4/ip_forward
o mas prolijo en /etc/sysctl.conf:
net.ipv4.ip_forward=1
Y luego en cada adsl configurar la ruta hacia nuestra LAN. Si x ejemplo tenemos la LAN 192.168.0.0/16, hay que agregar una ruta estática en los adsl.
Por ejemplo en el modem con ip 10.0.2.1 agregamos(pseudocódigo):
add 192.168.0.0/16 gateway 10.0.2.2
Y con eso basta, por lo que he podido comprobar los routers/modems natean todo lo que sale por su interfaz ppp así que esas ips 192.168.0.0/16 que el linux hace llegar crudas a los ADSL son NATeadas y luego el router sabe como devolver los paquete gracias a la ruta que le agregamos.
La otra opción era usar NAT en el Linux y no tener que tocar el router, habría que agregar esto al script(lo dejo comentado en el original):
  1. ############ NAT ############  
  2. # - hago masquerade por cada interfaz/conexión  
  3. for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
  4.         iptables -t nat -A POSTROUTING -o ${adsl_ifaces[n]} -j MASQUERADE  
  5. done  
  6.     
Firewall statefull (connection tracking)
Si simplemente balanceamos las conexiones agregando una ruta multipath y nada más, vamos a tener un problema.
Las rutas tienen un cache de unos 5 minutos por default. Entonces cuando el cache de la ruta que usé para loguearme en MSN messenger expire, me va a tocar otra ruta nueva para llegar al servidor de MSN, es decir, voy a seguir mandando packetes de una conexión establecida desde una ip de origen que nunca estableció la conexión, ergo el MSN se me va a cortar, y así me va a pasar con muchos otros protocolos, como puede ser una sesión de ssh o de un home banking.
Primer intento...
El primer intento fue aumentar el cache de las tablas de ruteo, hacerlo de un día por ejemplo, pero tiene varias contras
Uno es que realmente desaprovecha el balanceo de carga, porque por cada host de destino uso únicamente un enlace, y además, cada vez que se cae un enlace necesariamente debo flushear la tabla de ruteo, perdiendo todas las rutas cacheadas y genreando las no deseadas desconexiones.
Segundo intento... (la solución final)
Usando las listas del LUGMen recibí ayuda de Diego Woitasen, quien me hizo dar cuenta de que podíamos usar conntrack para mantener la correspondencia entre cada conexión y su respectivo enlace.
Conntrack es un modulo de netfilter(iptables) que nos da la posibilidad de guardar(--save-mark) una marka particular para un paquete que pertenece a una conexión. Una vez markado ese paquete, luego me puedo parar en los paquetes entrantes y decirles que restauren su marka (--restore mark). Cada packete tendrá una marka que identifica al enlace al que pertenece y de esa manera puedo tomar la decisión de ruteo de por cual enlace salir.
De esta forma tenemos un firewall multipath y satefull. Obviamente hay excepciones(todo lo que conntrack no puede trackear) pero son mínimas.
Entonces agregamos las reglas de iptables para hacer conntrack
  1. ############ CONNTRACK ############  
  2. # restauro la marka en PREROUTING antes de la decisión de ruteo.  
  3. iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark  
  4.   
  5. # CONNTRACK para el multipath  
  6. # creo una tabla aparte  
  7. iptables -t mangle -N my_connmark  
  8. # y hago pasar los packetes que aún nunca fueron markados  
  9. # (siempre serán paquetes que inician una conexión)  
  10. iptables -t mangle -A FORWARD -m mark --mark 0 -j my_connmark  
  11. # una vez procesado, borro la marka por si quiero usar las markas para otras cosas  
  12. # como x ej QoS y control ancho de banda  
  13. iptables -t mangle -A FORWARD -j MARK --set-mark 0x0  
  14.   
  15. # y ahora el contenido de la tabla aparte: my_conntrack  
  16. # para la LAN no me hace falta conntrack ya que tengo una sola interfaz  
  17. iptables -t mangle -A my_connmark -o eth1 -j RETURN  
  18. # por cada conexión  
  19. for((n=0;n<${#adsl_ifaces[@]};n++)); do  
  20.         #asocio una marka a cada interfaz  
  21.         iptables -t mangle -A my_connmark -o ${adsl_ifaces[n]} -j MARK --set-mark 0x$((n+1))  
  22.         iptables -t mangle -A my_connmark -i ${adsl_ifaces[n]} -j MARK --set-mark 0x$((n+1))  
  23. done  
  24. # la guardo para después poder hacer el –restore-mark en PREROUTING  
  25. iptables -t mangle -A my_connmark -j CONNMARK --save-mark  
  26. # por ultimo uso ip ru para hacer que el packete use la tabla de ruteo que le corresponde  
  27. for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
  28.         ip ru del fwmark 0x$((n+1)) table adsl$((n+1)) 2>/dev/null  
  29.         ip ru add fwmark 0x$((n+1)) table adsl$((n+1))  
  30. done  
  31.     
Y eso es todo, solo falta ejecutarlo y tendremos nuestra solución andando.A partir de este punto surgen otros interrogantes, como por ejemplo, como testeo que los enlaces estén funcionando, y como hago para adaptar el multipath en caso de que alguno de los enlaces se caiga. Si siguen leyendo, también hay respuestas a esas preguntas.
3.3-El script completo(firewall.sh)
Descargar el script completo: firewall.sh

4-Verificando cada conexión y actualizando el default gateway

Vamos a hacer ahora un segundo script, que debería correr cada unos 5 minutos por ejemplo, el cual va a testear la conectividad de cada uno de esos enlaces y actualizara la ruta multipath para que figuren solo los enlaces que están respondiendo.
Como hicimos con el script anterior lo analizamos por partes.Antes que nada cargo la info de cada adsl usando las mismas variables de firewall.sh así cualquier cambio que realice allí, este script actuará acorde.
Para que eso funcione tenemos que colocar la ruta completa de donde tengamos nuestro archivo firewall.sh
  1. #!/bin/bash  
  2. source /path/to/firewall.sh loadvars  
La primer dificultad que surge es como saber si un enlace esta caído o no. Después de rascarme bastante la cabeza dí con una solución que me dejo feliz.
Existen en internet lo que se conoce como root nameservers, que son la última autoridad cuando se hace una consulta de DNS. Estos son servidores redundantes y de alta disponibilidad, con una conectividad maravillosa, mantenidos por la ICANN. Como hacen funcionar a internet, alguno puede caer, pero no todos a la vez.
Estos "root nameservers" son 13, y se usan letras de la A a la M para para su identificación. Lo que hice fue testear cuales de esos servidores respondían ping (icmp echo), y quedaron 10 servidores.
  1. #A to M ROOT DNS world servers ip address  
  2. #I choose those that seems to accept icmp-echo-requests  
  3. root_nameservers="B C D E F I J K L M"  
El script hará un ping a cada uno de esos servidores parándose de a un enlace por vez. Al primer pong que recibimos, podemos afirmar con certeza que ese enlace esta up y no me hace falta seguir pingueando el resto.
  1. multipath_total=0  
  2. for((n=0;n>${#adsl_ifaces[@]};n++)); do  
  3.         pong=0  
  4.         for letter in $root_nameserversdo  
  5.                 if(ping -c1 -W2 $letter.root-servers.net -I ${adsl_ips[n]} &>/dev/null);then  
  6.                         pong=1  
  7.                         # el doble espacio antes de dev _does_matter_  
  8.                         multipath="$multipath nexthop via ${adsl_gws[n]}  dev ${adsl_ifaces[n]} weight ${adsl_weight[n]}"  
  9.                         let multipath_total+=1  
  10.                         break  
  11.                 fi  
  12.         done  
  13.     
Si para un enlace no recibo ninguna respuesta entonces ese enlace lo dejo fuera del multipath. Como un plus, también puedo aprovechar para hacer telnet a ese modem en particular y resetearlo, o mandar un mail avisando que ese enlace esta caído, o incluso hacer sonar la “bell” del servidor si habrá alguien escuchando.
  1.         #if no one answers  
  2.         if [[ $pong == 0 ]];then  
  3.                 #ejemplo telnet y reset, para un zyxel (opciones 24, 4 y 21)  
  4.                 # user=user;pass=pass;   
  5.                 #echo -e "$user\n$pass\n$24\n4\n21\n" | telnet ${adsl_gws[n]} &  
  6.                 # ejemplo hacer sonar el beep  
  7.                 #echo -e "\a"  
  8.                 # ejemplo mail  
  9.                 # echo “ip:${adsl_ips[n} iface:${adsl_ifaces[n]}” | mail -s “se cayo la conexión ${adsl_ips[n]}” someone@foo.bar  
  10.                 # logueo para futuro análisis  
  11.                 echo `date`" la conexion con ${adsl_gws[n]} esta down" >> /var/log/multipath_watchdog.log  
  12.     fi  
  13. done  
  14.     
Luego una vez que tengo toda la info estoy listo para tomar decisiones, voy a cambiar el default gateway solo en el caso de que tenga un multipath distinto al actual, ya que si los mismos enlaces que antes están up, no hace falta que modifique nada, y no pago el costo de un flush de la tabla de ruteo por ejemplo.
  1. #si todos están caídos dejo todo como estaba  
  2. test -z "${multipath}" && exit 1  
  3.   
  4. # cargo en $route el multipath actual  
  5. while read line ;do  
  6.         test -z "${line##default*}" && begin=1  
  7.         test "$begin" == 1 && route="$route ${line}"  
  8. done < \  
  9. <(/sbin/ip route ls)  
  10.   
  11. # armo el multipath de los que están up para poder comparar  
  12. # tengo que preguntar xq si hay solo un enlace up, la sintaxis cambia  
  13. if [[ $multipath_total > 1 ]];then  
  14.         # el doble espacio antes de proto _does_matter_  
  15.         route_multipath=" default  proto static${multipath}"  
  16. else  
  17.         route_multipath=${multipath#nexthop }  
  18.         route_multipath=${route_multipath% weight*}  
  19.         route_multipath=" default ${route_multipath/ dev/ dev} proto static"  
  20. fi  
  21.   
  22. #printf "%q\n" "${route}"  
  23. #printf "%q\n" "${route_multipath}"  
  24. # Ya tengo los 2 multipath, ahora puedo comparar  
  25. if [[ "$route" != "$route_multipath" ]];then  
  26.         # si no son iguales, es hora de cambiar el default gateway  
  27.         ip route chg default proto static $multipath  
  28.         ip route flush cache  
  29.         echo `date`" cambiando default gateway a $multipath" >> /var/log/multipath_watchdog.log  
  30. fi  
  31.     
Bien, eso también fue todo, ahora solo hay que agregarlo en alguna crontab para que se ejecute cada unos 5 minutos. Yo uso una crontab propia para esta y otras cosas periódicas que la llamo /etc/cron.d/watchdog
*/5 * * * * root /usr/local/bin/multipath_watchdog.sh
4.1-El script completo(multipath_watchdog.sh)
Descargar el script completo: multipath_watchdog.sh

5-Y las 13 placas?

Estem... estaba esperando que pregunten :-). Si bien al principio pareció complicado, a los dos minutos ya había una solución:placas PCI de 4 ports Funcionan bien, sólo son un poco caras (US$ ~150) comparado con lo que cuestan 4 placas de red(US$ ~36). El tema es que con 3 slots pci tengo 12 placas y yo necesito al menos 14(13 adsl + 1 LAN) y mothers con 4 o 5 solts PCI son un poco difícil de conseguir.
Así que si bien sirven, necesitaba encontrar una solución más genérica
Quizá algunos ya se estén preguntando para que necesito 13 placas si los puedo enchufar todos juntos a una sola ethernet y crear 13 alias en el linux, en principio es posible, pero puedo tener mucho más control(y lo necesito) si tengo una interfaz por cada conexión.
5.1-Dicen que el que busca encuentra y así fue: VLAN
VLAN permite crear redes físicas virtuales. Para conectarme desde linux a esa red virtual creo una interfaz que solo escuchará los frames ETHERNET que pertenezcan a esa red virtual.
De esta forma usando un switch VLAN de 24 bocas entre los modems/routers y el Linux , puedo decir que un puerto del switch, se mapee con una VLAN específica, y así usar 23 bocas del switch para conectar ADSL y con la boca restante conecto el Linux usando una VLAN por ADSL.
5.2-Configurando el switch VLAN
La idea principal es usar una boca del switch para conectar con el linux, y 13 bocas para conectar los ADSL.
En la boca que se conecta con el Linux configuro las VLAN respectivas, tanto en el port del switch, como del lado del Linux para que se puedan hablar.
Pero los modems/routers ADSL no hablan VLAN, por lo que necesito configurarlos de otra manera. Afortunadamente, los switchs VLAN ofrecen 2 modos de operación por puerto: tagged y untagged.
El modo tagged es en el que efectivamente se crea la VLAN en esa boca del switch.
El modo untagged en cambio, bindea un port con un VLAN ID determinado, pero sin requerir que el tráfico llegue con el tag VLAN, es decir el tráfico llega normalmente y es el router quien lo taggea.
Entonces configuro cada uno de los 13 ports de los ADSL "untagged" con su respectivo VLAN ID.
5.3-Configurando Linux para usar VLANs
Del lado del Linux tengo que levantar las VLAN. Para crear VLANs en Linux usamos el comando vconfig (paquete vlan)
Para hacerlo bien fácil, integramos la configuración de las VLANs a nuestro script firewall.sh.
Repasemos la parte en donde hacemos un loop por cada conexión y entre otras cosas damos de alta las ips, en este caso, en vez de configurar una interfaz normal, doy de alta una interface VLAN y luego la configuro.
  1. # por cada conexión  
  2. for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
  3.         #...  
  4.         # creamos la vlan con su ID respectivo  
  5.         vconfig add ${adsl_ifaces[n]%%.*} ${adsl_ifaces[n]##*.} &>/dev/null  
  6.         # configuro la ip   
  7.         ifconfig ${adsl_ifaces[n]} ${adsl_ips[n]} netmask 255.255.255.0 up  
  8.         #...  
  9. done  

6-Diagnóstico y debug

Hay varios lugares por donde mirar, y varios comandos que podemos usar para saber si el balanceo esta realmente funcionando o no.
Primero usamos ip route para ver cual es nuestro default gateway en el momento actual, deberíamos ver algo así como "nexthop via dev...." por cada una de las conexiones activas
ip route show
Para ver la tabla de una conexión en particular.
ip route show table adsl2
Para testear una conexión podemos por ejemplo hacer un ping a un google.com usando la ip de la conexión en cuestión.
ping -I 10.0.2.2 www.google.com
También podemos hacer tests de velocidad sobre una conexión, usando por ejemplo wget o curl.
wget --bind-address=10.0.2.2 http://somehost/somefile
curl --interface 10.0.2.2 http://somehost/somefile
Usando tcpdump o iftop podemos verificar que realmente los paquetes estén saliendo por la interfaz(y conexión) correspondiente.
tcpdump -n -i eth0.2
iftop -n -i eth0.2
Por ultimo si los script nos dan errores podemos ejecutarlos con "bash -x" para ver que comandos son los que están fallando
bash -x firewall.sh
bash -x multipath_watchdog.sh

7-Algunos puntos en contra

Puede pasar que los modems se cuelguen seguido. Esto pasa porque al usarlos de router, los modems tienen que hacer NAT y connection tracking ellos, y tienen una cantidad de memoria finita asignada para ello. Si usamos esta receta para colgar detrás cientos y cientos de máquinas puede pasar que llenemos esas tablas y los modems se cuelguen, en ese caso hay que conseguir o mejores modems(o usar un mikrotik por ejemplo como cuento más abajo), o codear una nueva solución que contemple pon, poff y la mar en coche.
Algunos Home banking muy particulares, usan la ip de origen como una variable más en su esquema de seguridad, el problema es que toman es ip en un servidor que autentica y luego nos hacen saltar a un segundo servidor, pero se nos exige mantener la misma ip de origen, cosa que no podemos garantizar.

8-Conclusión

La solución funciona muy bien, puedo contar varios ejemplos en donde está funcionando, exactamente igual o con diferencias, por ejemplo con el agregado de control de ancho de banda usando htb-gen, o con selección de proveedor o grupos lógicos de proveedores por cliente, o usar por ejemplo un mikrotik de 9 bocas en vez del switch VLAN, para poder tener una tabla de conntrack que se pueda estirar lo que haga falta.
También hay empreas que lo único que quieren es que no se corte jamas internet, sea porque usan VPNs con sistemas, o porque su negocio depende mucho del e-mail o de la web, y contratan dos proveedores o más.
Hay muchos escenarios, pero lo fundamental es que esta solución ha sido lo suficientemente flexible y cómoda para adaptarse a todos ellos, y es por eso que hoy la quise compartir con la cosi detta "comunidad”.
Enjoy!

Tomado de: http://bourneagainshell.blogspot.com.ar/2008/05/de-como-conectar-13-adsls-en-balanceo.html

No hay comentarios: