Cap�tulo 1. Virtualizaci�n y redes

Tabla de contenidos

Virtualizaci�n en GNU/Linux
VMWare y la red
Qemu y TUN/TAP
Ejemplos
Instalar QEMU
Crear una imagen con Qemu
Listados de ejemplos de TUN/TAP

Virtualizaci�n en GNU/Linux

Mediante la virtualizaci�n en una sola m�quina es posible tener varios sistemas, como si en lugar de un PC tuvi�ramos varios. As�, un ISP que ofrezca servidores dedicados puede ofrecer varios servidores virtuales sobre una m�quina: cada uno funcionar� como un servidor independiente con su propia IP, se podr�n instalar todo tipo de servicios (DNS, mail, Jabber, web, PostgreSQL) y reiniciar y administrar independientemente.

Al sistema sobre el que se ejecuta el virtualizador se le llama host; a veces tambi�n se habla de domain 0, porque cada sistema que se ejecuta se le considera un dominio. A cada uno de los sistemas que se ejecutan sobre el virtualizador se les denomina guest. En algunos casos no hay sistema host porque el virtualizador se ejecuta directamente sobre el hardware.

Hay hardware como los mainframes de IBM, que soportan virtualizaci�n. Los Pcs no soportan virtualizaci�n: hay instrucciones de modo protegido que impiden ejecutar dos sistemas operativos simult�neamente, pero mediante software se pueden suplir (con bastante complejidad) las carencias de hardware. As� mismo mediante sofware se emulan componentes del hardware como discos, tarjeta gr�fica, de red y de sonido.

Adem�s de la virtualizaci�n de la CPU, est� la del resto del hardware: tarjeta de red, discos, tarjeta gr�fica... Para esta parte la mayor�a de los proyectos libres toman c�digo de Qemu.

