.. _qemu-red: Red *** Dedicamos un epígrafe completo a la red, porque, amén de muy importante, es uno de los dispositivos que da más juego en su configuración. Al principio, :ref:`al proponer los alias ` para simplificar las órdenes, definimos una interfaz de red así: :code:`-netdev user,id=nic -device virtio-net,netdev=nic` donde vemos que intervienen dos opciones complementarias: :kbd:`-device`, que como ya venimos viendo con otro tipo de dispositivos define el dispositivo físico que se virtualiza; y :kbd:`-netdev`, que indica cómo se utilizará y que es dónde se encuentra fundamentalmente el meollo. En cuanto a la definición del dispositivo (:kbd:`-device`) es importante apreciar algunos aspectos: * El dispositivo escogido es un *virtio-net*, que `tiene mejor rendimiento `_ que emular completamente una tarjeta de red\ [#]_. Esto exige, no obstante, que el driver esté incluido en el sistema huésped. Es el caso de *Linux*, pero de los *Windows* (al menos los *Windows* 10). En el :ref:`apartado de red para Virtualbox ` hay nota con un enlace desde el que se puede descargar el controlador. * Sin embargo, el predeterminado es *e1000* que emula una tarjeta 82450EM de Intel, porque es más probable que el sistema anfitrión la soporte sin necesidad de instalar ningún *hardware*. * :kbd:`netdev=` permite referir el identificador incluido con :kbd:`id=` en la opción :kbd:`-netdev` asociada. * Si disponemos varias tarjetas o arrancamos varias máquinas virtuales que comparten red, es importante que especifiquemos su dirección |MAC|, porque :program:`QEmu` **siempre asigna la misma**: *52:54:00:12:34:56*. Para ello, basta añadir la dirección al argumento de la opción: :code:`-device virtio-net,netdev=nic,mac=54:52:00:12:34:57`. .. warning:: Todas las configuraciones se hacen usando *virtio-net*, pero para que realmente sea ventajosa para el rendimiento su elección, es necesario también que :ref:`se habilite el uso del módulo vhost_net `. Podemos pues seguir sin preocuparnos de esto último, pero es conveniente, una vez que se controle bien cómo configurar la red, que se remate habilitándolo. Con esto es suficiente para declarar el dispositivo virtual. :kbd:`-netdev` es otra historia que requiere un cuento bastante más largo. .. todo:: Probar (como es probable que así sea) que se necesita fijar a **1** :kbd:`net.ipv4.ip_forward` para que el tráfico proviniente de los huéspedes puede acceder al exterior. .. _qemu-red-usuario: Red de usuario ============== Es la configuración de la interfaz que :ref:`Virtualbox llama NAT ` y por defecto crea :program:`QEmu`, si no la deshabiltamos con la opción :kbd:`-nodefaults`. Su definición es la mostrada arriba: :code:`-netdev user,id=nic` donde :kbd:`id` refiere el identificador al que se hará en el :kbd:`-device` asociado. Esta es la configuración mínima que supone que la máquina virtual se encuentre en una red definida de la siguiente forma: * La dirección de red es *10.0.2.0/24*. * *QEmu* se encarga de traducir las peticiones al exterior como si se tratara de un *router* que hace enmascaramiento. La puerta de enlace que verá el *huésped* será la segunda |IP| disponible (en este caso, *10.0.2.2*); y el servidor |DNS|, la tercera (en este caso, *10.0.2.3*). * El sistema de la máquina virtual recibirá por |DHCP| otra |IP| de la red y tendrá conectividad con el exterior. * Una segunda máquina virtual se colocará en una red idéntica, pero no será la misma red, por lo que no existirá conectividad entre ambos huéspedes. * Funciona perfectamente el tráfico |UDP| y |TCP|, pero por un problema de privilegos no el |ICMP|, por lo que no podemos usar éste para comprobar conectividad. * Ningún puerto del sistema huésped estará expuesto. Aunque no suele ser necesario, existen distintos parámetros para alterar las características de esta red que pueden consultarse en el manual de :manpage:`qemu-system-x86_64`. Lo que sí es interesante es solucionar los dos últimos inconvenientes. .. _qemu-qemusers: |ICMP| Para ello lo más recomendable es crear un grupo en el anfitrión al que agreguemos todos los usuarios que utilicen :program:`QEmu` (lo cual será útil más adelante para otras tareas), y que permitamos a tal grupo generar tráfico |ICMP|:: # addgroup --system qemusers # adduser usuario qemusers # getent group qemusers qemusers:x:115:usuario # echo "115 115" > /proc/sys/net/ipv4/ping_group_range Este permiso es temporal y se perderá al apagar la máquina. Si queremos hacerlo permanente, en un sistema *Debian* podemos añadir una línea a :file:`/etc/sysctl.conf`:: # echo "net.ipv4.ping_group_range = 115 155" >> /etc/sysctl.conf y para no tener que reiniciar, podemos sólo por esta vez cargar su configuración:: # sysctl -p **Exposición de puertos** Tiene mucha utilidad si el huésped ofrece un servicio al que queremos acceder desde el anfitrión (p.e. el servicio |SSH|). Para ello, hay un parámetro (:kbd:`hostfwd`) que permite redirigir un puerto del anfitrión a uno del cliente. Por ejemplo: :code:`-netdev user,id=nic,hostfwd=tcp:127.0.0.1:10022-:22` permite acceder al servidor |SSH| del cliente a través del puerto **10022** del anfitrión. Para exponer más puertos, no hay más que escribir repetidamente el parámetro. Red de máquinas virtuales ========================= El propósito de este subapartado es solventar otra de las limitaciones de la red de usuario: la falta de conectividad entre los sistemas huéspedes. .. warning:: Tenga presente que por defecto :program:`QEmu` asigna la misma |MAC| a todas las máquinas virtuales, por lo que tendrá que especificar expresamente direcciones |MAC| distintas para cada una de ellas. Tenemos, al menos, dos alternativas: *socket* e interfaz puente. .. _qemu-red-socket: socket ------ Es la solución más sencilla que, además, no requiere permisos de administración, por lo que puede implementarla un usuario sin privilegios. Para configurar una interfaz basta con hacerlo del siguiente modo: :code:`-netdev socket,id=nic,mcast=230.0.0.1:12345` en donde usamos la dirección de multicast *230.0.0.1* y el puerto **12345**. Con que todas las máquinas que participen en esa red repitan esta configuración se encontrarán en la misma red. Por ejemplo, las siguientes dos máquinas se encontrarán dentro de la misma red interna:: $ qemu-system-vga -hda disco1.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:56 \ -netdev socket,id=nic,mcast=230.0.0.1:12345 $ qemu-system-vga -hda disco2.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:57 \ -netdev socket,id=nic,mcast=230.0.0.1:12345 En este caso se encontrarán aisladas y necesitaremos fijarles direcciones estáticas, puesto que no hay ningún servidor |DHCP| en esa red. Si quisiéramos comunicar esta red con el exterior bastaría con que una de ellas hiciera de router. Por ejemplo, la primera de ellas podríamos haberla levantado así: .. _qemu-red-router: :: $ qemu-system-vga -hda disco1.qcw -device virtio-net,netdev=nic0,mac=52:54:00:12:34:55 -netdev user,id=nic0 \ -device virtio-net,netdev=nic,mac=52:54:00:12:34:56 -netdev socket,id=nic,mcast=230.0.0.1:12345 Si tuviéramos necesidad de crear un segundo grupo de máquinas virtuales, bastaría con modificar la dirección de multicast, para que este grupo estuviera en una red diferente al primero. Por ejemplo:: $ qemu-system-vga -hda disco1.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:58 \ -netdev socket,id=nic,mcast=230.0.0.2:12345 $ qemu-system-vga -hda disco2.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:59 \ -netdev socket,id=nic,mcast=230.0.0.2:12345 .. todo:: Es interesante poder acceder directamente a esta red desde el anfitrión. El `blog de mcastelino propone una solución con socat `_ que no me acaba de funcionar. .. _qemu-red-tap: Puente ------ Esta alternativa sí requiere permisos de administrador, porque exige crear interfaces adicionales en el anfitrión. La idea es crear una :ref:`interfaz puente ` que contendrá interfaces virtuales *TAP* cada una de las cuales se asocia a una máquina virtual. De este modo, todas las máquinas virtuales compartirán la red. Antes de empezar debemos preparar el sistema. En primer lugar, delegaremos en :program:`Qemu` la tarea de crear las interfaces TAP y este hace uso del programita :file:`/usr/lib/qemu/qemu-bridge-helper`. Sin embargo, si utilizamos un usuario sin privilegios, éste no será capaz de crear las interfaces, así que primero lo ajustaremos para que tenga :ref:`esa capacidad `:: # setcap 'cap_net_admin=ep' /usr/lib/qemu/qemu-bridge-helper Además, el programa limita las interfaces puente a las que puede añadir las interfaces TAP que crea, así que debemos decir a cuáles se permite incluyéndolas en el archivo :file:`/etc/qemu/bridge.conf`:: # mkdir -p /etc/qemu # echo "allow all" > /etc/qemu/bridge.conf Preparado el sistema, ya podemos indicar qué se debe hacer cada vez que se quiere crear una red mediante esta estrategia. Lo primero es crear una interfaz puente:: # ip link add name vmnet0 type bridge # ip link set vmnet0 up y, creada, ya podemos arrancar un par de máquinas virtuales dentro de una misma red:: $ qemu-system-vga -hda disco1.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:56 -netdev bridge,id=nic,br=vmnet0 $ qemu-system-vga -hda disco2.qcw -device virtio-net,netdev=nic,mac=52:54:00:12:34:57 -netdev bridge,id=nic,br=vmnet0 :program:`QEmu`, a través de :program:`qemu-bridge-helper`, se encargará de crear sendas interfaces TAP e incluirlas dentro del puente *vmnet0*. Cuáles sean en concreto estas interfaces, nos es indiferente, aunque para escoger nombre para ellas el programita toma *tapN* donde *N* es el número más bajo que haga que el nombre esté libre. Así, en principio, será *tap0*, pero si esta interfaz ya existe en el anfitrión, creará *tap1*. Como en el caso de :ref:`socket `, la red estará aislada y las interfaces virtuales del huésped no recibirá una dirección |IP| dinámica. No obstante, para conectarla con el exterior podemos utilizar uno de los huéspedes como *router*, de modo análogo a como :ref:`ya se hizo cuando ilustramos la red con socket `. .. note:: Obviamente, si quisiéramos crear un segundo grupo de máquinas en un red distinta, bastaría con crear una interfaz puente distinta (p.e. *vmnet1*) y asociar tales máquinas a ella. Es posible que, cuando las máquinas estén en funcionamiento, queramos poder establecer conexión con ellas directamente desde el anfitrión. Para ello, no tenemos más que dar a la interfaz puente (*vmnet0* en este caso) una |IP| de la red en la que hayamos situado a los sistemas huéspedes. Por ejemplo, si en los sistemas huéspedes fijamos direcciones de la red *192.168.255.0/24*, bastará con:: # ip addr add 192.168.255.5/24 dev vmnet0 suponiendo que tal |IP| está libre. Al apagar las máquinas, las interfaces TAP creadas se borrarán automáticamente. Por tanto, lo único que restará, será eliminar el puente:: # ip link del vmnet0 .. seealso:: Exploraremos la posibilidad de automatizar la creación de las interfaces necesarias en el epígrafe en que proponemos un :ref:`script de arranque `. .. http://www.kaizou.org/2018/06/qemu-bridge.html Adaptador puente ================ El propósito bajo el epígrafe es lograr un huésped cuya interfaz de red se encuentre en la misma red que el anfitrión (o sea, la :ref:`configuración que Virtualbox denomina adaptador puente `). Esto se logra asociando a la interfaz real del anfitrión la interfaz virtual que utilice el huésped. Tenemos al menos dos alternativas: - Utilizar una :ref:`interfaz TAP como ya hemos visto ` dentro de un puente en el que también esté incluida la interfaz física del anfitrión. - Echar mano de las interfaces *macvlan*. .. _qemu-red-puente-tap: Puente ------ Esta alternativa exige que ya tengamos preparado el anfitrión, y hayamos agregado la interfaz física a un puente. En *Debian* esto se traduciría en una configuración dentro de :file:`/etc/network/interfaces` semejante a esta:: # Interfaz física. allow-hotplug eth0 iface eth0 inet manual up ip link set $IFACE up down ip link set $IFACE down # Interfaz puente en que se incluye la anterior auto br0 iface br0 inet dhcp bridge_ports eth0 bridge_maxwait 2 donde suponemos que el anfitrión recibe una |IP| dinámicamente. Con esta situación, el puente ya está creado de antemano, con lo que para arrancar una máquina en la misma red que la del anfitrión no habrá más que hacer lo siguiente:: $ qemu-system-vga -hda disco.qcw -device virtio-net,netdev=nic -netdev bridge,id=nic,br=br0 supuesto, claro está, que hayamos preparado :file:`/usr/lib/qemu/qemu-brigde-helper`, como se explicó en el epígrafe anterior, para que sea capaz de crear las interfaces TAP. .. _qemu-red-puente-macvtap: MACVLAN ------- La otra alternativa es más eficiente y, en principio, no exige configurar la interfaz física del anfitrión de un modo especial. Simplemente, antes de arrancar la máquina deberemos preparar una interfaz derivada del siguiente modo:: # ip link add link eth0 name macvtap0 address 52:54:00:12:34:56 type macvtap mode bridge # ip link set macvtap0 up La primera orden creará un dispositivo de caracteres :file:`/dev/tapN` donde *N* es un número que puede consultarse en :file:`/sys/class/net/nombre_interfaz/ifindex`. El problema es que el usuario deberá poder leer y escribir en él, si queremos que funcione este método. Para ello podemos cambiar los permisos cada vez que creamos una nueva interfaz:: # chgrp qemusers /dev/tap$(> /etc/udev/rules.d/55-qemuperm.rules KERNEL=="tap*", ACTION=="add", GROUP="qemusers", MODE="0660" .. note:: Hemos supuesto que hemos creado un grupo *qemusers* donde se encontrarán todos los usuarios que usen :program:`QEmu` tal como sugerimos para :ref:`resolver el ping en una red de usuario `. Preparado el sistema, podremos arrancar la máquina de este modo:: $ qemu-system-vga -hda disco.qcw -device virtio-net,netdev=nic,mac=$(/dev/tap$(`. .. |TCP| replace:: :abbr:`TCP (Transmission Control Protocol)` .. |UDP| replace:: :abbr:`UDP (User Datagram Protocol)` .. |ICMP| replace:: :abbr:`ICMP (Internet Control Message Protocol)` .. |MAC| replace:: :abbr:`MAC (Media Access Control)`