viernes, 7 de febrero de 2014

Inestabilidad de BGP a nivel mundial



Durante el principio de semana sufrimos de una inestabilidad de BGP a nivel mundial.

Los equipos que recibían por BGP toda la tabla mundial empezaron a cerrar las sesiones aleatoriamente con un mensaje de error, el resultado directo de esto es la pérdida conocimiento de las redes remotas, por lo que digamos mal y pronto que "no andaba internet".

El motivo del problema fue que un sistema autónomo (47868) se puso a jugar con BGP de una forma muy extraña y sin medir las consecuencias de esto.



Como todos sabemos. cualquier mala configuración de este protocolo puede ser penalizado y aislado o bien puede hacer un blackhole.

En este caso el tema fue mucho peor porque desencadenó un bug de muchos routers de la espina dorsal de internet.

Puntualmente esta gente del AS47868 (SuproNet) puso en práctica algún tipo de idea loca para su política de enrutamiento exterior.

Este AS "empeoró" sus rutas aumentando excesivamente el largo del atributo bien conocido AS_PATH.

Para los que no saben de BGP voy a dar una pequeña intro:


BGP es un protocolo de enrutamiento de gateway exterior (EGP) que usa un algoritmo de tipo vector camino para decidir el enrutamiento.

La métrica es compuesta, y depende de muchos atributos que son evaluados para conseguir la mejor ruta al destino.

Uno de esos atributos es el llamado AS_PATH, que es un vector (un arreglo unidimensional para los que saben de programación) en donde se van guardando todos los AS por donde pasó ese prefijo hasta llegar al router local.

[caption id="attachment_297" align="aligncenter" width="300" caption="Ejemplo de Atributo AS-PATH"]Ejemplo de Atributo AS-PATH[/caption]

Cada vez que el prefijo se pasa de un AS a otro, se agrega su número y por ende el largo de este vector aumenta.

Si no se consideran otros atributos que se evalúan antes, el camino con el AS_PATH más corto es el que se instala como ruta preferida.

Un router nos permite agregar nuestro propio AS muchas veces a este atributo (prepending) para aumentar este largo intencionalmente, y por ende podemos "empeorar" una ruta para que sea backup, ya que todos los routers eligirían la más corta por defecto.

Entonces tenemos publicada la ruta por dos lados, por uno en forma normal, y por el otro "prependeada" para que sea el último recurso.

Cuando la publicación normal esté andando todo llega por ahí, pero cuando se cae todo llega por la empeorada. Digamos que esto se hace para evitar el balanceo de carga por los dos enlaces.

La cuestión es que los genios del AS 47868 prependearon su AS 252 veces!!! y desataron la colgada de los equipos que mencioné anteriormente, los cuales seguro tienen sistemas operativos no actualizados.

Ahora vos te preguntas de quien es la culpa de esto...

Bueno, podemos verlo así:

  • El originador del problema no tenía la menor idea de lo que estaba haciendo y qué consecuencias podía tener.

  • El proveedor de ese AS no tenía una política de filtrado para evitar que esto se propague al mundo.

  • El resto del mundo (para mantener la estabilidad) usa sistemas operativos muy estables y probados, pero eso significa también que son viejos y que no implementan los nuevos features de los protocolos de enrutamiento. El tener un AS_PATH de 256 entradas es una modificación relativamente nueva al protocolo, y se propaga activando algunos campos especiales del paquete de actualización. Sumado a esto, tampoco teníán protección contra este evento.


Bien, ahora que todos somos culpables, quiero mencionar una frase que escribió un CCIE veterano que se llama Ivan Pepelnjak, y que me tomé la molestia de traducir:
Dos routers 3725 de "core": U$D 15.000.

Un switch Layer-3 para conectarlos: U$D 3.000.

Connectividad a dos proveedores de internet: U$D 3.000 por mes (estimado).

Provocar un fallo mundial en internet porque te ahorraste U$D 1000 en un curso de BGP o U$D 50 en un libro: No tiene precio.

En el próximo episodio les cuento como se puede evitar este nuevo tipo de ataque. Porque como siempre, el IOS tiene un feature que nos evita este problema. Pero la cuestión es la misma de siempre, nadie lo usaba (yo tampoco).

Actualización #1:


Pueden aprender como prevenir el problema en este post.

A pesar que yo voy a ir escribiendo acerca de este protocolo, de todas formas recomiendo imperiosamente leer la bibliia que escribió Sam Halabi: Arquitectura de Enrutamiento En Internet - 2b: Edicion (Spanish Edition).

No hay excusa para no tenerla, y para mejor está totalmente traducida al español.

Script PERL para consultar prefijos recibidos desde un peer de BGP



Hace un tiempo que estoy buscando de armar un panel de monitoreo personalizado, y como toda mañana de viernes me puse a despuntar el vicio de programar un rato en PERL.

Estuve jugando con el módulo Net::Telnet y al final terminé haciendo un script que se conecta contra un router para extraer información.

No es mi intención reinventar la rueda, sencillamente lo comparto para ahorrarle tiempo a alguien que pueda estar necesitando esto.

Seguramente existen miles de scripts mucho más completos que manejan más cosas, pero en este caso es sencillamente por una satisfacción personal de programar un rato.

tnet.pl

#!/usr//bin/perl
#Hecho por Ariel Weher @20110701
 
use Net::Telnet ();
 
#En este caso los datos del host, usuario y password
#los dejo grabados en el script.
#Verificar que los permisos del archivo no den lectura a todos.
#
my $username = 'usuario';
my $password = 'supersecreto';
my $host = '192.168.0.1';
 
 
# Me conecto y ajusto algunos parámetros
my $t = new Net::Telnet (Timeout => 15, Prompt => '/[%#>]$/');
$t->open($host);
$t->login($username, $password);
$t->max_buffer_length("50000000");
$t->timeout("120");
 
# Con esto digo que la consola haga scroll sin pedir
# de apretar la barra espaciadora para continuar...
$t->cmd("terminal len 0");
 
# Ahora mando el comando que quiero capturar:
my @lineas = $t->cmd("show ip route");
 
# Desconecto
$t->close;
 
# Muestro los resultados
print "\n";
print @lineas;
print "\n";
 
# Salimos
exit 0;

Ahora la aplicación práctica:

Modifiqué el script para que me de una salida que informe la cantidad de prefijos recibidos por un neighbor de BGP.

Este script lo corre MRTG y luego dibuja una bonita gráfica donde nos quedan las fluctuaciones de las cantidades de rutas recibidas.

rutasrecibidas.pl

#!/usr//bin/perl
# Hecho por Ariel Weher @20110701
# Uso: rutasrecibidas.pl {ip_del_neighbor_bgp}
#
# No olvidar darle permisos adecuados: (chmod 750 rutasrecibidas.pl)
 
use Net::Telnet ();
 
my $username = 'usuariodelrouterqueusa-AAA-new-model-o-login-local';
my $password = 'super-password_secreto';
my $host = '192.168.0.1';
 
