Categories
General In detail

Algunas cosas de AWS que quizás no conoces

Aunque los competidores están empezando a coger carrerilla, decir hoy en día que Amazon Web Services es el proveedor de cloud más utilizado, con más funcionalidades y servicios interesantes es como decir que el cielo es azul. AWS se ha transformado en un monstruo en el que probablemente casi nadie puede estar al día de todos los cambios y funcionalidades en detalle que va adoptando. En este post vamos a ver algunas de las funcionalidades y características de AWS que probablemente si no has trabajado un poco con AWS no conozcas.
post

ALIAS

En route 53 podemos crear registros DNS con ALIAS, no penséis que Amazon ha reinventado el protocolo DNS ni nada por el estilo. Ésta característica ha salido por un lado porque al apex de un dominio (raíz), no se le puede asignar un registro CNAME y esto es un problema en un entorno cloud dónde las IPs no son fijas y todo puede cambiar. A parte también interesa tener registros DNS que apunten a componentes de AWS (como por ejemplo un ELB) y que en caso de que cambie la IP del componente en cuestión el registro sea actualizado.
Al crear un registro DNS , podemos configurar que sea de tipo ALIAS y el componente al que apunta, ésto nos permite apuntar a componentes con IP cambiante y a parte poder configurar un apex de un dominio como un registro que aunque sea de tipo A, es dinámico.

EC2 Metadata

Aunque probablemente todos los que hemos trasteado un poco con EC2 vemos que mágicamente se nos configuran algunos parámetros de la máquina automáticamente como el hostname, se ejecuta el user-data que le hemos pasado, se crea un usuario estándar con nuestra clave pública,… ¿De dónde proviene todo esto? ¿Como puedo recoger toda esta información y actuar si me preparo una AMI de zero?
La respuesta está en el servicio de metadatos, el servicio de metadatos es un servicio http que se encuentra en la dirección 169.254.169.254 de cada máquina. Si ejecutamos por ejemplo:

curl http://169.254.169.254/latest/meta-data/

Podremos ver todos los metadatos relacionados con la instancia. Si ejecutamos:

curl http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key

Podremos ver la clave pública con la que AWS nos configura el usuario ec2-user.
Con ésto podemos ejecutar nuestros propios scripts para que nuestro servidor arranque con las configuraciones que nos interesen del meta-data. Otra posibilidad es instalar cloud-init, el cual nos permite configurar los parámetros del meta-data cómo queremos que se comporten. Las AMIs oficiales de AWS llevan cloud-init instalado por defecto.

ASG Termination Policy

En los autoscaling groups de Amazon se puede configurar la política para de terminar las máquinas virtuales. Por defecto siempre se borra la que más cerca de llegar a un numero entero de horas del Launch Configuration más viejo del Availability Zone en el que tengamos más máquinas.
Si queremos cambiar éste comportamiento, podemos cambiar la termination policy a uno de estos parámetros:

  • OldestInstance – Dentro del Auto Scaling group seleccionado (el que tenga más instancias) se selecciona la instancia más vieja.
  • NewestInstance – Se termina la instancia más recientemente creada.
  • OldestLaunchConfiguration – Se termina la instancia del Launch Configuration más viejo.
  • ClosestToNextInstanceHour – Se termina la instancia que más a punto está de cumplir un múltiplo de 60 minutos.
  • Default – Se termina con la política por defecto explicada más arriba.

ASG Health Checks

En los AutoScaling Groups, AWS utiliza health checks para detectar si una instancia está en buen estado. En caso de que una instancia no esté respondiendo, es terminada y en caso de que sea necesario escalará agregando nuevas instancias. Por defecto el health check se coge del estado general de EC2 y aunque es la configuración recomendada, en caso de tener un Elastic Load Balancer asociado al AutoScaling Group se puede hacer que los health checks se cojan del estado que está detectando el balanceador. Ésta última configuración puede dar raíz a problemas, imaginemos que de repente nos llega mucha carga y nuestras instancias dejan de responder un código 200 a los balanceadores que hemos configurado como healthcheck, ¿que pasará? El resultado será que en vez de escalar nuestro AutoScaling Group las instancias que no respondían serán eliminadas teniendo el efecto contrario al deseado. Más información aquí.

Multi-Factor Authentication

Con Multi-Factor Authentication, AWS permite la autenticación con dos factores, por un lado tenemos el usuario y contraseña y por el otro tenemos el segundo factor que puede ser con dispositivos virtuales como Google Authenticator, o la virtual MFA de AWS. También se puede utilizar Gemalto como dispositivo físico, el cual  nos dará aún más seguridad que los dispositivos virtuales.

AWS Direct Connect

ADC_Connection_Map_v3_screen
Aunque el diagrama lo dice casi todo, DirectConnect trata de tener conectividad directa hacia los Centros de Datos de AWS, ¿como se hace esto? Pues básicamente debemos tirar un enlace a uno de los routers de Direct Connect y tenemos ancho de banda dedicado con AWS, la parte de conectividad del router a los centros de datos de AWS es gestionado por AWS. +Info aquí

Aplicación para dispositivos móviles

Y para terminar, y más como curiosidad que otra cosa, vemos que existe una aplicación de AWS para móviles. Se puede encontrar en el PlayStore de Android y en el AppStore de Apple. Después de probar la aplicación si que vemos que aunque es útil para visualizar el estado de nuestra infraestructura, no nos sirve para poder lanzar nueva infraestructura o cambiar configuraciones.
Esto es todo cloudadmins, si tienen cualquier duda o sugerencia pongan sus comentarios!
Saludos,
Oriol Marti
Cloud Admin

Categories
General In detail

Rotando logs de apache a S3

Con la llegada de Amazon AWS y conceptos como el autoescalado nos surge un reto al que tenemos que enfrentarnos: como guardamos los logs de las máquinas que pueden ser creadas y borradas en cualquier momento?
AmazonS3-Multifile2

Soluciones

Para solventar este problema las soluciones son varias. A continuación se enumeran las virtudes y defectos de algunas de ellas y veremos como poner en marcha la solución de rotar los logs a un storage basado en objetos como S3.

  • Servicio de logs en cloud: Hay muchos servicios de este tipo: loggly, sumologic, papertrail, …. Las ventajas de un servicio de estas características es que nos despreocupamos de un componente de nuestra arquitectura y nos ahorramos dolores de cabeza, a parte de las funcionalidades extras para la visualización y análisis de logs. El problema pero cómo podéis ver en los enlaces de tarifas de loggly y papertrail son los precios, sobretodo si tenemos un volumen considerable de logs.
  • FIleSystem Compartido: Esta solución tiene la desventaja que tenemos un punto más de fallo en nuestra arquitectura.
  • Syslog-ng: Con esta solución la ventaja es que tenemos una máquina con los logs centralizados, pero tenemos que tener un servicio mas corriendo y si no tenemos muchas máquinas corriendo no es una solución muy óptima por los costes añadidos.
  • Rotación de logs a storage basado en objetos: Las ventajas de esta solución es que es económica y sencilla, a parte de no tener dependencias de servicios que puedan fallar al tratarse de S3 el cual tiene una disponibilidad de 99,99% y una durabilidad de un 99.999999999%. Cómo desventajas destacaría su tratamiento que como veremos existe una alta fragmentación y que existe la posibilidad aunque sea poco probable  de perder logs .

Rotación de logs a S3

log-rotate-300x299
Para rotar los logs de apache a S3 utilizaremos la herramienta logrotate, la idea es rotar los logs cada hora y sincronizarlos con un bucket de S3 con el comando s3cmd. A parte de rotar los logs cada hora, tenemos el añadido de que si nuestra máquina está corriendo en un autoescaling group, ésta puede ser eliminada en cualquier momento. Teniendo en cuenta que primero las máquinas són paradas con un soft shutdown, podemos crear un servicio que cuando la máquina sea parada fuerce a rotar los logs para no perderlos. En caso de que la sincronización tardara demasiado Amazon haría un hard shutdown y podríamos perder los logs de las últimas dos horas.

Instalación s3cmd

En primer lugar vamos a instalar s3cmd.
El primer paso es añadir los repositorios de epel para instalar pip:

# rpm -ivh http://mirror-fpt-telecom.fpt.net/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm

Desactivamos el repositorio epel, para que sólo sea utilizado cuando lo indiquemos explícitamente en yum.

# sed -i "s/enabled=1/enabled=0/g" /etc/yum.repos.d/epel.repo

Instalamos pip  y python-magic indicando que nos active temporalmente el repositorio epel.

# yum -y install python-pip python-magic --enablerepo=epel

Instalamos s3cmd:

# pip install s3cmd

Para la configuración del s3cmd creamos el fichero de configuración correspondiente en /root/.s3cfg, sustituyendo <acces_key> y <secret_key> por las credenciales correspondientes a nuestro usuario:

[default]
access_key = <acces_key>
access_token =
add_encoding_exts =
add_headers =
bucket_location = EU
cache_file =
cloudfront_host = cloudfront.amazonaws.com
default_mime_type = binary/octet-stream
delay_updates = False
delete_after = False
delete_after_fetch = False
delete_removed = False
dry_run = False
enable_multipart = True
encoding = UTF-8
encrypt = False
follow_symlinks = False
force = False
get_continue = False
gpg_command = /usr/bin/gpg
gpg_decrypt = %(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_encrypt = %(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s
gpg_passphrase = testtt
guess_mime_type = True
host_base = s3.amazonaws.com
host_bucket = %(bucket)s.s3.amazonaws.com
human_readable_sizes = False
invalidate_default_index_on_cf = False
invalidate_default_index_root_on_cf = True
invalidate_on_cf = False
list_md5 = False
log_target_prefix =
mime_type =
multipart_chunk_size_mb = 15
preserve_attrs = True
progress_meter = True
proxy_host =
proxy_port = 0
recursive = False
recv_chunk = 4096
reduced_redundancy = False
secret_key = <secret_key>
send_chunk = 4096
simpledb_host = sdb.amazonaws.com
skip_existing = False
socket_timeout = 300
urlencoding_mode = normal
use_https = True
verbosity = WARNING
website_endpoint = http://%(bucket)s.s3-website-%(location)s.amazonaws.com/
website_error =
website_index = index.html

Para testear que funciona bien el s3cmd, vamos a sincronizar un archivo, supondremos que ya tenemos creado un bucket de nombre logs:

# mkdir test
# cd test
# echo "This is a test" > test
# s3cmd sync . s3://logs/

En este punto deberíamos ver cómo se ha sincronizado nuestro fichero con el bucket. Para verlo con el s3cmd:

# s3cmd ls s3://logs/

Configuración logrotate

Vamos a configurar el logrotate para que al rotar los logs del apache sincronice estos con nuestro bucket de S3. Sustituimos el fichero /etc/logrotate.d/httpd con el siguiente contenido:

/var/log/httpd/*log {
    daily
    rotate 4
    size 5k
    dateext
    dateformat +%Y-%m-%d.%s
    compress
    missingok
    sharedscripts
    postrotate
        /sbin/service httpd reload > /dev/null 2>/dev/null || true
        BUCKET=logs
        INSTANCE_ID=`/usr/bin/curl --silent http://169.254.169.254/latest/meta-data/instance-id`
        /usr/bin/s3cmd -c /root/.s3cfg -m text/plain sync /var/log/httpd/*gz* s3://${BUCKET}/${INSTANCE_ID}/ > /dev/null
    endscript
}

Con esta configuración, los parámetros a tener en cuenta son:

  • daily: Nos rotará los logs diariamente, aunque en nuestro caso los vamos a rotar cada hora si ocupan más de 5Kbytes. Más adelante veremos cómo.
  • rotate 4: Nos borrará los logs a partir de 4 rotaciones.
  • size 5k: Éste parámetro hace que los logs siempre sean rotados, aunque tengamos la política daily, si éstos ocupan más de 5KB.
  • dateext: Hace que los logs sean guardados poniendo la fecha en el nombre, el formato es el de dateformat.
  • dateformat +%Y-%m-%d.%s: Formato de la fecha: Año, mes, día del mes y segundos des de 1970.
  • compress: Al hacer la rotación los logs antiguos son comprimidos.
  • sharedscripts: Corre la sección de postrotate una sola vez para todos los ficheros.
  • postrotate: Sección a correr una vez se han rotado los logs, en nuestro caso se hace un reload del apache, se recoge el nombre de instancia de nuestra máquina en EC2 y se sincronizan los logs que están comprimidos con el bucket logs dentro de un directorio con nuestro nombre de instancia.

Tenemos que tener en cuenta, aunque la página del man diga lo contrario el postrotate es ejecutado antes de la compresión, por lo que no nos sincronizará los logs actuales hasta la siguiente rotación de logs, que como veremos será al cabo de una hora.
Debido a que la rotacion de logs ocurre una sola vez al dia, y en nuestro caso queremos que se haga cada hora, vamos a crear el fichero /etc/cron.hourly/1logrotatehttpd con el siguiente contenido:

#!/bin/sh
/usr/sbin/logrotate  /etc/logrotate.d/httpd >/dev/null 2>&1
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
    /usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0

Le damos permisos de ejecución:

# chmod +x /etc/cron.hourly/1logrotatehttpd

Rotando logs al parar la máquina

Con lo que hemos visto hasta ahora, ya tenemos preparada nuestra máquina para que sincronice los logs cada hora, con la particularidad que siempre nos sincroniza los de la última hora y no los actuales. Si la máquina es borrada de nuestro autoscaling group perderemos nuestros logs, por lo que necesitamos crear un script en el /etc/init.d que sincronice los logs antes de apagar la máquina. Creamos el script /etc/init.d/s3sync con el siguiente contenido:

#!/bin/bash
#
# s3sync     Sync httpd logs to S3
#
# chkconfig: -  86 14
# description:	s3sync logs of apache
# processname: s3sync
#
#
### BEGIN INIT INFO
# Provides: s3sync
# Required-Start: $local_fs $remote_fs $network $named
# Required-Stop: $local_fs $remote_fs $network
# Short-Description: s3sync logs of apache
# Description: s3sync logs of apache
### END INIT INFO
# Source function library.
. /etc/init.d/functions
start() {
    touch /var/lock/subsys/s3sync
    return 0
}
stop() {
    /usr/sbin/logrotate -f /etc/logrotate.d/httpd
    BUCKET=logs
    INSTANCE_ID=`/usr/bin/curl --silent http://169.254.169.254/latest/meta-data/instance-id`
    /usr/bin/s3cmd -c /root/.s3cfg sync /var/log/httpd/*gz* s3://${BUCKET}/${INSTANCE_ID}/ > /dev/null
    return 0
}
restart() {
    stop
    start
}
case "$1" in
    start)
	start
	RETVAL=$?
	;;
    stop)
	stop
	RETVAL=$?
	;;
    restart)
	restart
	RETVAL=$?
	;;
    *)
	echo $"Usage: s3sync {start|stop|restart|condrestart|status|panic|save}"
	RETVAL=2
	;;
esac
exit $RETVAL

Hacemos ejecutable el script, lo configuramos para que arranque al arrancar la máquina y le hacemos un start:

# chmod +x /etc/init.d/s3sync
# chkconfig s3sync on
# service s3sync start

Como hemos visto mediante el logrotate no se rotan los últimos logs y en caso de que ocupen menos de 5k tampoco. Así pues necesitaremos hacer una sincronización después de rotados los logs. A parte para que los logs de menos de 5k sean también sincronizados necesitaremos ejecutar el logrotate con el flag -f (force). En CentOs para indicar que un servicio está corriendo y por lo tanto para que al parar la máquina ejecute el stop del servicio en cuestión se debe crear un fichero con el mismo nombre del fichero en /var/lock/subsys
Con esto ya tenemos nuestros logs de apache rotando a S3 y con el mínimo peligro de que se pierdan, como ya os podéis imaginar éste manual se podría aplicar a muchos otros servicios que tengan logs.
Un saludo cloudadmins !!
Oricloud

Categories
In detail OpenSource Security

OpenvSwitch y OpenNebula – 3a entrega

openvswitch
opennebula_logo
Siguiendo con la serie de posts sobre OpenvSwitch y OpenNebula en los que vamos viendo la integración de OpenNebula con Open vSwitch a través del driver, vamos a ver en esta última entrega cómo se aplica el control de MAC-Spoofing en openNebula y cómo añadir también control para IP-Spoofing que por defecto no viene en el driver de OpenNebula.

MAC-Spoofing

En caso de que una máquina se cambie la MAC, sabemos que se puede hacer un ataque de man-in-the-middle entre otros problemas derivados, para evitar esto OpenNebula añade una regla al Open vSwitch para fijar la MAC, el comando que se ejecuta és de la siguiente forma, donde <mac> es la MAC asignada por OpenNebula a la máquina virtual y <puerto> es el puerto que se ha creado sobre el bridge de OpenvSwitch:

# ovs-ofctl add-flow br32 in_port=<port>,dl_src=<mac>,priority=40000,actions=normal
# ovs-ofctl add-flow br32 in_port=<port>,priority=39000,actions=drop

Los comandos anteriores lo que hacen es filtrar todo el tráfico por defecto en el puerto (prioridad 39000) y sólo dejar pasar el tráfico por el puerto que tenga la mac de la máquina virtual cómo destino/origen (prioridad 40000). Más prioridad indica que en caso de hacer match se ejecutará esta y no pasara a las siguientes.
En primer lugar vamos a probar que efectivamente si cambiamos la MAC de una máquina virtual el tráfico hacia esta es descartado . Hacemos dos máquinas virtuales con la IP 192.168.2.29 y 192.168.2.31 situadas en el mismo host físico , y cambiamos la MAC de la segunda con el macchanger :

# macchanger -r eth1

Seguidamente hacemos un ping entre las dos redes y vemos como efectivamente no llegan tanto los pings de la primera a la segunda como los de la segunda a la primera .
También hacemos un tcpdump en la segunda mientras hacemos el ping:

20:15:10.946400 ARP, Request who-has 192.168.2.31 tell 192.168.2.29, length 46
20:15:10.946409 ARP, Reply 192.168.2.31 is-at 10:c7:43:8a:dc:8d, length 28

Vemos como los broadcast de petición who-has si que nos llegan ya que estos no tienen ninguna MAC de destino asociada, pero al contestar la segunda máquina los paquetes son descartados y el mensaje anterior se repite ya que la primera máquina va repitiendo al no encontrar ninguna máquina que conteste con su MAC a la petición .
Si después de hacer el ping ejecutamos en la primera máquina lo siguiente:

# arp- a

Nos da la siguiente salida :

? (192.168.2.31) at <incomplete> on eth1

Lo cual nos confirma que los paquetes de respuesta de la IP en la petición ARP no está llegando a la primera máquina .
Vamos a hacer la misma prueba borrando las reglas de Open vSwitch que no permiten el tráfico más que en la MAC asignada , ejecutamos los siguientes comandos en la máquina física:

ovs-ofctl del-flows <bridge> dl_src=<mac>
ovs-ofctl del-flows <bridge> in_port=<port>

donde <bridge> es el bridge sobre el que estamos poniendo las máquinas virtuales , <mac> es la MAC inicial de la segunda máquina y <puerto> es el puerto virtual sobre el que se ha creado la máquina virtual en el bridge .
Ahora hacemos un ping desde la primera a la segunda y viceversa y vemos cómo efectivamente llegan los pings después de haber falseado la MAC de la segunda . Si miramos la tabla ARP de la primera máquina :

# arp- a

Vemos lo siguiente:

? (192.168.2.31) at 10:c7:43:8a:dc:8d [ether] on eth1

Así pues vemos como efectivamente la máquina está viendo la MAC falseada.
En este apartado tan sólo hemos comprovado que efectivamente funciona el control de MAC-Spoofing en OpenNebula, en el próximo apartado vamos a ver cómo OpenNebula no tiene implementado el control de IP-Spoofing y como implementar éste.

IP-Spoofing

Si cambiamos la IP a una máquina con OpenNebula veremos cómo efectivamente és possible falsear las IPs que OpenNebula assigna a nuestra máquina virtual. Los comandos vistos en el anterior apartado para que no sea posible hacer MAC-Spoofing són los siguientes:

# ovs-ofctl add-flow <bridge> in_port=<port>,dl_src=<mac>,priority=40000,actions=normal
# ovs-ofctl add-flow <bridge> in_port=<port>,priority=39000,actions=drop

Los comandos que se ejecutan para añadir los filtros, cómo vimos en la segunda entrega:

# ovs-ofctl add-flow <bridge> tcp,dl_dst=<mac>,tp_dst=<port>/<mask>,dl_vlan=<vlan>,actions=drop

y para añadir el filtro icmp:

ovs-ofctl add-flow <bridge> icmp,dl_dst=<mac>,dl_vlan=<vlan>,actions=drop

Vemos pues que no se está aplicando ningún filtro si la IP no corresponde a la que se ha definido, también hemos visto ya en el apartado anterior cómo el segundo comando del primer bloque nos filtra todo el tráfico que pase por la puerto virtual asignado a la máquina virtual , pero con una prioridad menor a la primera, que lo que hace es dejar pasar el tráfico del puerto en cuestión que coincida con la MAC de la máquina virtual.
Para el fin de que en el primer comando se filtre también lo que no coincida con la IP , necesitamos añadir el tag nw_src=<ip> , pero para añadirlo open vswitch nos obliga definir el protocolo cómo IP, ya que por ejemplo con el protocolo ARP no tiene sentido, para definir el protocolo como IP lo haremos añadiendo dl_type=0x0800
Así pues el primer comando queda de la siguiente forma:

# ovs-ofctl add-flow <bridge> dl_type=0x0800,in_port=<port_virtual>,dl_src=<mac>,nw_src=<ip>,priority=40000,actions=normal

Con este comando, pero vemos que mientras antes se dejava pasar el tráfico ARP, ahora no se está permitiendo, así pues necesitamos añadir una nueva regla que deje pasar el tráfico ARP para la MAC correspondiente. Para especificar el tráfico ARP se hace con dl_type=0x0806. Así pues, la regla quedará de la siguiente forma:

# ovs-ofctl add-flow <bridge> dl_type=0x0806,dl_src=<mac>,in_port=<port_virtual>,priority=40000,actions=normal

Una vez aplicada la regla se ha probado y funciona correctamente el control de IP-Spoofing.
Con este post terminamos la serie de Open vSwitch y OpenNebula. Para bajar el driver entero, se puede bajar de aqui.
Un saludo des del cloud! 😉

Categories
OpenSource

OpenvSwitch y OpenNebula – 2a entrega

openvswitch
opennebula_logo
Siguiendo con la serie de posts sobre OpenvSwitch y OpenNebula en los que vamos viendo la integración de OpenNebula con Open vSwitch a través del driver, vamos a ver en esta entrega cómo poder aplicar firewalling con OpenNebula al driver de OpenvSwitch.
Para empezar, vamos a ver como se configura el firewalling en general con OpenNebula, en este enlace podemos ver mas detalles. OpenNebula tiene cinco campos especiales a la hora de crear una màquina/template que són:

  • WHITE_PORTS_TCP: Se filtran todos los puertos tcp menos los especificados por el parámetro, para especificarlo se hace con “:” para rangos de puertos y con “,” para puertos especificos. Así pues si queremos filtrar todos los puertos menos el 22, el 80 i del 2000 al 3000  se pasaria la variable de la siguiente forma: WHITE_PORTS_TCP = 22,80,2000:3000  
  • BLACK_PORTS_TCP: Se filtran sólo los puertos tcp especificados, para especificar los puertos a filtrar se hace de la misma forma que con el WHITE_PORTS_TCP, però en este caso el funcionamiento es el inverso, és decir se filtran todos los puertos especificados y el resto se dejan abiertos. En caso de especificar tanto el WHITE_PORTS_TCP cómo el BLACK_PORTS_TCP, entonces se aplican sólo los WHITE_PORTS_TCP. Si quisieramos filtrar todos los puertos menos el 22, 80 i del 2000 al 3000, en este caso se especificaria de la siguiente forma:  BLACK_PORTS_UDP = 1:21,23:79,81:1999,3001:65535
  • WHITE_PORTS_UDP: En este caso el funcionamiento és idéntico al TCP pero con tráfico UDP.
  • BLACK_PORTS_UDP: También este caso es idéntico al TCP pero con UDP.
  • ICMP: En el caso de ICMP podemos optar por filtrar todo el tráfico o no, si queremos filtrarlo, lo especificaremos de la siguiente forma: ICMP = drop

Para la implementación de esta funcionalidad con Open vSwitch, en el driver actual de OpenNebula no se pueden especificar rangos de puertos, se tienen que hacer uno a uno. Se ha provado i si se crean máquinas virtuales con muchos puertos filtrados, tarda muchas horas en crear la máquina virtual y añade mucha carga adicional al nodo físico. Para solventarlo tendremos que actualizar la versión de open vSwitch a la 1.6 o superior, ya que a partir de esta se pueden especificar los puertos con mascaras. Con las mascaras podemos especificar un puerto y la mascara asociada, la cual cosa nos permitirá filtrar todo el rango de puertos a los que se llegue con esta. Si por ejemplo quisieramos filtrar del puerto 32768 al 65535, podriamos hacerlo especificanod el puerto y la mascara de la siguiente forma (en hexadecimal): 0x8000/0x8000. Aqui podemos ver como el numero 32768 equivale a 0x8000 (el primero) y el rango de puertos que estaremos filtrando irá del 0x8000 (1000 0000 0000 0000) al 0xFFFF (1111 1111 1111 1111)  és decir el 65535 después de aplicarle la mascara.
Vemos pero que si queremos aplicar un filtro que vaya del puerto 32769 al 65535 la cosa no es tan evidente, ya que tenemos que hacer un filtro que para el 32769/0xFFFF, otro para el 32770/0xFFFE, otro para el 32772/0xFFFC y asi sucesivamente.
Así pues el algoritmo para el filtrado con rangos de puertos será:
Para todos los puertos p:

  1. Calculamos la máscara máxima para no filtrar algun puerto ya filtrado o que no se tenga que filtrar
  2. Calculamos la máscara máxima para los puertos que se tendrán que filtrar a continuación, hasta encontrar alguno que no sea consecutivo
  3. Aplicamos la mascara más pequeña entre 1 y 2.
  4. Aplicamos el filtro con la máscara escogida
  5. p= maximo puerto filtrado en 4 (aplicando mascara) + 1

En el ejemplo de que quisieramos filtrar todos los puertos menos el 22,80 y del 2000 al 3000, las reglas correspondientes quedarian de la siguiente forma:

0x1/0xffff, 0x2/0xfffe, 0x4/0xfffc, 0x8/0xfff8, 0x10/0xfffc, 0x14/0xfffe,
0x17/0xffff, 0x18/0xfff8, 0x20/0xffe0, 0x40/0xfff0, 0x51/0xffff, 0x52/0xfffe,
0x54/0xfffc, 0x58/0xfff8, 0x60/0xffe0, 0x80/0xff80, 0x100/0xff00, 0x200/0xfe00,
 0x400/0xfe00, 0x600/0xff00, 0x700/0xff80, 0x780/0xffc0, 0x7c0/0xfff0,
0x7d1/0xffff, 0x7d2/0xfffe, 0x7d4/0xfffc, 0x7d8/0xfff8, 0x7e0/0xffe0,
0x800/0xfe00, 0xa00/0xff00, 0xb00/0xff80, 0xb80/0xffe0, 0xba0/0xfff0,
0xbb0/0xfff8, 0xbb9/0xffff, 0xbba/0xfffe, 0xbbc/0xfffc, 0xbc0/0xffc0,
0xc00/0xfc00, 0x1000/0xf000, 0x2000/0xe000, 0x4000/0xc000, 0x8000/0x8000

Así pues, vemos que con este ejemplo pasariamos de 64532 reglas para aplicar a 43 gracias a las mascaras.

Actualización del driver de OpenNebula

Una vez visto que es lo que tenemos que hacer para que nos funcionen los drivers para OpenvSwitch con mascaras vamos a ver las modificaciones que se tienen que hacer en el driver de OpenNebula para Open vSwitch. El fichero en cuestión se encuentra en /var/lib/one/remotes/vnm/ovswitch/OpenvSwitch.rb. Aqui podeis encontrar el fichero con las modificaciones que se han explicado en el post.
Para modificar el driver, lo único que tenemos que hacer és sobreescribir el fichero y ejecutar:

onehost sync

Una vez ejecutado el comando ya podremos crear máquinas virtuales pasandoles los parametros de filtraje como con el driver por defecto.
Oriol Marti
www.cloudadmins.org

Categories
General In detail

OpenvSwitch y OpenNebula – 1a entrega



Cómo ya vimos es posts anteriores, Open vSwitch és un software de virtualización de redes pensado sobretodo para la virtualización en plataformas Linux como Xen o KVM. Después de estar trasteando un buen tiempo con OpenNebula pensamos que seria una muy buena idea añadirle el soporte que viene integrado con Open vSwitch. Al añadir el driver para este, pero, nos encontramos con que el driver no está acabado del todo y que nos quedábamos sin algunas de las funcionalidades de red de OpenNebula.
Así pues, vamos a empezar una serie de posts con los que iremos viendo algunas de las deficiencias que se han encontrado a los drivers de OpenNebula para Open vSwitch y las soluciones que le hemos aplicado al driver en cuestión. En este primer post vamos a ver un bug que se ha encontrado en el driver y la solución que se ha aplicado. Tener en cuenta que en la versión 4.0 de OpenNebula este bug ya a sido solucionado. En posts futuros veremos como se ha añadido soporte para filtraje de rangos de puertos y cómo hacer que el tráfico de las máquinas virtuales sea descartado en caso de que la IP sea falseada en las máquinas virtuales.
OpenNebula asigna la MAC a las interfícies de las máquinas virtuales según la IP que asignamos, entonces si hacemos dos redes con coincidencia de IPs en diferentes VLANs es probable que las MACs de dos máquinas virtuales coincidan están en la misma máquina física.
Para entender bien el bug, en primer lugar se han hecho pruebas de si este caso afecta al comportamiento de la red. Se han creado dos redes taggeadas diferentes con el mismo direccionamiento, así pues cuando creemos interfícies de cada una de las redes sobre el bridge estas estarán taggeadas con una etiqueta diferente.
Se han creado 4 máquinas virtuales:
1 y 2 – con VLAN con etiqueta 1. La primera tiene la IP 192.168.2.1 y MAC 02:00:c0:a8:02:01 y la segunda tiene la IP 192.168.2.2 y MAC 02:00:c0:a8:02:02
3 y 4 – con VLAN con etiqueta 2. La tercera tiene la IP 192.168.2.1 y MAC 02:00:c0:a8:02:01 y la tercera tiene la IP 192.168.2.2 y MAC 02:00: c0: a8: 02:02
Vemos pues que las máquinas 1 y 3 y las máquinas 2 y 4 coinciden en la MAC, para la prueba hemos puesto la máquina 1 y 3 en el mismo nodo físico y la 2 y la 4 en otro las dos.
Una vez hecho esto, desde la máquina 1 hacemos un ping a la IP 192.168.2.2 mientras en las máquinas 2 y 4 hacemos un tcpdump, la salida del tcpdump en la máquina 2 es:

20:27:36.768326 ARP, Request who-has 192.168.2.2 tell 192.168.2.1, length 46
20:27:36.768336 ARP, Reply 192.168.2.2 is-at 2:00: c0: a8: 02:02, length 28
20:27:36.769355 IP 192.168.2.1> 192.168.2.2: ICMP echo request, y 46852, seq 1, length 64
20:27:36.769390 IP 192.168.2.2> 192.168.2.1: ICMP echo reply, id 46852, seq 1, length 64

En la máquina 4 el tcpdump no nos da ninguna salida.
Así pues vemos como a pesar de tener interfaces con la misma MAC no afecta al correcto funcionamiento del Open vSwitch, ya que están taggeadas diferente y el Open vSwitch aunque detecta MACs duplicadas sabe redirigir el tráfico según la VLAN a la que pertenece cada paquete de red .
Si miramos el driver de Open vSwitch en el fichero /var/lib/one/remotes/vnm/ovswitch/OpenvSwitch.rb, veremos que las reglas de firewalling se aplican para la MAC, suponiendo que queremos filtrar el puerto 1 para la máquina con MAC <mac>, el comando que se ejecuta en las máquinas físicas es como sigue:

sudo ovs-ofctl add-flow br32 tcp,dl_dst=<mac>,tp_dst=0x1,actions=drop

Vemos como cuando se aplica el filtraje, sólo se tiene en cuenta la MAC, así si aplicamos filtros sobre una máquina virtual y tenemos otra con la misma MAC, se aplicará sobre las dos máquinas al mismo tiempo, por lo que los filtros aplicados por un usuario podrían afectar a los demás.
Hemos hecho la misma prueba que en el apartado anterior y efectivamente hemos visto que al aplicar un firewall sobre una MV si tenemos otra MV en la misma red que tenga la misma MAC (aunque esté en otra VLAN) aplica las reglas para a las dos máquinas.
Para solventar este problema se han modificado las reglas añadiendo el tag dl_vlan al comando ovs-ofctl. Se ha probado y efectivamente, como las redes por fuerza tienen diferente tag de VLAN, funciona correctamente.
Hay que tener en cuenta que desde el Sunstone es posible crear redes sin que estén taggeadas. En este caso si que podríamos tener un problema, ya que si las redes no tienen ninguna etiqueta, no están en ninguna VLAN, entonces si que tenemos el problema explicado anteriormente.
El comando anterior, una vez arreglado este bug quedaría de la siguiente forma, suponiendo que la interfaz de la máquina virtual está en la vlan 3001:

sudo ovs-ofctl add-flow br32 tcp,dl_vlan=3001,dl_dst=<mac>,tp_dst=0x1,actions=drop

En este y este enlace podemos ver el seguimiento del bug, en el segundo enlace podemos también descargarnos el driver para OpenNebula modificado.
Eso es todo por este post, en los siguientes, tal y como ya hemos avanzado al principio veremos cómo permitir el filtraje de puertos por rangos mediante Open vSwitch y añadir la funcionalidad en los mismos drivers para no permitir que las máquinas virtuales puedan hacer IP-Spoofing.
Un saludo clouderos! 😉

Categories
General Security Social

Videos del I Congreso de Seguridad en la Red. (UOC-Con)

.
El pasado 4 de Junio se celebró en Barcelona el I congreso de seguridad en la red (UOC-Con) organizado por la UOC. Las charlas, muy interesantes, se enfocaron a ciberguerra y ciberespionaje.
Sin más os dejamos los videos de cada  una de ellas, no tienen pérdida.




Jesús Luna García – Generando Confianza en el Cloud



Vicente Díaz – 2013: Del cibercrimen a la ciberguerra



David Barroso – Ataques dirigidos a activistas



Chema Alonso – WorldWar III

Categories
General

GRE Tunnels en Open vSwitch


Siguiendo con la serie de posts sobre Open vSwitch, vamos a ver hoy cómo configurar GRE Tunneling sobre éste. Para los que no lo sepáis, GRE nos permite configurar un enlace Point-to-Point entre dos IPs y tener un enlace a nivel 2 entre dos puntos a través de internet, a efectos prácticos seria como tener una VPN entre estos dos puntos.
Siguiendo con el post sobre un ejemplo práctico en OpenvSwitch ahora vamos a suponer el caso de que tenemos dos hosts con máquinas virtuales, pero separados por internet, en diferentes CPDs, sin conexión a nivel 2, cómo ya vimos, nos interesa que nuestros clientes puedan crear máquinas virtuales en cada una de las máquinas y además cada uno tendrá sus redes privadas implementadas con VLANS en Open vSwitch, estas redes privadas tienen que tener visibilidad entre los dos hosts, al estar las dos máquinas separadas por internet, necesitaremos hacer un túnel GRE para que se vean a nivel 2. Un ejemplo podría ser como sigue:

Vemos en la figura anterior, cómo tendremos un bridge en cada uno de los hosts con una IP pública, en el bridge02 tendremos un puerto haciendo túnel en GRE y especificando la IP del otro host. Así pues a través de la conexión del túnel GRE tendremos los dos hosts conectados a nivel 2. Vamos a ver las IPs que tendrá cada uno de ellos:
Host1- IP 82.82.82.1
Host2- IP 82.82.82.2
Vamos a configurar pues el bridge01 en el host1:

# ovs-vsctl add-br bridge01

# ovs-vsctl add-port bridge01 eth0
# ifconfig bridge01 82.82.82.1
Configuramos el bridge01 en el host2:
# ovs-vsctl add-br bridge01
# ovs-vsctl add-port bridge01 eth0
# ifconfig bridge01 82.82.82.2
Configuramos el bridge02 en el host1, le añadiremos un puerto de tipo gre, especificando la IP del host2:
# ovs-vsctl add-br bridge02
# ovs-vsctl add-port bridge02 gre0 -- set interface gre0 type=gre options:remote_ip=82.82.82.2
Lo mismo en el host2 pero con la IP del host1:
# ovs-vsctl add-br bridge02
# ovs-vsctl add-port bridge02 gre0 -- set interface gre0 type=gre options:remote_ip=82.82.82.1
Una vez configurado, ya podemos añadir puertos en el bridge02, en vez de añadir máquinas virtuales cómo en el post anterior, vamos a añadir dos puertos mapeados a una interfície en cada uno de los hosts, el primero con el tag 1 y el segundo con el tag 2 y vamos a ver que hay visibilidad entre cada VLAN:
Añadimos los puertos en el host1, los taggeamos y les asignamos una IP:
# ovs-vsctl add-port bridge02 bridge02p1 -- set interface bridge02p1 type=internal
# ovs-vsctl set port bridge02p1 tag=[1]
# ifconfig bridge02p1 192.168.1.1
# ovs-vsctl add-port bridge02 bridge02p2 -- set interface bridge02p2 type=internal
# ovs-vsctl set port bridge02p2 tag=[2]
# ifconfig bridge02p2 192.168.2.1
Añadimos los puertos en el host2:
# ovs-vsctl add-port bridge02 bridge02p1 -- set interface bridge02p1 type=internal
# ovs-vsctl set port bridge02p1 tag=[1]
# ifconfig bridge02p1 192.168.1.2
# ovs-vsctl add-port bridge02 bridge02p2 -- set interface bridge02p2 type=internal
# ovs-vsctl set port bridge02p2 tag=[2]
# ifconfig bridge02p2 192.168.2.2
Vamos a hacer un ping des del host1 a las IPs del host2:

host1:~# ping -c4 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_req=1 ttl=64 time=0.532 ms
64 bytes from 192.168.1.2: icmp_req=2 ttl=64 time=0.160 ms
64 bytes from 192.168.1.2: icmp_req=3 ttl=64 time=0.154 ms
64 bytes from 192.168.1.2: icmp_req=4 ttl=64 time=0.158 ms
--- 192.168.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.154/0.251/0.532/0.162 ms
host1:~# ping -c4 192.168.2.2
PING 192.168.1.2 (192.168.2.2) 56(84) bytes of data.
64 bytes from 192.168.2.2: icmp_req=1 ttl=64 time=0.528 ms
64 bytes from 192.168.2.2: icmp_req=2 ttl=64 time=0.148 ms
64 bytes from 192.168.2.2: icmp_req=3 ttl=64 time=0.148 ms
64 bytes from 192.168.2.2: icmp_req=4 ttl=64 time=0.150 ms
--- 192.168.2.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2999ms
rtt min/avg/max/mdev = 0.148/0.243/0.528/0.165 ms

Vemos efectivamente como se llega a cada uno de ellos, ahora mientras hacemos el ping en la VLAN con el tag 1, vamos a ver cómo efectivamente la interfície de la VLAN 2 de la misma máquina no ve el tráfico, en el host 1 ejecutamos:

host1:~# tcpdump -ni bridge02p2
tcpdump: WARNING: test1p2: no IPv4 address assigned
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on test1p2, link-type EN10MB (Ethernet), capture size 65535 bytes

Lo dejamos un rato y vemos como efectivamente no recibe tráfico de la interfície del otro puerto.

Categories
General

Open vSwitch: Un ejemplo práctico

Un ejemplo práctico

Después de instalar KVM i Open vSwitch y ver los comandos básicos para la creación/modificación de bridges/puertos/bondings, vamos a configurar la red de nuestros hosts de KVM, los cuales tienen 53 VLANS diferentes, para este ejemplo utilizaremos 2 hosts físicos, para ver la forma de crear VLANs de forma que puedan ser vistas des del switch externo y de esta forma poder llegar a la red privada de la otra máquina. El esquema de red con los switches virtuales y con varias máquinas virtuales en funcionamiento en un momento dado podría ser:

Éste podría ser un ejemplo de proveedor de Iaas, dónde los clientes comparten la red pública y cada uno de ellos puede crearse sus propias redes privadas entre máquinas. En este ejemplo las máquinas VM1, VM2 y VM3 podrian ser de un cliente, las VM4, VM5, VM6 y VM7 de otro, y las VM8 y VM9 de otro más.
Podemos ver como tenemos varias VLAN’s, la 1 será para el management, la 2 será para el storage NFS de las máquinas físicas, y la VLAN 3 será una VLAN pública común a todos los clientes, mientras que las VLANS de la 04 a la 53 nos servirán para las redes privadas entre máquinas virtuales. Ya que éstas redes privadas deberán verse entre hosts físicos, las tendremos que tener precreadas en el switch exterior. A continuación se detalla cada una de las redes y la configuración necesaria que deberemos tener en el switch exterior.

  • Management: VLAN 01. Red para management del host físico, esta interfície no tendrá ni bridges, ni tagging ni bonding así que no intervendrá el Open vSwitch. Será una sola IP por host: 192.168.1.1 y 192.168.1.2. Así pues tendremos que configurar los puertos 1 y 6 del switch exterior con modo acceso y con la VLAN 01.
  • Storage: Red para el storage NFS de imágenes de máquinas virtuales. Debido a la criticidad del storage, tendremos un bonding sobre dos interfícies físicas. A parte aquí nos entra el tráfico taggeado con la VLAN 02 y las máquinas físicas tendrán las IPs 192.168.2.1 y 192.168.2.2. Así pues tendremos que configurar los puertos 2,3,7 y 8 del switch exterior con la VLAN 02 en modo tagged.
  • MV-pública: Red para agregar puertos a las máquinas virtuales, tanto para esta cómo para la MV-privada tendremos un bridge común sobre el que crearemos puertos con diferentes tags. Para tener mejor redundancia de puertos, vamos a hacer un bonding sobre las interfícies eth3 y eth4, en un caso real cada una de las bocas iría a un switch diferente para tener redundancia a nivel de switch. Las máquinas físicas no tendrán ninguna IP de este rango. En este caso tendremos que configurar las bocas 4,5,9 y 10 en modo tagged con las VLANS de la 3 a la 53.
  • MV-privadas: Red para agregar puertos a las máquina virtuales y crear redes privadas entre ellas, al tener varias máquinas físicas necesitaremos que salgan las VLANs del host y es por eso que tendremos que precrear las VLANs de la 4 a la 53 en el switch exterior. Tal y como se ha explicado en el apartado de MV-pública tendremos los puertos 4,5,9 y 10 del switch exterior con las VLANS 3 a la 53.

Creación de bridges

Vamos pues a crear todos los bridges y configurar la red en los hosts, en este post no entraremos a configurar los switches exteriores, supondremos que ya los tenemos configurados como se ha explicado en el apartado anterior.

Management:

Para la IP de management sólo tenemos que añadir la configuración de la IP en el fichero /etc/network/interfaces, en el host 1 quedará de esta forma:

auto eth0
iface eth0 inet static
        address 192.168.1.1
        netmask 255.255.255.0
        gateway 192.168.1.254

En el host 2 quedará:

auto eth0
iface eth0 inet static
        address 192.168.1.2
        netmask 255.255.255.0
        gateway 192.168.1.254

Storage:

Para la red de storage vamos a crear una interfície de bonding (bondst) sobre un bridge (brst), como necesitamos una IP, vamos también a crear un puerto con una interfície física (brstp1) con tagging y la IP. En los dos hosts físicos ejecutamos:
# ovs-vsctl add-br brst
# ovs-vsctl add-bond brst bondst eth1 eth2
# ovs-vsctl add-port brst brstp1 — set interface brstp1 type=internal
#ovs-vsctl set port brstp1 tag=2
Añadimos la IP a la interfície brstp1 del bridge con el openvswitch y configuramos las interfícies eth1 y eth2 para que se levanten al arrancar.
En el nodo 1 añadimos lo siguiente en el /etc/network/interfaces:

auto brstp1
iface brstp1 inet static
address 192.168.2.1
netmask 255.255.255.0
auto eth1
iface eth1 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down
auto eth2
iface eth2 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down

En el nodo 2 quedará:

auto brstp1
iface brstp1 inet static
address 192.168.2.2
netmask 255.255.255.0
auto eth1
iface eth1 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down
auto eth2
iface eth2 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down

Algunos problemas con los que me he encontrado con esta solución, son que al añadir el punto de montaje en el /etc/fstab la máquina no arranca porque se intenta montar antes de que el servicio del openvswitch se haya levantado. Una solución temporal es añadir noauto a las opciones del /etc/fstab y arrancarlo des del /etc/rc.local, si hubiera servicios que dependieran de este punto de montaje no seria una solución válida, pero como no es el caso, lo dejamos así.
La linea correspondiente al /etc/fstab podría ser como:

192.168.2.50:/vol/mvs   /mvs                  nfs     noauto 0 0

Y añadiríamos en el /etc/rc.local:

mount /mvs

MV-Pública y MV-privadas:

En este caso, cómo no tendremos ninguna IP asociada en el host, tan solo creamos los bridges y configuramos las interfícies de red eth3 y eth4 para que se levanten al arrancar la máquina.
Creamos el bridge (brmv) con el bonding (bondmv) en los dos hosts:
# ovs-vsctl add-br brmv
# ovs-vsctl add-bond brmv bondmv eth3 eth4
Añadimos en el fichero /etc/network/interfaces de los dos hosts lo siguiente para que las interfícies se levanten al arrancar:

auto eth3
iface eth3 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down
auto eth4
iface eth4 inet manual
up ifconfig $IFACE 0.0.0.0 up
down ifconfig $IFACE down

Una vez llegados a este punto ya tenemos toda la red configurada, tan sólo nos queda hacer un reboot de los hosts, ver que se ha configurado todo correctamente y empezar a crear máquinas virtuales.

Creación de máquinas virtuales

Para ver el procedimiento de creación de máquinas virtuales y para comprobar que todo esta correctamente, vamos a crear unas maquinas virtuales con la misma VLAN en diferentes hosts y vamos a comprobar que se ven entre ellas, también vamos a comprobar que no se mezcla el tráfico entre VLANs.
Vamos a suponer que tenemos dos clientes, cada uno con dos máquinas virtuales, con una IP privada cada una, cómo es lógico no queremos que las máquinas entre clientes puedan verse el tráfico, así que la VLAN privada va a tener un tag diferente para cada cliente:

  • Cliente1:
  • MV1
  • Host físico: host1
  • Redes:
    • privada: VLAN 4
  • MV2
  • Host físico: host2
  • Redes:
    • privada: VLAN 4
  • Cliente2:
  • MV3
  • Host físico: host1
  • Redes:
    • privada: VLAN 5
  • MV2
  • Host físico: host2
  • Redes:
    • privada: VLAN 5

Supondremos que ya tenemos creadas imágenes de disco con una Ubuntu instalada. Así creamos el xml de creación de la MV1 para libvirt (no se pone el xml de todas las máquina ya que serán muy parecidos adaptando el nombre, la imágen y la mac. Lógicamente el bridge donde se conectaran será para todos el mismo, cambiando posteriormente el tag de cada puerto):

# cd /mvs
# cat mv1.xml
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
        <name>mv1</name>
        <cputune>
                <shares>1024</shares>
        </cputune>
        <memory>524288</memory>
        <os>
                <type arch='x86_64'>hvm</type>
                <boot dev='hd'/>
        </os>
        <devices>
                <emulator>/usr/bin/kvm</emulator>
                <disk type='file' device='disk'>
                        <source file='/mvs/disk.mv1'/>
                        <target dev='hda'/>
                        <driver name='qemu' type='qcow2' cache='default'/>
                </disk>
                <interface type='bridge'>
                        <source bridge='br32'/>
                        <mac address='00:00:00:00:00:01'/>
                         <model type='virtio'/>
                </interface>
         </devices>
        <features>
                <acpi/>
        </features>
</domain>

Creamos las mv’s en el host1:

# virsh create mv1.xml
# virsh create mv3.xml

Creamos las mv’s en el host2:

# virsh create mv2.xml
# virsh create mv4.xml

una vez creadas las máquinas vamos a ver que puertos les ha asignado a cada uno, en el host1 ejecutamos:

# virsh dumpxml mv1 | grep vnet
<target dev='vnet0'/>
# virsh dumpxml mv3 | grep vnet
<target dev='vnet1'/>

Vamos al host 2:

# virsh dumpxml mv2 | grep vnet
<target dev='vnet0'/>
# virsh dumpxml mv4 | grep vnet
<target dev='vnet1'/>

Visto esto vamos a asignar la VLAN correspondiente a cada uno de los puertos, empezamos con el host 1:

# ovs-vsctl set port vnet0 tag=4
# ovs-vsctl set port vnet1 tag=5

Lo mismo en el host 2:

# ovs-vsctl set port vnet0 tag=4
# ovs-vsctl set port vnet1 tag=5

Comprobaciones finales

Vamos a comprobar que se ven entre las máquinas de cliente y que no se ven las máquinas de diferentes clientes.
Para empezar asignamos una dirección IP a cada una de ellas:
MV 1: 192.168.1.1
MV 2: 192.168.1.2
MV 3: 192.168.1.3
MV 4: 192.168.1.4
Hemos puesto IPs del mismo rango, pero no tendrían que verse entre las máquinas de diferentes clientes, ya que les hemos asignado diferente VLAN. Vamos a comprobarlo, entramos en la MV1:

mv1:~# ping -c4 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_req=1 ttl=64 time=0.187 ms
64 bytes from 192.168.1.2: icmp_req=2 ttl=64 time=0.193 ms
64 bytes from 192.168.1.2: icmp_req=3 ttl=64 time=0.191 ms
64 bytes from 192.168.1.2: icmp_req=4 ttl=64 time=0.205 ms
--- 192.168.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 0.187/0.194/0.205/0.006 ms

Vemos como si que se ven las máquinas mv1 y la mv2, vamos ahora a comprobar que no se ven la mv1 con la mv3

mv1:~# ping -c4 192.168.1.3
PING 192.168.1.3 (192.168.1.3) 56(84) bytes of data.
From 192.168.1.1 icmp_seq=1 Destination Host Unreachable
From 192.168.1.1 icmp_seq=2 Destination Host Unreachable
From 192.168.1.1 icmp_seq=3 Destination Host Unreachable
From 192.168.1.1 icmp_seq=4 Destination Host Unreachable
--- 192.168.1.3 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3011ms

Eso es todo por hoy. En posts futuros veremos cómo fijar las MACs de las máquinas virtuales, aplicar reglas de firewalling, QoS,…
Un saludo post navideño! 😉

Categories
General

Open vSwitch: Bridges, puertos y bondings

Bridges, puertos y bondings

Antes de entrar en materia, vamos a ver algunos comandos que nos seran útiles para crear, modificar y listar los parámetros  de bridges/puertos/bondings.

Bridges:

Para agregar un bridge la sintaxis és la siguiente:

ovs-vsctl add-br <nombre>

Una vez creado un bridge, si queremos ver las propiedades:

ovs-vsctl list bridge <nombre>

O si queremos ver las propiedades de todos los bridges:

ovs-vsctl list bridge

Esto no dará una salida parecida a la siguiente:

_uuid               : d755e5f7-04c0-477d-91b4-e0b6c078e330
controller          : []
datapath_id         : "00000026b9fae772"
datapath_type       : ""
external_ids        : {}
fail_mode           : []
flood_vlans         : []
mirrors             : []
name                : "br2066"
netflow             : []
other_config        : {}
ports               : [285c7888-d9ec-4eb6-a6cd-33865d946e81]
sflow               : []
status              : {}
stp_enable          : false

Para eliminar un bridge:

ovs-vsctl del-br <nombre>

Puertos:

Para los puertos, la sintaxis es parecida, pero siempre va asociado a un bridge:

ovs-vsctl add-port <bridge> <puerto>

Si queremos que este puerto este asociado a una interficie de red que creara el openvswitch (NO para una interfície que ya exista en la maquina), luego le podremos poner una IP por ejemplo:

ovs-vsctl add-port <bridge> <puerto> -- set interface <puerto> type=internal

Una vez creado el puerto podemos ver sus propiedades:

ovs-vsctl list port <puerto>

Nos dará una salida parecida a la siguiente:

_uuid               : fd908ca0-c636-41bd-bca9-29fcf2e60bce
bond_downdelay      : 0
bond_fake_iface     : false
bond_mode           : []
bond_updelay        : 0
external_ids        : {}
fake_bridge         : false
interfaces          : [13ca2629-5fac-412c-8dcd-b21e917f48e3]
lacp                : []
mac                 : []
name                : "puerto"
other_config        : {}
qos                 : []
statistics          : {}
status              : {}
tag                 : []
trunks              : []
vlan_mode           : []

Aqui ya podemos ver algunas propiedades interesantes, vemos como podemos configurar parametros como trunks o tag si estamos entrando VLANs taggeadas o el modo lacp si quisieramos configurarla en este modo. Para modificar alguna de sus propiedades, la sintaxis es la siguiente:

ovs-vsctl set port <puerto> <propiedad>=<valor>

Así, si quisieramos modificar el tag del puerto, un ejemplo podria ser:

ovs-vsctl set port br01pr01 tag=2022

Y para volver a dejarlo sin tag:

ovs-vsctl set port br01pr01 tag=[]

Bondings e interfícies

Para crear bondings, lo que hacemos es crear un puerto (asociado a un bridge) con bonding formado de dos o más interfícies de red físicas. Al ser creado como un puerto tendrá los mismos atributos que hemos visto para los puertos.

ovs-vsctl add-bond <bridge> <bond_port> <if1> <if2> ...

Por ejemplo si quisieramos crear un bonding sobre las interfícies eth0 y eth1

ovs-vsctl add-bond br01 bond0 eth0 eth1

Para ver el estado del bonding, ejecutamos:

ovs-appctl bond/show bond0

Un puerto esta formado por una o mas interfícies, en los puertos con bonding estan formados por mas de una. Una interfície puede ser mapeada a una interfície de red física de la máquina o a una interfície correspondiente de una maquina virtual. Para ver las interfícies:

ovs-vsctl list interface

O con:

ovs-vsctl show

también vemos toda la estructura de interfícies y bridges a los que estan mapeadas.

Categories
General

Instalación de KVM y Open vSwitch en Ubuntu


Después de un primer post de introducción de la serie Open vSwitch dónde vimos las virtudes de éste, vamos a ver el proceso de instalación en Ubuntu 12.04, en este post vamos a instalar Open vSwitch y KVM.

Instalación inicial y configuración:

Nos loggeamos cómo usuario root y actualizamos la lista de los repositorios y el sistema operativo:

# apt-get update
# apt-get dist-upgrade

Instalamos KVM y libvirt:

# apt-get install qemu-kvm libvirt-bin virtinst virt-manager virt-viewer

Instalamos los paquetes para el manejo de redes:

# apt-get install openvswitch-controller openvswitch-brcompat \ 
openvswitch-switch openvswitch-datapath-source vlan

En nuestro caso, veremos más adelante cómo almacenaremos las imágenes de maquina virtuales en NFS, así que instalamos el paquete necesario para el cliente:

# apt-get install nfs-common

Editamos el fichero /etc/default/openvswitch-switch y descomentamos y cambiamos la linea dónde pone:

#BRCOMPAT=no

la cambiamos por:

BRCOMPAT=yes

Borrado de bridges por defecto y puesta en marcha

Vamos a borrar los bridges que nos crea el KVM por defecto:

# virsh net-destroy default
# virsh net-autostart --disable default

Boramos el paquete ebtables:

# apt-get purge ebtables

Eliminamos el modulo bridge del kernel, ya que el del openvswitch y éste no pueden correr juntos en el kernel, tener en cuenta que si en el fichero de configuración de redes tenemos algún bridge configurado, al reiniciar la máquina se cargará el modulo bridge y no nos será posible iniciar el servicio del openvswitch.

# rmmod bridge
# service openvswitch-switch start

Vemos si nos ha cargado el modulo del openvswitch

# lsmod | grep brcom

Esto debería darnos una salida similar a la siguiente:

brcompat_mod           13512  0
openvswitch_mod        83993  3 brcompat_mod

Llegados a este punto ya tenemos el Open vSwitch instalado y preparado para funcionar. En futuros posts veremos como crear bridges y agregar puertos a estos tanto para la máquina física como para las maquinas virtuales