martes, mayo 24, 2011

Virtualización con Kernel-based Virtual Machine KVM

KVM es una solución de virtualización que se apoya en Qemu como software de virtualización y en unos módulos del kernel para aprovechar los registro VT en procesadores Intel y SVM en los AMD.

Lo primero que haremos será configurar estos módulos en nuestro kernel:
Virtualization --> Kernel-based Virtual Machine (KVM) support --> KVM for Intel processors support

NOTA: En mi caso se trata de un microprocesador de Intel.

Instalamos las aplicaciones a nivel de usuario, para que la gestión de las máquinas virtuales sea mas cómoda también vamos a instalar una utilidad de gestión:
apt-get install qemu-kvm aqemu

Desde aqemu debe ser posible acceder a diferentes funcionalidades de Linux que solo es posible acceder con permisos de root, se pueden cambiar los permisos de diferentes dispositivos pero los mas fácil es editar los comandos permitidos por sudo:
visudo
"usuario" ALL=(root)NOPASSWD: /usr/bin/aqemu

KVM tiene el tema de gestión de red un poco verde, si tenemos una tarjeta de red ethernet no hay problema, tan solo habrá que generar un bridge de la tarjeta cableada pero si la tarjeta de red es inalámbrica en principio esto no es posible, a continuación explicaré como resolver cada uno de los escenarios.

Instalamos el software necesario:
apt-get install uml-utilities parprouted bcrelay

Red cableada:

Para que las máquinas virtuales puedan integrarse en nuestra red cableada es necesario crear un bridge entre nuestra tarjeta de red ethernet y una interfaz tap.

Generamos la interfaz y la levantamos:

tunctl -t tap0
ifconfig tap0 up

Creamos el bridge y le añadimos la interfaz ethernet y la virtual:
brctl addbr br0
brctl addif br0 eth0
brctl addif br0 tap0

Reconfiguramos la interfaz ethernet para que no posea ninguna dirección IP y le asignamos una al bridge:

ifconfig eth0 0.0.0.0
dhclient br0


Ahora asociamos nuestra tap0 a la máquina virtual:
Connection mode: Open a TUN/TAP interface
TUN/TAP Script Deshabilitado
Interface name: tap0

Nuestra máquina virtual ya se comportará como si se tratase de un equipo físico conectado a la red ;)

Red wireless:

En la red wireless debemos hacer dos distinciones según el método de asignación de direcciones IP a las máquinas virtualizadas:

IP estática:

Habilitamos el enrutado en el kernel:
echo 1 > /proc/sys/net/ipv4/ip_forward

Generamos una interfaz TAP:
tunctl -t tap0
ifconfig tap0 up

Le asignamos una ip de nuestra red:
ifconfig tap0 192.168.1.100

Con Parprouted conseguiremos hacer magia, se trata de un proxy ARP a nivel 3 ;))
parprouted wlan0 tap0

Añadimos una ruta estática para la máquina virtual:
route add -host 192.168.1.200 dev tap0

Ahora configuramos la máquina virtual en qemu:
Connection mode: Open a TUN/TAP interface
TUN/TAP Script Deshabilitado
Interface name: tap0

Dentro de la máquina virtual se configurará la direcciín IP de forma estática indicandole la IP: 192.168.1.200

Con esto la máquina virtual se podrá comunicar con Internet y con la máquina anfitrión.


IP dinámica:

Habilitamos el enrutado en el kernel:
echo 1 > /proc/sys/net/ipv4/ip_forward

Generamos una interfaz TAP:
tunctl -t tap0
ifconfig tap0 up

Le asignamos una ip de nuestra red:
ifconfig tap0 192.168.1.100

Habilitamos el proxy ARP de capa3:
parprouted wlan0 tap0

Parprouted tiene un inconveniente y es que solo permite el paso de tráfico unicast por el bridge, por lo tanto las peticiones DHCP serán capadas, pero existe la herramienta bcrelay que solventa este problema:
bcrelay -i tap0 -o wlan0 &

Ahora configuramos la máquina virtual en qemu:
Connection mode: Open a TUN/TAP interface
TUN/TAP Script Deshabilitado
Interface name: tap0