#Chequeo si me pasaron una IP como argumento...
if ($ARGV[0] =~ /^\s?(0?[0-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.(0?[0-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.(0?[0-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.(0?[0-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\s?$/){
        $neighbor = $ARGV[0];
        chomp $neighbor;
} else {
        # MRTG espera dos ceros como resultado de un query inválido
        die "0\n0";
}
 
$t = new Net::Telnet (Timeout => 15, Prompt => '/[%#>]$/');
$t->open($host);
$t->login($username, $password);
$t->max_buffer_length("50000000");
$t->timeout("120");
$t->cmd("terminal len 0");
my @linea = $t->cmd("show ip bgp sum | include $neighbor");
my $dato = $linea[0];
my @columnas = split(" ", $dato);
$salida = $columnas[9];
chomp $salida;
if ($salida =~ /\d\d*/){
 print "$salida\n$salida";
} else {
 print "0\n0";
}
exit 0;

Ahora configuramos una entrada en nuestro mrtg.cfg:
Title[bgp-pref-192-168-0-1]: Rutas recibidas por BGP
PageTop[bgp-pref-192-168-0-1]: Cantidad de prefijos recibidos por BGP desde 192.168.0.1
Target[bgp-pref-192-168-0-1]: `/path/al/script/rutasrecibidas.pl 192.168.0.1`
MaxBytes[bgp-pref-192-168-0-1]: 500000
ShortLegend[bgp-pref-192-168-0-1]: Prefijos IP
YLegend[bgp-pref-192-168-0-1]: Prefijos IP
Options[bgp-pref-192-168-0-1]: integer, nopercent, gauge, noinfo
kMG[bgp-pref-192-168-0-1]: ,,

Les dejo un ejemplo de como MRTG me dibuja los datos extraídos del router.



Espero que les sirva este sencillo ejemplo. Seguro hay algunos mejores pero a mí me gustan las cosas hechas en casa.

Implementando RPKI (Parte 1)



Volvemos a actualizar el blog con un tema por demás de actual: Resource Public Key Infrastructure.

La idea básica del problema es que si se dan algunas condiciones, cualquier mortal con acceso a un router que usa BGP puede publicar las redes de cualquier otra institución como si fueran propias.

Hubo muchos casos, quizás el más famoso sea el de la Pakistan Telekom que se robó los prefijos de Youtube, haciendo que gran parte del tráfico mundial de Youtube se dirija hasta esta telco (y se descarte).

RPKI nos puede ayudar a que estos incidentes no vuelvan a ocurrir, y a vuelo de pájaro vamos a explicar como funciona:
  1. Cualquier entidad que posee rangos IP(v4|v6) genera ante la entidad que se los asignó un certificado y uno o más ROA (Route Origination Autorization), que son básicamente una autorización en donde describe qué prefijos va a asignar y hacia qué sistema autónomo.
  2. La información de los anuncios permitidos de cada sistema autónomo se procesa y queda disponible para que se pueda consultar desde cualquier lugar.
  3. En nuestra empresa instalamos una aplicación de RIPE NCC que descarga via RSYNC las autorizaciones y arma un cache local con toda la información.
  4. Nuestros routers se conectarán al cache mediante el protocolo RTR y podrán obtener la información para chequear la validez de los prefijos de BGP que se reciben desde los upstream providers, generando rutas válidas (coinciden con los ROA), inválidas (no coinciden con los ROA) o desconocidas (no hay un ROA para esas rutas).


Esta información se puede aprovechar al momento de armar las políticas de ruteo (route-maps), como por ejemplo:

route-map internet-in permit 10
 match rpki valid
 set local-preference 200
route-map internet-in permit 20
 match rpki not-found
 set local-preference 50
route-map internet-in deny 30
 match rpki invalid

En el ejemplo anterior, damos mayor preferencia a las rutas válidas, menor preferencias a las indeterminadas y descartamos las inválidas.

En la siguiente entrega vamos a mostrar la implementación de estos servicios.

Espero les haya servido.




RPKI Parte 0 (para tomadores de decisiones)



Señor Gerente:

En este texto intentaré explicar para qué sirve RPKI tratando de no entrar en detalles técnicos.

¿Qué es RPKI? (en tres oraciones)

  • Resource Public Key Infrastructure es un sistema en donde cada empresa va a declarar a una base de datos mundial cómo y a quién anuncia sus Direcciones IP sin costo alguno.
  • Luego, los routers del mundo podrán consultar esa base de datos para verificar que la información que reciben coincide con las que la empresa declara, pudiendo filtrar redes que sean 'robadas' por atacantes malintencionados.
  • Esto se complementa con un fuerte sistema criptográfico de firmado, que garantiza la integridad, validez y veracidad de la información obtenida.

¿Qué hago para comenzar a implementar RPKI?


En este momento de la historia todas las entidades que poseen recursos IP propios deben declarar y firmar digitalmente la información acerca de las redes que publican a internet. Técnicamente esto se denomina "Firmar un ROA" (Autorización de Originación de Rutas).

Esto se hace desde el sitio web de su RIR, en cuestión de minutos.

Luego, se deben actualizar los sistemas operativos de los routers de forma tal que puedan consultar la información de todos los ROA de las organizaciones.
Pasos para la implementación de RPKI

Ahora algunos detalles más, quizás un poco más técnicos.


Una dirección IP es a un equipo lo que una chapa patente a un auto. No se puede circular por la red sin tener una de ellas.

Generalmente las organizaciones toman Direcciones IP prestadas de su proveedor de acceso a Internet, pero en los casos en donde las organizaciones tienen varios proveedores o bien prestan servicio (son ISP) deben "comprar" su propio rango de direcciones.

Usted debe saber si su empresa paga un cargo anual por "Direcciones IP" a alguna de las entidades presentadas en el siguiente diagrama, de acuerdo a su localización geográfica.
Registros Regionales de Internet según la zona geográfica
Para mi caso, dado que estoy en Argentina, los recursos se compran al RIR llamado LACNIC.

Ahora bien, una vez que a su empresa se le asignan los rangos de direcciones y se concreta el pago, su personal técnico debe Publicar o Anunciar al resto de los routers del mundo el rango de Direcciones IP propias, para que el resto del mundo pueda enviar información hacia las redes de su empresa.

En este punto es donde debemos concentrarnos y lo remarco:
Alguien (idealmente su personal técnico) debe anunciar al mundo la existencia del nuevo rango de Direcciones IP asignadas a su empresa usando un protocolo de ruteo llamado BGP.

La realidad es que por como están hechos el protocolo BGP, ya sea en forma malitencionada o no ese alguien puede ser cualquier empresa o persona que cuente con la infraestructura necesaria. Se necesita:
  • Un router
  • Un enlace a internet
  • Una conexión de BGP con un proveedor de internet.
Estos tres requerimientos no son difíciles de conseguir y tampoco son costosos.

Esto quiere decir que hoy en día cualquier entidad puede anunciar al mundo los rangos de otra entidad. Por ejemplo:

Hace un par de años hubo un incidente en donde por error una Telco de Pakistán anunció al mundo las redes del portal Youtube. La consecuencia de esto es que gran parte de los millones de personas que pedían su navegador de entrar este sitio eran redirigidos hacia Pakistán

Imaginemos un caso que hipotéticamente podría pasar:
  1. Un atacante crea un clon del sitio web de su banco de confianza.
  2. Anuncia como propias las direcciones IP del banco.
  3. Los clientes van a caer en los servidores del atacante cuando quieran entrar al sitio del banco.
  4. El atacante roba las contraseñas del home banking de los clientes que caigan en esta trampa.
  5. Luego, el atacante se hace rico al retirar dinero de esas cuentas.
Espero le sirva el documento.
Por favor no deje de hacer los comentarios que crea necesarios.