Hay varios m�todos de implementar la virtualiaci�n del procesador:

  1. Emuladores totales: emulan totalmente el hardware, incluyendo el procesador. Es el caso de Booch. Su rendimiento es muy pobre.

  2. Emuladores con compilaci�n JIT: es el caso de Qemu, cuando se ejecuta sin el m�dulo kqemu. El c�digo necesita "compilarse" para la m�quina virtual, si bien como los compiladores JIT de Java se hace s�lo la primera vez que se ejecuta el c�digo, luego ya est� compilado. Mucho m�s r�pidos que los emuladores totales, pero m�s lentos que el resto de soluciones. Se puede ejecutar como usuario normal sin instalar nada como root. Se pueden emular procesadores distintos.

  3. Virtualizadores completos: es el caso de Vmware (software privativo), Qemu con el m�dulo de aceleraci�n Kqemu (antes privativo ahora libre) y Virtual Box (software con una versi�n libre y otra m�s funcional privativa). Se basan en un VMM (Virtual Machine Monitor, tambi�n conocido como hypervisor) que mediante complicadas t�cnicas (como traps y an�lisis del c�digo antes de su ejecuci�n) detecta en tiempo de ejecuci�n el c�digo que no puede ejecutarse directamente porque afectar�a a todo el sistema, modificando din�micamente las instrucciones conflictivas. El rendimiento var�a mucho seg�n lo avanzado que sea el VMM: Vmware tiene varias patentes. Estos tres programas permiten instalar un sistema operativo sobre un virtualizador del mismo modo que sobre un PC: la ventana del virtualizador asemeja el monitor de un PC, podemos entrar en la BIOS, reiniciar el ordenador...

  4. Paravirtualizadores: es el caso de Xen y UML (User mode Linux). En lugar de tener que detectar un VMM los casos conflictivos en tiempo de ejecuci�n, se modifica el c�digo fuente de los sistemas operativos para evitar esos casos conflictivos. En lugar de el VMM tener que analizar el c�digo, es el c�digo quien invoca al VMM cuando sea necesario. Esta t�cnica simplifica much�simo el VMM y ofrece muy buen rendimiento, aunque en el caso concreto de UML el rendimiento es mediocre. La pega es que haya que parchear el sistema operativo, sobre todo para poder ejecutar Windows. Xen parche� un Windows XP en un programa de investigaci�n que permit�a acceso al c�digo fuente de Microsoft, pero ese tipo de licencias no permit�a distribuir el resultado. UML tambi�n se puede considerar dentro de esta categor�a, pues es una modificaci�n del kernel de Linux para que pueda ejecutarse dentro de otro Linux. Xen no emula una tarjeta gr�fica SVGA "completa" como Qemu, Vmware o VirtualBox, pero utiliza VNC que para el sistema guest se ve como una tarjeta VGA.

    Vmware y VirtualBox no son paravirtualizadores, pero utilizan esta t�cnica para virtualizar la E/S en los drivers especiales que se ejecutan en el sistema guest (por ejemplo el driver de red y el de la tarjeta gr�fica: se comunican con el hipervisor en lugar de ser drivers normales sobre el hardware emulado). Lo mismo planea hacer KVM.

  5. Virtualizadores apoyados en el hardware (un tanto pretenciosamente llamados nativos): los nuevos procesadores de Intel (los Core Duo y la mayor�a, pero no todos, ver la wikipedia, de los Core Duo2 a�aden las extensiones VT) y los m�s recientes de AMD (a partir de stepping F; las extensiones se llaman SVM) cuentan con nuevas instrucciones que permiten la virtualizaci�n de la CPU. De este modo ya no es necesario ni un complicado VMM ni parchear el sistema operativo, si bien sigue siendo necesario virtualizar otros dispositivos y emular discos, tarjetas gr�ficas, de red... Ejemplos de estas soluciones son KVM (integrado en el kernel desde la versi�n 2.6.20, utiliza qemu para la virtualizaci�n del resto del hardware) y Virtual Iron (basado en Xen, pero ya no es paravirtualizador; en cualquier caso es una soluci�n propietaria, con algo de c�digo bajo GPL). Adem�s Xen soporta tambi�n estas instrucciones, como m�todo para poder ejecutar Windows o simplemente sistemas sin paravirtualizar. Los virtualizadores apoyados en el hardware son m�s lentos que los paravirtualizadores e incluso que los virtualizadores completos, al menos que los que tienen un VMM avanzado. VirtualBox no usa por defecto estas instrucciones, aunque las soporte, por este motivo. Lo mismo ocurre con Vmware, aunque s� lo utiliza para poder utilizar como host un sistema operativo de 64bits (VirtualBox actualmente no permite esta configuraci�n).

  6. Virtualizaci�n a nivel de sistema operativo (OS level Virtualization): no permite ejecutar dos sistemas operativos simult�neamente, sino servidores privados virtuales (SVP) dentro de un �nico servidor, es decir, es un �nico kernel, pero que permite aislar (isolate) los servidores. Cada servidor tendr� su propia red, espacio de disco, de memoria, se podr� reiniciar.. as� mismo tendr� limitaci�n de uso de CPU con el fin de evitar que un servidor virtual esquilme recursos de los otros. Tambi�n esta tecnolog�a se denomina como Jail, pues es extender el concepto de chroot. Tantao Linux VServer como Virtuozzo lo vienen ofreciendo proveedores de hosting desde hace a�os. Estas son las dos soluciones libres m�s destacadas:

    1. Linux VServer: http://linux-vserver.org (no confundir con linux virtual server, que es sobre clusters). Software libre. Una limitaci�n es que no admite usar iptables dentro de cada SVP, sino dentro del host. Tampoco admite migraci�n de procesos. As� mismo est� m�s limitado en lo que se virtualiza, por ejemplo no se virtualiza nada de /proc). Por otro lado la distribuci�n host parece menos restringida que en OpenVZ, que como host s�lo admite Fedora, algunas versiones de CentOS y algunas de RHEL. Hay varias distribuciones que funcionan como guest directamente (las instalamos en su partici�n y luego las usamos, con sus programas y librer�as, pero no obviamente con su kernel) aunque otras como Gentoo no.

    2. OpenVZ (http://openvz.org). Virtuozzo es un virtualizador bajo una licencia privativa; OpenVZ es el producto de la misma compa��a que es software libre y que es la base de Virtuozzo. Un hecho positivo es que OpenVZ no es un conjunto de c�digo GPL dif�cil de integrar y sin soporte como ocurre con otros productos en los que hay versi�n GPL y privativa: tambi�n venden soporte para OpenVZ. Admite distintas distribuciones como host, a trav�s de templates, que son repositorios para bajar los paquetes necesarios para esa distribuci�n. Hosting con OpenVZ: http://www.vpslink.com/vps-hosting/. En alg�n caso es m�s caro con OpenVZ que con Virtuozzo, por ser menos maduro y requerir m�s recursos...

Entre las posibilidades m�s avanzadas de algunos virtualizadores est� el migrar en caliente con una indisponibilidad inapreciable un dominio de un servidor a otro. Dentro de los productos libres lo permiten Xen, KVM y OpenVZ. Vmware lo permite s�lo en su servidor de pago (EXS). En Vmware Server (antiguo Vmware GSX), ahora gratis (que no libre) no es posible. Para saber m�s sobre este tema: http://kvm.qumranet.com/kvmwiki/Migration

Un debate interesante es el de los virtualizadores que se ejecutan "bare metal", es decir, directamente sobre el hardware, en lugar de sobre un sistema operativo "host". Vmware EXS sigue esta f�rmula de forma pura, de tal modo que s�lo funciona con determinado hardware. En el caso de Xen, se ejecuta sobre un host, pero asume parte de las funciones de un sistema operativo, al tener c�digo por ejemplo para planificar la CPU. En cambio KVM utiliza todo lo que aporta Linux, lo que para muchos desarrolladores es la opci�n preferible pues dif�cilmente una empresa que desarrolla un producto de virtualizaci�n tendr� m�s experiencia en elementos de sistemas operativos como un planificador, que el grupo de personas que llevan desarrollando estos componentes desde hace a�os en un sistema tan extendido como el kernel Linux.

Software interesante:

http://virt-manager.et.redhat.com/ interfaz gr�fica sobre todo para Xen, pero tambi�n soporta

KVM y Qemu. Incluye parte para gestionar redes.

Informaci�n muy completa (navegar por los enlaces del marco de la izquierda):

http://virt.kernelnewbies.org/TechOverview

VMWare y la red

En VMWare a la hora de crear un dispositivo de red se puede elegir entre:

  1. NAT: en el host aparecer� como la interfaz vmnet8, pero no podremos hacer nada con esta interfaz, por ejemplo usar Iptables para restringir las Ips que se pueden alcanzar desde el sistema que se ejecuta dentro de Vmware. El motivo es que no se usa realmente el NAT del n�cleo sino un demonio, vmnet-natd, por lo que los paquetes no pasan realmente por vmnet8. Si se quiere abrir puertos, basta con editar el fichero /etc/vmware/vmnet8/nat.conf

  2. Bridge: tambi�n se implementa utilizando un demonio privativo, en este caso vmnet-bridge, en lugar de utilizar el soporte del n�cleo, por lo que no se puede restringir la red con iptables sobre la interfaz vmnet2. Como en el caso de vmnet8, realmente el tr�fico no pasa por esta interfaz.

  3. Host only: aparentemente este modo es el m�s limitado. Pues bien, en realidad es el m�s flexible, pues por la interfaz de red que crea, vmnet1, s� que pasan todos los paquetes. De este modo podemos utilizar esta interfaz para hacer NAT a trav�s de iptables, o crear un bridge con brctl. Al usar iptables, podemos restringir el tr�fico como con cualquier otra unidad de red.

En Qemu hay dos formas de utilizar la red. Por defecto se usa -net socket, que ser�a el equivalente al modo NAT de Vmware. Mediante la opci�n -redir se pueden abrir puertos de servidor. Una diferencia interesante sobre Vmware es que esta soluci�n se implementa enteramente en espacio de usuario, por lo que no se crea interfaz de red ni se precisa cargar ning�n m�dulo del kernel, lo que es bueno porque en el caso de Vmware es un m�dulo privativo que activa la marca "tained" del k�rnel, con lo que perdemos toda opci�n de soporte. Adem�s as� no hay que tener privilegios de superusuario para instalar Qemu (Vmware no requiere privilegios para ejecutarse, pero s� hace falta para insertar el m�dulo en el kernel).

Las interfaces de red vmnet1, vmnet2, vment8, se crean al ejecutar vmware-config, en la parte de configuraci�n de red. Una posibilidad interesante si vamos a ejecutar varios sistemas simult�neamente o si queremos que un sistema tenga m�s de una interfaz es crear m�s de un dispositivo de red para "host only", de modo que aparte de vmnet1 haya otros. De otro modo todas las m�quinas virtuales estar�n conectadas a la misma red, la de vmnet1. As�, una m�quina podr� tener la IP 192.168.152.128, otra la 192.168.152.129 y el host la 192.168.152.1; las dos m�quinas virtuales se ver�n la una a la otra y podr�n comunicarse, aunque eso s�, con un sniffer una m�quina no ver� el tr�fico de los otros nodos.

La red vmnet1 que crea Vmware es de m�scara de red 255.255.255.0; ejecuta un servidor DHCP autom�ticamente, cuya configuraci�n y arrendamientos pueden verse en /etc/vmware/vmnet1. Pero nada impide que podamos cambiar esta configuraci�n, pues se emula a una interfaz ethernet. Por ejemplo un nodo puede cambiar su IP a otra de la red o incluso crear un alias y usar una red distinta, tanto en el host como en las m�quinas virtuales.

Si usamos vmnet1 para hacer NAT utilizando iptables, hay que tener en cuenta que habr� que configurar la red de la m�quina virtual para a�adirle una ruta por defecto y la configuraci�n del DNS y que el firewall deber� permitir que llegue al servidor DNS. Para pasar la configuraci�n de DNS y ruta por defecto podemos usar el servidor DHCP de Vmware: "option routers" y "option domain-name-servers".

Qemu y TUN/TAP

Un inconveniente de -net socket es que como ocurre con los modos NAT y Bridge de Vmware los paquetes no pasan por ninguna interfaz de red, por lo que no se puede utilizar iptables para restringir la red.

La soluci�n est� en el uso del soporte de TUN/TAP del kernel. Consiste en que una aplicaci�n puede abrir el fichero de dispositivo /dev/net/tun y con eso crear una nueva interfaz de red (por defecto tun0). Todo lo que la aplicaci�n escriba en ese dispositivo se recibir� en la interfaz de red reci�n creada; de igual modo todo lo que llegue a esa interfaz de red (por ejemplo a trav�s de enrutamiento) lo leer� la aplicaci�n del fichero de dispositivo.

Los dispositivos TUN operan a nivel IP y son punto a punto. Los dispositivos TAP operan a nivel 2 y son multipunto, como las interfaces eth*. Un dispositivo tap0 y un dispositivo vmnet1 vienen a funcionar de forma muy similar y a nivel de ejemplos de configuraci�n con iptables o brctl donde aparezca un tap0 podr�a aparecer un vmnet1 y viceversa. Por lo general se usa tun0 en lugar de tap0; para la mayor�a de los usos son equivalentes por lo que es mucho m�s habitual utilizar tun0 que resulta m�s sencillo y directo.

Normalmente un dispositivo tun/tap s�lo existe mientras el programa no cierra el fichero /dev/net/tun. Esto a veces es problem�tico, especialmente porque para crear un dispositivo TUN/TAP hacen falta privilegios de superusuario. Afortunadamente, con root se puede abrir un dispositivo en modo persistente para un determinado usuario, de modo que luego un programa ejecutado por ese usario sin privilegios podr� abrir ese dispositivo tun/tap creado para �l por el root. Este se puede hacer con el programa tunctl, que forma parte del paquete uml-utilities.

�Por qu� no usa Vmware TUN/TAP en lugar de vmnet1? quiz�s por unicidad entre plataformas, o por diferencia de implementaci�n; es posible que vmnet1 tambi�n permita driver de red de la m�quina virtual directamente en espacio del kernel.

TUN/TAP es la soluci�n utilizada tambi�n por otros virtualizadores, como Virtual Box. Muy interesantes los documentos sobre red avanzada en la web de Virtual Box: http://www.virtualbox.org/wiki/User_HOWTOS.

Ejemplos

Permitir acceso s�lo a red local 192.168.10.0 y adem�s excluir el nodo 9 de esa red.

iptables -A FORWARD -i vmnet1 --destination 192.168.10.9 -j REJECT

iptables -A FORWARD -i vmnet1 --destination 192.168.10.0/24 -j ACCEPT

iptables -A FORWARD -i vmnet1 -j REJECT

iptables -t nat -A POSTROUTING -j MASQUERADE -o eth0

echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding

echo 1 > /proc/sys/net/ipv4/conf/vmnet1/forwarding

Crear un bridge, pero prohibiendo el acceso a la IP 157.88.10.20. Se puede filtrar con ebtables o con iptables.

Ojo, muchas tarjetas wireless no soportan bridge. Un AP generalmente s�.

ifconfig eth0 0.0.0.0

ifconfig vmnet1 0.0.0.0

brctl addbr puente

brctl addbr puente

brctl addif eth0

brctl addif vmnet1

ifconfig puente 192.168.10.1

iptables -O FORWARD -m physdev --physdev-in vmnet1 --destination 157.88.10.20 -j REJECT

Instalar QEMU

Para compilar kqemu no hace falta versi�n vieja de compilador gcc, ni las fuentes de qemu. Es bastante r�pido:

./configure

make

sudo make install

modprobe kqemu

Por defecto, necesitamos permisos de root para leer /dev/kqemu

  1. creamos grupo qemu: sudo addgroup qemu

  2. a�adimos nuestro usuario (jomar) al grupo: sudo gpasswd -a jomar qemu

  3. configuramos udev para que cree fichero de dispositivo con permisos para grupo qemu. Para ello editamos fichero /etc/udev/rules.d/60-kqemu.rules con este contenido: KERNEL=="kqemu", NAME="%k", MODE="0666", GROUP="qemu", RUN="/root/prueba.sh"

  4. hacemos lo propio con el fichero /dev/net/tun. A partir del kernel 2.6.18 no pasa nada por dar permiso para todo el mundo, pues nadie sin privilegios puede crear una nueva interfaz si no se ha creado antes por el root para ese usuario. Esto se puede hacer con la herramienta tunctl, que forma parte del paquete uml-utilities. Tambi�n se puede usar el programa que adjuntamos m�s adelante, cambiando el tipo de dispositivo de tun a tap. Para crear el dispositivo con tunctl se usa tunctl -u jomar -t tap0; para borrarlo tunctl -d tap0.

Ejemplos:

./qemu -net nic -net tap,script=no ~/linux-0.2.img -net nic,vlan=1 -net socket,vlan=1,listen=:8081 centos.qcow2

ifconfig tap0 up

ifconfig eth0

brctl addif puente tap0

ifconfig eth0 0.0.0.0

brctl addif puente eth0

ifconfig eth0 192.168.15.45

./qemu -net nic -net tap,script=no ~/centos.qcow2 -no-kqemu

Crear una imagen con Qemu

qemu-img create -f qcow2 centos.qcow2 3G

Con esta orden se crea una imagen de un disco de 3GB; en realidad con GNU/Linux este fichero no ocupa 3GB; el espacio sin usar del fichero no ocupa espacio en el disco.

Para arrancar del CD de instalaci�n podemos ejecutar:

qemu -kernel-kqemu -cdrom /home/jomar/centos1of6.iso -boot d -m 512 centos.qcow2

La opci�n -kernel-kqemu es para obtener la m�xima aceleraci�n: acelera tambi�n el c�digo del espacio del kernel; por defecto s�lo se acelera la de usuario. Si se produce alg�n problema, reintentaremos sin esta opci�n; si sigue habiendo problemas podemos probar con -no-kqemu a quitar incluso la aceleraci�n de espacio de usuario. Tras la instalaci�n, podemos probar a volver a utilizar aceleraci�n: a veces los posibles problemas s�lo se dan durante la instalaci�n, aunque esta situaci�n es m�s propia de Windows que GNU/Linux.

Con la opci�n -cdrom le indicamos que el CDROM es en realidad esa ISO; as� evitamos el tener que tostar un CD. Con la opci�n -boot d indicamos que arranque de CD en vez de disco duro. La opci�n -m 512 establece que la m�quina virtual tenga 512 MB de memoria. La cantidad de memoria puede cambiarse de una ejecuci�n a otra, pero hay que tener en cuenta que los instaladores suelen crear una partici�n de intercambio con el doble de la memoria RAM.

�C�mo cambiar de CD durante la instalaci�n? Con ctrl-alt-2 (ojo 1, no F1) pasamos al monitor, en el que ejecutamos el comando:

change cdrom /home/jomar/centos2of6.iso

Tras escribir la orden (qemu no indica ni errores ni que la operaci�n se ha realizado con �xito) volvemos a la pantalla de la m�quina virtual con ctrl-alt-1.

Una caracter�stica interesante de Qemu es que permite crear a partir de un fichero de imagen, otra imagen que s�lo contendr� los cambios que se produzcan en la primera, si la primera permanece sin modificar. Esta caracter�stica es �til por ejemplo para crear dos im�genes muy parecidas para hacer pruebas de redes entre las dos im�genes, sin que ocupe tanto en el disco.

qemu-img create -b xubuntu.qcow2 xubuntu1.qcow2

qemu-img create -b xubuntu.qcow2 xubuntu2.qcow2

Listados de ejemplos de TUN/TAP

Listado para usar el dispositivo creado para este usuario (en kernels viejos lo crea si no existe): muestra primer paquete que recibe, una salida similar a la de tcpdump -x -i tun0. Para probarlo configuramos con ifconfig el dispositivo tun0, usando pointtopoint para indicar una IP supuestamente destino; podemos hacer un ping a esa direcci�n y ver lo que recibe el programa.

Listado para crear como persistente el nodo:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/if_tun.h>
#include <linux/if.h>
#include <string.h>

int main() {
   struct ifreq ifr;
   int fd, err;
   char dev[IFNAMSIZ];

   fd = open("/dev/net/tun", O_RDWR) ;
   memset(&ifr, 0, sizeof(ifr));

   /* Flags: escoger entre IFF_TAP o IFF_TUN; opcionalmente
    * a�adir IFF_NO_PI
    * IFF_TAP   - Dispositivo TAP: Nivel ethernet (Layer2),           
    *             multipunto; �til para hacer bridge o para tr�fico no IP
    *             tambi�n para Qemu, pues usa TAP
    * IFF_TUN   - Dispositivo TUN: nivel IP (Layer3); punto a
    *             punto; la opci�n recomendada normalmente si
    *             s�lo trafico IP sin bridge
    * IFF_NO_PI - No a�adir a paquetes TUN informaci�n adicional
    *             antes del paquete. 
    */
    ifr.ifr_flags = IFF_TUN|IFF_NO_PI;
    if( *dev )
        strncpy(ifr.ifr_name, "tun0",5);
    err= ioctl(fd, TUNSETIFF, (void *) &ifr);
    if (!(err<0)) {
      // Hacer dispositivo persistente, es decir, que permanece
      // creado aunque se cierre dispositivo; normalmente el
      // dispositivo s�lo existe mientras est� abierto el
      // descriptor de fichero a /dev/net/tun.
      // Cambiar 1 por 0 para borrar un dispositivo persistente.
      err= ioctl(fd, TUNSETPERSIST, 1);

      // Poner como due�o del dispositivo al UID 1000; de este
      // modo puede crear dispositivo proceso ejecutado por
      // usuario con este UID en lugar de root, si adem�s tiene
      // permiso de lectura y escritura sobre /dev/net/tun
      // antes de kernel 2.6.18 no era necesario hacer esto, pero
      // ahora ya s�. Con Qemu otra alternativa es hacer un
      // programa lanzador setuid que abra fichero, revoque
      // privilegios y lance Qemu pas�ndole handler abierto; o que
      // un programa con privilegio de root abra fichero y pase el
      // handler v�a un socket UNIX (ver man cmsg)
      if (!(err<0))
          err= ioctl(fd, TUNSETOWNER, 1000);
    }

    if( err<0) {
        perror("fall�");
        close(fd);
        return err;
    }
    strcpy(dev, ifr.ifr_name);
    printf("%s\n",ifr.ifr_name);
    return 0;
}

Programa para crear un dispositivo TUN/TAP persistente

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <linux/if_tun.h>
#include <linux/if.h>
#include <string.h>

int main() {
   struct ifreq ifr;
   int fd, err;
   char dev[IFNAMSIZ];

   fd = open("/dev/net/tun", O_RDWR) ;
   memset(&ifr, 0, sizeof(ifr));

   /* Flags: escoger entre IFF_TAP o IFF_TUN; opcionalmente
    * a�adir IFF_NO_PI
    * IFF_TAP   - Dispositivo TAP: Nivel ethernet (Layer2),           
    *             multipunto.
    *             �til para hacer bridge o para tr�fico no IP
    *             tambi�n para Qemu, pues usa TAP
    * IFF_TUN   - Dispositivo TUN: nivel IP (Layer3); punto a
    *             punto; la opci�n recomendada normalmente si
    *             s�lo tr�fico IP sin bridge
    * IFF_NO_PI - No a�adir a paquetes TUN informaci�n adicional
    *             antes del paquete. 
    */
    ifr.ifr_flags = IFF_TUN|IFF_NO_PI;
    if( *dev )
        strncpy(ifr.ifr_name, "tun0",5);
    err= ioctl(fd, TUNSETIFF, (void *) &ifr);
    if (!(err<0)) {
      // Hacer dispositivo persistente, es decir, que permanece
      // creado aunque se cierre dispositivo; normalmente el
      // dispositivo s�lo existe mientras est� abierto el
      // descriptor de fichero a /dev/net/tun.
      // Cambiar 1 por 0 para borrar un dispositivo persistente.
      err= ioctl(fd, TUNSETPERSIST, 1);

      // Poner como due�o del dispositivo al UID 1000; de este
      // modo puede crear dispositivo proceso ejecutado por
      // usuario con este UID en lugar de root, si adem�s tiene
      // permiso de lectura y escritura sobre /dev/net/tun
      // antes de kernel 2.6.18 no era necesario hacer esto, pero
      // ahora ya s�. Con Qemu otra alternativa es hacer un
      // programa lanzador setuid que abra fichero, revoque
      // privilegios y lance Qemu pas�ndole handler abierto; o que
      // un programa con privilegio de root abra fichero y pase el
      // handler v�a un socket UNIX (ver man cmsg)
      if (!(err<0))
          err= ioctl(fd, TUNSETOWNER, 1000);
    }

    if( err<0) {
        perror("fall�");
        close(fd);
        return err;
    }
    strcpy(dev, ifr.ifr_name);
    printf("%s\n",ifr.ifr_name);
    return 0;
}