Dentro de la máquina virtual se configurará la dirección IP de forma dinámica.


NOTA: Las direcciones IP para las interfaces TAP he decidido que empiezen por la 100 y las IPs de las máquinas virtuales a partir de la 200, estos rangos son totalmente arbitrarios, yo los elegí porque son rangos libre de mi direccionamiento

Para cada máquina virtual habrá que añadir una interfaz tap distinta ocupando una ip de nuestra red :(
Si queremos que las máquinas virtuales puedan comunicarse entre ellas habrá que "bridgearlas" entre ellas:
parprouted tap0 tap1

De este modo nos podremos olvidar de los tediosos problemas que dan Vmware y VirtualBox cuando recompilamos el kernel, módulos que no compilan o ñapas en el código......

NOTA: Si se configura una máquina virtual Linux para que pida dirección por DHCP no funciona, este es un tema en el que seguiré indagando.

Dejo estos scripts para que todo sea automático, nos generará un TAP por máquina vritual, le asignará un IP y la meterá en un bridge junto con el resto de máquinas consiguiendo que todos puedan verse con todos y además tengan acceso a Inet ;), además el script configura de forma automática las intyerfaces con bcrelay.

Para que funcionen tendremos que definir algunas variables en AQemu_UP.sh

- AQemu_UP.sh
#!/bin/bash
clear
echo "|---------------------------------------|"
echo "| Script configuracion interfaces AQemu |"
echo "| By Kr0m V0.1b |"
echo "|---------------------------------------|"
echo " "
echo " "


rm -rf /tmp/TAPS 2>/dev/null
rm -rf /tmp/IP_VM 2>/dev/null

DIR_AQEMU=/mnt/datos/AQemu
N=0
RED_TAP=192.168.1.
IP_TAP=100
RED_VM=192.168.1.
echo $RED_VM > /tmp/RED_VM
IP_VM=200
echo $IP_VM > /tmp/IP_VM
WIFI=wlan0

echo 1 > /proc/sys/net/ipv4/ip_forward

for i in $DIR_AQEMU/*.aqemu
do
#echo i: $i
#echo N: $N
#echo IP_TAP: $IP_TAP
#echo IP_VM: $IP_VM
tunctl -t tap$N
ifconfig tap$N up
ifconfig tap$N $RED_TAP$IP_TAP
route add -host $RED_VM$IP_VM dev tap$N
bcrelay -i tap$N -o $WIFI &
let N=$N+1
let IP_TAP=$IP_TAP+1
let IP_VM=$IP_VM+1
done

N=$((N-1))
#echo N: $N
parprouted $WIFI $(for t in $(seq 0 $N); do echo tap$t; done)

echo $N > /tmp/TAPS

echo " "
echo " "
echo "---------- INTERFACES DE RED ---------------"
ifconfig

echo " "
echo "---------- TABLA DE RUTAS ------------------"
route -n

echo " "
echo "---------- PROCESOSO ARRANCADOS ------------------"
ps aux | grep bcrelay | grep -v grep
ps aux | grep parprouted | grep -v grep


- AQemu_DOWN.sh
#!/bin/bash
clear
echo "|---------------------------------------------|"
echo "|Script eliminacion interfaces AQemu |"
echo "|---------------------------------------------|"
echo " "
echo " "

echo 0 > /proc/sys/net/ipv4/ip_forward

N=$(cat /tmp/TAPS)
for i in $(seq 0 $N)
do
ifconfig tap$i down
done

killall parprouted
killall bcrelay

echo " "
echo " "
echo "------------- INTERFACES DE RED ---------------"
ifconfig

echo " "
echo "------------- TABLA DE RUTAS ------------------"
route -n

echo " "
echo "------------- PROCESOS ARRANCADOS ------------------"
ps aux | grep bcrelay | grep -v grep
ps aux | grep parprouted | grep -v grep

NOTA: Estos scripts precisan de privilegios de root, para ello configuraremos sudo de tal modo que:
"usuario" ALL=(root)NOPASSWD: "ruta AQemu_UP.sh"
"usuario" ALL=(root)NOPASSWD: "ruta AQemu_DOWN.sh"

No hay comentarios: