- Mensajes
- 5,998
Introducción
Hoy vamos a hablar de un tema la mar de interesante, si bien no es demasiado usado a nivel doméstico. Se trata del balanceo de carga con failover. Básicamente cómo aprovechar tu conexión, cuando tienes dos líneas de internet.Propósito
El propósito de este manual viene de una nueva necesidad: trabajo de normal desde casa y llevaba tiempo con el runrun de poner una segunda conexión a internet. Normalmente, cuando fallaba mi querido Pepephone (todas fallan alguna vez), tiraba de la conexión móvil. Pero, dado que vivo en una zona con escasa cobertura, cumplir con mi trabajo se me hacía complicado usando este tipo de conexión. Esto, unido a que derivado de la pandemia la situación en casa ha cambiado y ya no soy yo sólo el que trabaja en remoto, me hizo plantearme que no sería nada descabellado tener una segunda conexión a internet (dos fibras) por si, $deity no lo quiera, mi querido Pepephone me dejaba tirado en algún momento. Estudiadas las ofertas y haciendo números, opté por contratar con o2, de la cual ya tenía buenas referencias por un par de instalaciones en casa de familiares. Además de esto, en mi casa ya existía una toma de fibra de telefónica, que Pepephone respetó cuando instaló la suya, así que supuse que iba a ser coser y cantar. Dicho y hecho, el móvil costó un poco más, pero la fibra estaba instalada al día siguiente de pedirla. Y ahora viene cuando pokoyo se pregunta, ¿qué coj_nes hago yo con dos líneas de 600, cómo las aprovecho? Porque, si ya me parecía burra la de 300 simétricos, ahora con dos de 600, habrá que hacer algo para aprovecharlas, ¿no? (al final me lío la manta a la cabeza y cableo el bloque a los vecinos, sino al tiempo). Pues aquí es donde entra en juego el balanceo de carga y el failoverUn poco de teoría
Empecemos por lo más sencillo, el failover: básicamente se trata de seleccionar una ruta alternativa de salida a internet, cuando la ruta principal falla. En mikoritk, si vamos al apartado IP -> Routes, veremos una lista de direcciones con una entrada especial que apunta a la dirección 0.0.0.0/0. Esta ruta es la ruta por defecto. Básicamente esa tabla representa una lista de caminos a tomar para resolver las distintas peticiones que llegan al router. Si la dirección ip que solicitamos no se puede resolver localmente, se encarrila por esa ruta por defecto, pidiendo a lo que sea que tengas por encima que te lleve hasta ello. Dichas rutas tienen distancias, que no es más que un orden por el cual vamos a consultarlas. En un router doméstico, las rutas locales (LAN) tienen distancia 0, mientras que la ruta por defecto, normalmente creada de forma dinámica por algun cliente dhcp o pppoe, tiene distancia 1. Eso hace que cuando pedimos una dirección local no nos mande a internet en busca de ella, sino que el propio router la resuelva internamente.En mikrotik, montar un failover es la cosa más tonta del mundo: basta con añadir una segunda ruta (bien manualmente, bien automáticamente) con una distancia superior a la ruta por defecto. Así, si usamos un pincho 3G conectado al router por USB, veremos que el cliente dhcp que levanta el router sobre la interfaz LTE crea una ruta con distancia 2. Eso quieres decir que, mientras esté viva la ruta por defecto con distacia 1, no se usará nunca la ruta "alternativa", mientras que si muere la ruta por defecto con distancia = 1, se empezará a usar la siguiente disponible, en este caso la de la interfaz LTE con distancia = 2. Tan chorra como eso, no tiene más. Más adelante podréis ver esto en fotos, y cómo se comporta.
Ahora lo interesante, el balanceo de carga: entendemos por balanceo la distribución del tráfico entre dos o más interfaces de salida WAN. Esta distribución se puede hacer de muchas formas, pero este manual se va a centrar en la que creo es la forma más eficiente que tiene mikrotik de hacerlo, el balanceo de carga PCC (Per Connection Clasiffier). Tenéis otros dos métodos que podéis estuidar: uno muy facilito de entender (ECMP o Equal Cost Multi Path) y otro algo más complejo, aunque también interesante (NTH o de enésimo paquete). No obstante, nos vamos a centrar en PCC. Ahora bién, ¿cómo divide el tráfico PCC? Pues lo hace dividiendo la conexión por flujos o streams, de tal manera que, una vez establecida una conexión, esta permanezca en el mismo canuto de salida para todos los paquetes relacionados con ella. Esa clasificación por tipo de conexión se hace usando un algoritmo de hashing y un selector, para seleccionar (valga la rebuznancia) sobre qué aplicamos el hashing. El selector tiene varias opciones, pero usaremos "both-addresses" para clasificar el tráfico, de tal menera que la función hash trabajará con las direcciones de origen y destino que tiene en la cabecera de los paquetes IP y, una vez aplicada la función de hashing, tendremos un chorizo de 32 bits. Ese chorizo lo dividimos entre el número de WAN's que tengamos, y el resultado de la operación tendrá un resto. Ese resto será el indicador que usaremos para marcar el tráfico e indicarle por qué canuto tirar.
Por ejemplo, para una conexión con 2 WAN's y clasificación por "both-addresses" tendremos como divisor el número 2 y, como posibles resultados para el resto de la operación de división, el 0 y 1. Si el resto de la división es 0, marcaremos ese paquete para que tire por un canuto, y si es 1, por el otro. Esto se expresa en la opción correspondiente como PCC = both-addresses:2/0 para la primera conexión y PCC = both-addresses:2/1 para la segunda. (dividimos por dos las opciones de resto son 0 o 1). Para una conexión con 3 WANs, sería igual pero tendríamos tres posibles restos para dicha división, así que tendríamos una definición de both-addresses:3/0 para la primera conexión y PCC = both-addresses:3/1 para la segunda y PCC = both-addresses:3/2 para la tercera... y así sucesivamente, con todas las interfaces WAN que tengáis.
Manos a la obra
Doy por hecho que todos sabemos configurar una conexión en automático con el que sea nuestro operador. En mi caso tengo ether1 y ether2 conectados a o2 y Pepephone, respectivamente (acordaos de sacar ambas interfaces del bridge lan y de meter ambas en la lista WAN para que les aplique la regla general de masquerade). O2 trabaja con PPPoE para obtener IP pública, mientras que Pepephone trabaja con DHCP. Levantados sendos clientes en dichas interfaces, tendremos una tabla de rutas con dos entradas 0.0.0.0/0, una de ellas en azul, indicando que dicha entrada no está en uso. Lo primero que vamos a editar es uno de los dos clientes, bien el dhpc bien el pppoe, para indicarles que vamos a dar preferencia a una de las dos rutas, quedando la otra como failover. En mi caso, he decidido que Pepehone tiene preferencia y se queda con distancia = 1 en la ruta, mientras que el cliente PPPoE va a tener distancia = 2. Ya está, ya hemos acabado con el failover. Si no os lo creéis, abrid la consola, tirad un ping a google.com y, en mitad de la fiesta, tirad de uno de los dos cables, bien ether1 o ether2. Si tiráis de ether2, mi conexión preferida, veréis como ether1 entra en acción enseguida, y práctiamente no perdéis más que uno o dos paquetes. Dicha entrada con peso 2 ahora estará en negro, en lugar de en azúl. Si vuelve en sí la preferida, toma preferencia sobre la otra y vuelve a enrutar el tráfico por ella, pasando a estar en azul la que tiene distancia = 2. ¿fácil, no? Siguiente paso: mangleMangle es la herramienta que nos proporciona Mikrotik para el marcado de paquetes. La usaremos para clasificar y marcar el tráfico, de tal manera que lo podamos lanzar a una WAN u otra, según nos convenga. Lo primero que tenemos que saber es que mangle es incompatible con fasttrack. Ohh... qué pena. Así que, si queréis usar mangle, no queda otra que desprendernos de nuestra querida regla de fasttrack la cual nos hace volar en mikrotik. Pero, ¿a quien le importa? ¡vamos a tener dos líneas de 600 para usar ala vez!, por velocidad no va a ser. Una vez localizada la regla de fasttrack en ip -> firewall -> filter, la deshabilitamos y reiniciamos el equipo. Al hacerlo, veremos ques otras reglas de conteo de paquetes que aparecían en la parte superior del firewall, así como en el apartado mangle, desaparecen. No hay problema, son reglas dinámicas que se crean solitas al habilitar fasttrack. Si mañana queremos volver a usarlo, con habilitarlo y dar un reinicio al equipo, se crearán solas de nuevo. Una vez localizada la pestaña de mangle, al lío.
Lo primero que vamos a tratar son las excepciones. Hay veces en las que, por lo que quiera que sea, no nos interesa aplicar el balanceo sobre todo el tráfico, y necesitamos una regla para excepcionarlo. En mi caso, ese tráfico se llama VoIP, y lo tengo que excepcionar porque lleva su propia ruta dinámica (RIP) para telefónica movistar, y por tanto, idem para o2. La priemra regla que crearemos será la excepción de dicho tráfico. La regla dirá, si es tráfico de voz, acéptalo y pásalo al firewall, que es lo que se ejecuta justo después de mangle. En mi caso, dicha regla tiene este formato:
Código:
/ip firewall mangle
add action=accept chain=prerouting comment="bypass voip" dst-address=10.0.0.0/8 \
in-interface=bridge
A continuación, marcaremos las conexiones. Para ello, trabajaremos simpre sobre el chain de prerouting, y tenemos básicamente dos tipos de tráfico que marcar: el que viene desde fuera con destino dentro, y el que viene de la LAN con destino internet. Y os preguntaréis, ¿por qué narices tengo que marcar lo que viene de fuera, si a mi el balanceo me interesa sobre todo de salida: pues porque sino cabría la posibilidad de que respondieras a una conexión entrante por una IP pública que no fuera la que va como destino en la cabecera del paquete IP. El otro extremo diría, "Pero si yo he pedido hablar con Pepe, por qué me responde Juan" y ahí se acabó la converasación. Así que necestamos marcar ambos tipos de tráfico. Al lío:
Código:
add action=mark-connection chain=prerouting comment="mark connections" \
connection-mark=no-mark in-interface=internet-pepephone \
new-connection-mark=pepephone_conn passthrough=yes
add action=mark-connection chain=prerouting connection-mark=no-mark \
in-interface=internet-o2 new-connection-mark=o2_conn passthrough=yes
add action=mark-connection chain=prerouting connection-mark=no-mark \
dst-address-type=!local in-interface=bridge new-connection-mark=\
pepephone_conn passthrough=yes per-connection-classifier=both-addresses:2/0
add action=mark-connection chain=prerouting connection-mark=no-mark \
dst-address-type=!local in-interface=bridge new-connection-mark=o2_conn \
passthrough=yes per-connection-classifier=both-addresses:2/1
Marcadas las conexiones, lo que nos queda es, es el empujoncito final: para dichas conexiones marcadas, aplicar una regla de routeo. Para ello, simplemente analizaremos las marcas de conexión y, a las que vengan con "pepephone_conn", las mandamos a la ruta que trabaje con la marca de routing "to_pepephone", y a la que venga con "o2_conn", la mandamos a otra ruta que trabaje sobre la marca de routing "to_o2". Cuando creamos marcas de routing, en verdad lo que estamos haciendo son nuevas tablas de routeo además de la tabla de routeo principal "main" (toda conexión no marcada con una marca de routing, va por defecto a la tabla "main"). Al igual que en el punto anterior, tendremos dos casuísiticas, esta vez relacionadas con distintos "chains": dos reglas para prerouting y dos para output. Las dos de prerouting se encargarán del tráfico que viene de la LAN ya clasificado. Las dos de output atenderán el tráfico que sale del propio router. Las reglas, serían estas:
Código:
add action=mark-routing chain=prerouting comment="mark routing" \
connection-mark=pepephone_conn in-interface=bridge new-routing-mark=\
to_pepephone passthrough=no
add action=mark-routing chain=prerouting connection-mark=o2_conn in-interface=\
bridge new-routing-mark=to_o2 passthrough=no
add action=mark-routing chain=output connection-mark=pepephone_conn \
new-routing-mark=to_pepephone passthrough=no
add action=mark-routing chain=output connection-mark=o2_conn new-routing-mark=\
to_o2 passthrough=no
Por último, y ya que estamos usando mangle y que nuestro operador nos define una prioridad para los servicios, marcamos dicha prioridad. Esto no es obligatorio, pero como o2 lo hace en su definición de interfaces, pues nosotros lo vamos a hacer igual. En mi caso, sólo internet y tfno. Si tuvierais tv, tres cuartos de lo mismo:
Código:
add action=set-priority chain=postrouting comment="vlan priority" new-priority=1 \
out-interface=internet-o2 passthrough=no
add action=set-priority chain=postrouting new-priority=4 out-interface=\
vlan-voip-o2 passthrough=no
Con esto y un bizcocho, hemos terminado con el mangle. Pasamos a configurar las rutas. Para las rutas, lo único que tenemos que hacer es definir dos nuevas rutas, específicas para las marcas de routeo que hemos hecho. Esas rutas serán las que de verdad trabajen, mientras ambas conexiones estén vivas y balanceando. Las rutas por defecto se quedarán de backup, para el tráfico sin marcar o para cuando algo falle en nuestra configuración. Pasamos a crear las dos rutas nuevas, una para el tráfico marcado como "to_pepephone" y otra para el tráfico marcado como "to_o2", ambas con una sonda de tipo "ping" para comprobar que siguen vivas:
Código:
/ip route
add check-gateway=ping comment=pp-load-balanced distance=1 gateway=212.231.184.1 \
routing-mark=to_pepephone
add check-gateway=ping comment=o2-load-balanced distance=1 gateway=internet-o2 \
routing-mark=to_o2
Llegados a este punto ya tenemos todo el tinglado montado y funcionando. Si lo hemos hecho bien, en la tabla de rutas habrá cuatro entradas (si tenéis dos WANs) con la 0.0.0.0/0 como dirección de destino y el tráfico empezará a fluir balanceado. Y la pregunta creo que es obvia: "claro cachondo, pero si tenemos direcciones IP dinámicas en la mayoría de los casos, qué pasa cuando la IP cambia, ¿eh?" Pues habéis intuido bien, el tinglado se nos va al garete. La ruta dinámica sobrevibe, puesto que como su propio nombre indica es dinámica, y cambiará cuando el cliente dhcp obtenga una nueva dirección IP, así como su correspondiente gateway. Pero la que hemos dado de alta a mano se nos fastidia, así que necesitamos corregir eso. Para hacerlo, lo que vamos a montar es un script que añadiremos al cliente DHCP, tal que sea capaz de modificar esa que hemos dado de alta a mano, automáticamente. El script está sacado de la wiki de mikrotik, y adaptado a mis necesidades.
Lo primero que tenemos que hacer es etiquetar la ruta problemática, la de pepehone, con un comentario cualquiera, en mi caso "pp-load-balanced", tal que seamos capaces de leerla en el script. Una vez hecho, iremos a IP -> dhcp-client y editaremos el cliente dhcp asocidado a nuestra conexión DHCP, en mi caso "internet-pepephone", y le meteremos el siguiente script en la pestaña "Advanced"
Código:
{
:local rmark "to_pepephone"
:local rcomment "pp-load-balanced"
:local rcount [/ip route print count-only where comment=$rcomment]
:if ($bound=1) do={
:if ($rcount = 0) do={
/ip route add gateway=$"gateway-address" comment=$rcomment routing-mark=$rmark check-gateway=ping
} else={
:if ($rcount = 1) do={
:local test [/ip route find where comment=$rcomment]
:if ([/ip route get $test gateway] != $"gateway-address") do={
/ip route set $test gateway=$"gateway-address"
}
} else={
:error "Multiple routes found with the same comment!"
}
}
} else={
/ip route remove [find comment=$rcomment]
}
}
Si el cliente dhcp falla a la hora de obtener una dirección IP (ejemplo cuando se nos corta internet por un fallo del operador y el cliente dhcp se nos va a la mierda), borramos la ruta estática (ya no tanto) que lleva el tráfico a ese operador. Al borrarse de la tabla de rutas, la regla de mangle que etiqueta el tráfico de entrada por esa interfaz deja de funcionar y, aunque la de salida del PCC sigue funcionando, al no encontrar una ruta específica para esa etiqueta en la tabla de rutas, lo tirará por la tabla "main", para la que sea la ruta que esté actuando por defecto. Resultado: ni nos enteramos de que se nos ha caido internet, porque todo sigue funcionando.
Puede darse el caso de que el cliente DHCP no falle, aún, porque el lease time aguante hasta que le toque renovar la conexión DHCP, pero que el gateway no responda: para ese caso está el "check-gateway=ping" en la ruta, el cual comprobará cada 10s que tu gateway sigue vivo. A los dos timeouts, dará de baja esa ruta y la marcará como no disponible.
Conclusión
¿Merece la pena? Pues sinceramente, creo que no. Dado que las velocidades que manejamos hoy en día en casa son tan absurdamente altas, no creo que aproveche jamás el beneficio que me brinda el balanceo de carga con dos conexiones simétricas de 600. Pero es una cosa que tenía pendiente probar y... ya que estamos, manual al canto. Eso, y que me jode mucho tener un chisme enchufado haciendo nada, así que o2, te toca pringar también. No obstante, creo que puede ser una guía muy útil para quien tenga la posibilidad de montar un par de líneas o tres y distribuir el servicio entre muchos, como por ejemplo, una comunidad de vecinos que se lleve bien.Con esto y otro bizcocho... balanceo de carga PCC con failover; que Uds lo disfruten.
Saludos!