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! 😉