Bastionado, seguridad en sistemas: Conexión de Back Up (FailOver) pre { background:#eeeeee; border:1px solid #A6B0BF; font-size:120%; line-height:100%; overflow:auto; padding:10px; color:#000000 } pre:hover { border:1px solid #efefef; } code { font-size:120%; text-align:left; margin:0;padding:0; color: #000000;} .clear { clear:both; overflow:hidden; }

Bienvenido al blog

Bienvenidos al blog de seguridad en sistemas

lunes, 4 de abril de 2011

Conexión de Back Up (FailOver)

Cada vez es más común que en las empresas pequeñas y medianas se disponga de dos conexiones a Internet: la primaria y la de repuesto o back up. La primaria corresponde a una línea con un gran ancho de banda mientras que la secundaria, de un ISP distinto a la primaria, es una línea de repuesto con un ancho de banda inferior, cuya única finalidad es la de ofrecer una conexión a Internet en caso de que la primaria falle.

Para optar a un entorno de este tipo es necesario disponer de un dispositivo que permita transmitir el tráfico por la primaria, y que en caso de fallo, redireccione el tráfico por la secundaria. Ese dispositivo puede tratarse de un simple host Linux con el flag "Forwarding" activado y con el enmascaramiento (Masquerading) habilitado al tráfico saliente de las dos interfaces conectadas a las ISPs. Para esta entrada eth0 será la primaria y eth1 la secundaria.

Junto con la configuración descrita con anterioridad, será necesario ejecutar tres ordenes para que el núcleo gestione la ruta por la cual se retransmitirán los datos. Dichas ordenes son las siguientes:
# route add default gw GW_1 dev eth0
# route add default gw GW_2 dev eth1
# echo "30" > /proc/sys/net/ipv4/route/gc_timeout

Por desgracia, esta configuración no funciona del todo bien, ya que existen dos condiciones en las que he detectado que su funcionamiento no es el esperado:
  1. Cuando el problema es de un router del ISP intermedio, es decir, no es directamente el router que tenemos conectado a la interfaz del servidor Linux 
  2. Cuando se intenta restablecer la ruta principal, la cual había sido descartada por el router. 
Por ello me creé un script, de nombre failover.sh, que permite gestionar las rutas. No es una solución bonita, optima, pero si viable para cuando la opción descrita con anterioridad no os funcione. El script se debe añadir al crontab para que se ejecute cada 5 minutos. Los pasos que realiza son los siguientes:

1º) Identifica y registra la puerta de enlace de ambas interfaces. Elimina la ruta secundaria dejando solo la primaria. Esto lo hace solo una vez. 

2º) Cada vez que se ejecuta comprueba si tiene acceso a Internet mediante un ping a google y en caso de que falle, lo reintenta con la IP 8.8.8.8. Si no llega, lo anota en un fichero. Dicho proceso se repite para cada ejecución tantas veces como se le indique en la variable INTENTOS de script. El objetivo de esto es evitar falsos positivos.  

3º) Si pasado esos INTENTOS sigue sin recibir respuesta, cambia la ruta por la secundaria.

4º) Al pasar a la secundaria, comprobará cada "RESTAURAR" veces si la secundaria funciona. RESTAURAR es una variable cuyo valor en el script es 6. Mientras este activada la interfaz de back up el script se ejecutara marcando las veces que se ha ejecutado en estado de back up, al llegar al número indicado en RESTAURAR comprobara si la ruta primaria a vuelto a funcionar.

5º) Para comprobarlo lo que hace es restaurar la ruta primaria, volverá hacer los pings anteriores, si funciona dejará la ruta principal y eliminará la secundaria volviendo al estado del punto 2. Si al hacer los pings no llega, vuelve a dejar la secundaria como ruta por defecto y se volverá a repetir el proceso descrito en el punto 4. 

Para probarlo he creado una máquina virtual Linux empleando para ello Virtual Box. A la máquina le he asignado dos interfaces, la primera configurada como NAT y la secundaria como adaptador puente. A la primera interfaz (eth0), Virtual Box le conceda una interfaz del rango 10.0.0.0 puesto que "natea", mientras que a la segunda (eth1) es el router Linksys conectado a mi equipo físico con dhcpd quien le concede una IP del rango 192.168.0.0. Veámoslo:
# dhclient eth0
# dhclient eth1
# ifconfig

eth0    Link encap:Ethernet  HWaddr 08:00:27:58:XX:XX
          inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1180 (1.1 KB)  TX bytes:684 (684.0 B)
eth1    Link encap:Ethernet  HWaddr 08:00:27:c0:XX:XX
          inet addr:192.168.2.103  Bcast:192.168.2.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5 errors:0 dropped:0 overruns:0 frame:0
          TX packets:2 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1360 (1.3 KB)  TX bytes:684 (684.0 B)
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
Como vemos, la interfaz primaria eth0 tiene como puerta de enlace 10.0.2.2 y la secundaria eth1 192.168.2.1. A continuación veremos el funcionamiento del script "failover.sh. Éste será ejecutado a mano, aunque recordar que lo suyo es que este en el crontab cada 5 minutos ejecutándose (*/5 * * * /usr/local/failover/failover.sh):
# ./failover.sh
[OK] 2011-04-03_21:04 -> www.google.com
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         10.0.2.2        0.0.0.0         UG    0      0        0 eth0
# cat config
10.0.2.2
192.168.2.1
Como vemos ha almacenado las puertas de enlace de ambas interfaces, sabe cual es la primaria y secundaria. A su vez a eliminado la ruta secundaria dejando únicamente la ruta de la primaria. Para ver el funcionamiento del script vamos a filtrar todo el tráfico de entrada a la interfaz eth0 simulando una caída de la conexión a Internet:
# /sbin/iptables -A INPUT -i eth0 -j DROP
# ping -c1 google.es
PING google.es (209.85.147.99) 56(84) bytes of data.
--- google.es ping statistics ---
1 packets transmitted, 0 received, 100% packet loss, time 0ms
Ejecutemos el script tantas veces como indicado en su variable INTENTOS, la cual tiene el valor 3, y por tanto, el script deberá ser ejecutado en tres ocasiones para pasar a la línea de Back Up:
# ./failover.sh
# tail -1 failover.log

[ERROR] 2011-04-03_20:35 -> Fallo numero 1
# ./failover.sh
# tail -1 failover.log
[ERROR] 2011-04-03_20:40 -> Fallo numero 2
# ./failover.sh
# tail -2 failover.log

[ERROR] 2011-04-03_20:45 -> BACKUP ACTIVADO
[EVENTO] 2011-04-03_20:45
# cat backup
1
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
# ping google.es
PING google.es (209.85.147.106) 56(84) bytes of data.
64 bytes from bru01m01-in-f106.1e100.net (209.85.147.106): icmp_seq=1 ttl=53 time=78.8 ms
64 bytes from bru01m01-in-f106.1e100.net (209.85.147.106): icmp_seq=2 ttl=53 time=79.5 ms
...
Como vemos, una vez que el script se ha ejecutado "INTENTOS" veces, elimina la ruta primaria y activar la secundaria. De esta forma ya se tendrá acceso a Internet por la secundaria encontrandose el script en modo backup (valor del fichero backup a 1).

En modo back up el script, cada REINTENTAR veces (variable del script cuyo valor es 6), cambiará la puerta de enlace por la primaria y comprobará si tiene acceso a Internet. Siguiendo el ejemplo anterior donde el tráfico de la interfaz eth0 está bloqueado, al ejecutar 6 veces el script intentará salir por la ruta de eth0, fallará y volverá a usar la ruta de eth1:
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# cat restaurar

Esperar
Esperar
Esperar
Esperar
Esperar
Esperar
# ./failover.sh
# route -n

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.2.0     0.0.0.0         255.255.255.0   U     0      0        0 eth1
10.0.2.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.2.1     0.0.0.0         UG    0      0        0 eth1
Vamos a repetir el mismo paso que el anterior, pero esta vez eliminaremos la regla de Iptables, permitiendo que la interfaz eth0 vuelva a tener acceso a Internet:
# iptables -F
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# ./failover.sh
# cat restaurar

Esperar
Esperar
Esperar
Esperar
Esperar
Esperar
# ./failover.sh
# route -n

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
10.0.2.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
# cat backup
0
Como vemos el sistema ha sido capaz de volver a asignar como ruta de salida la de eth0 restaurando el sistema.  Ya para finalizar os dejo el script failover.sh, cualquier comentario o mejora será bienvenida.

Espero que os sea de utilidad. Nos vemos en la próxima entrada, que si no ocurre nada raro será de DNS.

PD: sí, sí ya me estoy pegando con blogger para que se vea todo el código más claro, pero por algún motivo el muy $!@# muestra caracteres al publicar que no se ven en modo visión... 

No hay comentarios:

Publicar un comentario