Gestión de VMs Bhyve en FreeBSD con Iohyve


Iohyve es un gestor de máquinas virtuales Bhyve que hace uso de funcionalidades ZFS para ofrecer una experiencia de uso mas sencilla e intuitiva, entre sus características destacan la capacidad de realizar  snapshots, gestión de ISOs, servidor VNC integrado, clonado y backup de VMs. Se podría decir que es el equivalente a Iocage pero para VMs Bhyve, por otro lado si preferimos una interfaz unificada siempre podremos utilizar CBSD(2).

 

Este manual se compone de diferentes partes:


Instalación:

Instalamos todo lo necesario:

pkg install iohyve grub2-bhyve bhyve-firmware

Si tenemos mas de un zpool debemos indicarle a Iohyve cual de ellos utilizar:

zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
zroot   109G  78.5G  30.5G        -         -    44%    71%  1.00x  ONLINE  -
iohyve setup pool=zroot

La red Iohyve funciona mediante bridging, debemos indicarle la interfaz de red que queremos meter dentro del bridge, de este modo cuando creemos una VM se attacheará la interfaz tap de dicha VM al bridge existente:

iohyve setup net=em0

Permitimos que Iohyve cargue los módulos del kernel que necesite:

iohyve setup kmod=1

Para hacerlo permanente en el arranque del servidor podemos utilizar los parámetros RC siguientes:

sysrc iohyve_enable="YES"
sysrc iohyve_flags="kmod=1 net=em0"

Reiniciamos para asegurarnos de que todo se carga de forma automática:

reboot

Descarga de imágenes ISO:

Para realizar la instalación del SO necesitamos la imagen ISO de instalación, la bajamos mediante el comando fetchiso:

iohyve fetchiso https://cdimage.kali.org/kali-2020.3/kali-linux-2020.3-installer-amd64.iso

La renombramos para que sea mas fácil de escribir:

iohyve renameiso kali-linux-2020.3-installer-amd64.iso kali2020.3.iso

Listamos las ISOs disponibles:

iohyve isolist
Listing ISO's...
kali2020.3.iso

Creación de VMs:

Creamos la VM con un disco de 15G:

iohyve create kali 15G

NOTA: La reserva de espacio del disco virtual NO es dinámica lo que implica que debemos tener disponible el espacio indicado en el momento de crear la VM.


Instalación por puerto serie:

Asignamos los parámetros de la VM:

iohyve set kali ram=2048M loader=grub-bhyve os=debian

El parámetro os no indica el SO a instalar si no solo algunos ajustes que grub-bhyve tendrá en cuenta para arrancar la VM, por ejemplo debian es cualquier Linux sin LVM.

Las posibles opciones son: openbsd57, openbsd58, openbsd59, openbsd60, openbsd61, netbsd, debian (non-LVM), d8lvm(LVM installs), centos6, centos7(non-XFS), ubuntu (LVM installs,non-LVM use debian), arch y custom.

La opción custom significa que se leerán los ficheros /iohyve/VM_NAME/device.map y /iohyve/VM_NAME/grub.cfg en el arranque.

NOTA: Si vamos a instalar un sistema FreeBSD no es necesario especificar los parámetros loader/os.

Antes de instalar el SO, dejamos una consola preparada a la espera:

iohyve console kali

En un segundo terminal iniciamos la instalación:

iohyve install kali kali2020.3.iso

Veremos que en el primer terminal aparece el asistente de instalación del SO, seleccionamos la segunda opción:

GNU GRUB version 2.00

+--------------------------------------------------------------------------+
|Graphical install |
|Install |
|Advanced options ... |
|Accessible dark contrast installer menu ... |
|Install with speech synthesis |
| |
| |
| |
| |
| |
| |
| |
+--------------------------------------------------------------------------+

 Use the ^ and v keys to select which entry is highlighted.
 Press enter to boot the selected OS, `e' to edit the commands
 before booting or `c' for a command-line.

Al terminar la instalación tendremos la VM apagada, la arrancamos y accedemos a la consola:

iohyve console kali
iohyve start kali
kali login: kr0m
Password:

Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64
The programs included with the Kali GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Kali GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Nov 8 10:59:10 CET 2020 on ttyS0

kr0m@kali:~$

Para salir de la consola escribimos Alt+4.: ~.


Instalación por VNC:

Por defecto Iohyve utiliza la consola serie para acceder al SO, en la mayoría de casos será mas que suficiente ya que si necesitamos arrancar alguna aplicación gráfica mediante ssh-Xforward podemos hacerlo sin tener que arrancar las X.

Otro modo de conseguir acceso a las X es instalando un servidor VNC en la propia VM, de este modo ya no dependeríamos del VNC de Iohyve.

Pero si necesitamos acceso gráfico en la instalación del SO como ocurre con Windows, tendremos que habilitar el acceso por VNC mediante el loader uefi, para que este esté disponible debemos instalar el paquete bhyve-firmware como se ha hecho al principio del manual e importar el fichero de firmware con el comando cpfw.

iohyve cpfw /usr/local/share/uefi-firmware/BHYVE_UEFI.fd
iohyve fwlist
Listing Firmware...
BHYVE_UEFI.fd

Ahora debemos decidir si queremos sacrificar una dirección ip de la red para el acceso VNC o si bindeamos el servicio a la loopback y accedemos vía túnel Ssh, mediante loopback el acceso será mas seguro ya que solo estará expuesto cuando montemos el túnel y no desperdiciaremos direcciones ips pero tendremos que configurar un puerto VNC distinto por cada VM.


VNC-Loopback:

Creamos la VM:

iohyve create kaliVNC 15G

Seteamos los parámetros necesarios:

iohyve set kaliVNC ram=2048M loader=uefi vnc=YES fw=BHYVE_UEFI.fd

Iniciamos la instalación:

iohyve install kaliVNC kali2020.3.iso

Vemos que hay un servicio en la loopback en el puerto 5900:

sockstat -sv|grep LISTEN|grep bhyve
root bhyve 9029 7 tcp4 127.0.0.1:5900 *:* LISTEN

Montamos el túnel Ssh para acceder desde fuera al VNC:

ssh -L 5900:127.0.0.1:5900 -A -g kr0m@HOST_PADRE

Arrancamos nuestro cliente VNC atacando nuestro pc el cual nos llevará vía túnel al VNC de la VM:

vinagre 127.0.0.1:5900

Si creamos una segunda VM tendremos que elegir un puerto VNC distinto:

iohyve create kaliVNC2 15G
iohyve set kaliVNC2 ram=2048M loader=uefi vnc=YES vnc_port=5901 fw=BHYVE_UEFI.fd
iohyve install kaliVNC2 kali2020.3.iso

Vemos que hay dos servicios bindeados a la loopback pero en distintos puertos:

sockstat -sv|grep LISTEN|grep bhyve
root bhyve 4166 7 tcp4 127.0.0.1:5901 *:* LISTEN
root bhyve 9029 7 tcp4 127.0.0.1:5900 *:* LISTEN

Montamos el túnel Ssh para dar acceso al VNC de la VM:

ssh -L 5901:127.0.0.1:5901 -A -g kr0m@HOST_PADRE

Accedemos al instalador vía VNC:

vinagre 127.0.0.1:5901


VNC-Ip:

Si optamos por asignar una dirección ip tendremos que configurar la ip como alias en el padre e indicarla en la configuración de la VM.

Vamos a dejarlo configurado en el rc.conf y manualmente, de este modo en caso de reinicio no se perderá configuración:

sysrc ifconfig_nfe0_alias0="inet IP_VM netmask NETMASK"
ifconfig INTERFAZ IP_VM netmask NETMASK alias

Creamos la VM:

iohyve create kaliVNC3 15G

Seteamos los parámetros necesarios:

iohyve set kaliVNC3 ram=2048M loader=uefi vnc=YES vnc_ip=192.168.69.254 fw=BHYVE_UEFI.fd

Iniciamos la instalación:

iohyve install kaliVNC3 kali2020.3.iso

Podemos ver como hay un VNC bindeado a la dirección ip indicada:

sockstat -sv|grep LISTEN|grep bhyve
root bhyve 14438 7 tcp4 192.168.69.254:5900 *:* LISTEN
root bhyve 4166 7 tcp4 127.0.0.1:5901 *:* LISTEN
root bhyve 9029 7 tcp4 127.0.0.1:5900 *:* LISTEN

Conectamos directamente al VNC de la VM sin necesidad de ningún túnel:

vinagre 192.168.69.254:5900

Realmente para un administrador de sistemas Unix el acceso VNC no tiene sentido, lo ideal es acceder vía Ssh, si necesitamos alguna aplicación gráfica arrancarla mediante ssh-Xforward y si se necesita un acceso de urgencia acceder vía puerto serie con el comando console de Iohyve.


Bug Xorg:

Si se han instalado las X estas están bugeadas(1, 2), el bug en cuestión presenta la siguiente salida al intentar arrancar las X:

Para solventarlo hay que entrar por Ssh y desinstalar el paquete xserver-xorg-video-vesa, el problema es que al arrancar el entorno gráfico se queda colgado por el bug y cuando presionamos Ctrl+Alt+F1 estamos enviando las pulsaciones a nuestro FreeBSD, para poder hacerlo dentro del cliente VNC previamente tendremos que deshabilitar las teclas en nuestro SO.

setxkbmap -option srvrkeys:none

Ahora ya podemos hacer login desde la tty no gráfica y arrancar el servicio Ssh para desinstalar el paquete conflictivo:

service ssh start

Accedemos por Ssh a la VM:

ssh kr0m@192.168.69.203 -p22

Desinstalamos el paquete y apagamos la VM:

apt remove xserver-xorg-video-vesa
halt

Rehabilitamos Ctrl+Alt+FX en nuestro SO:

setxkbmap -option

Arrancamos la VM:

iohyve start kaliVNC

Como podemos ver kali ya arranca las X con normalidad, si hacemos login veremos que el entorno gráfico funciona sin problemas:




Aplicaciones gráficas sin X por Ssh:

Una manera de ejecutar aplicaciones gráficas pero sin necesidad de arrancar las X es mediante el ssh-xforward, para ello configuramos el acceso ssh y averiguamos la dirección ip de la VM:

iohyve console kali

Starting console on kali...
~~. to escape console [uses cu(1) for console]
Connected

kali login: kr0m
Password:

Linux kali 5.7.0-kali1-amd64 #1 SMP Debian 5.7.6-1kali2 (2020-07-01) x86_64
The programs included with the Kali GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Kali GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Nov 8 11:50:53 CET 2020 on ttyS0

Habilitamos el servico Ssh:

kr0m@kali:~$ sudo su
root@kali:/home/kr0m# systemctl enable ssh.service
root@kali:/home/kr0m# systemctl start ssh.service

Consultamos la dirección ip de la VM:

root@kali:/home/kr0m# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.69.205 netmask 255.255.255.0 broadcast 192.168.69.255

Permitimos mostrar aplicaciones gráficas que provengan de la ip indicada en nuestro pc mediante xhost:

xhost +inet:192.168.69.205

Ejecutamos burpsuite a modo de prueba:

ssh -vYC kr0m@192.168.69.205 burpsuite


Listar VMs:

iohyve list
Guest     VMM?  Running  rcboot?  Description
kali      NO    NO       NO       Sun Nov  8 20:28:35 CET 2020
kaliVNC3  NO    NO       NO       Mon Nov  9 12:19:21 CET 2020

Información VMs:

Podemos consultar información de las VMs del siguiente modo:

iohyve info -sv
Guest           Size  CPU  RAM    Pool   OS       Loader      Tap   Con    VMM?  Running  rcboot?
kali            -     1    2048M  zroot  debian   grub-bhyve  tap0  nmdm0  NO    NO       NO
kali/disk0      15G   -    -      zroot  -        -           -     -      -     -        -
kaliVNC3        -     1    2048M  zroot  default  uefi        tap1  nmdm1  NO    NO       NO
kaliVNC3/disk0  15G   -    -      zroot  -        -           -     -      -     -        -
iohyve getall kali
Getting kali iohyve properties...
bargs            -A_-H_-P
bhyve_path       /usr/sbin/bhyve
boot             0
con              nmdm0
cpu              1
description      Sun Nov  8 20:28:35 CET 2020
install          no
loader           grub-bhyve
name             kali
os               debian
persist          1
ram              2048M
size             15G
tap              tap0
template         NO
utc              YES
vnc              NO
vnc_h            600
vnc_ip           127.0.0.1
vnc_tablet       NO
vnc_w            800
vnc_wait         NO


Parámetros:

Podemos asignar valores a los parámetros de la VM, algunos ejemplos pueden ser estos:

iohyve set kali ram=512M
iohyve set kali cpu=1
iohyve set kali description="This is my Kali box"

Incluso podemos hacer passthrugh de dispositivos:

iohyve set kali pcidev:1=passthru,2/0/0

Para obtener valores de los parámetros:

iohyve get kali ram
iohyve getall kali

Snapshots:

Creamos un snapshot:

iohyve snap kali@beforeupdate
Taking snapshot kali@beforeupdate

Listamos los snapshots disponibles:

iohyve snaplist
kali@beforeupdate

Revertimos a un snapshot:

iohyve stop kali
iohyve roll kali@beforeupdate
Rolling back to kali@beforeupdate

Eliminar snapshots:

iohyve rmsnap kali@beforeupdate

Clonar VMs:

Mediante el clonado estamos realizando una copia de la VM no un clon a nivel ZFS, esto puede suponer un consumo del espacio considerable ya que además del espacio que ocuparán las dos VMS Iohyve necesita espacio adicional mientras realiza el clonado.

iohyve clone kali dolly
iohyve list
Guest  VMM?  Running  rcboot?  Description
dolly  NO    NO       NO       Tue_Nov__8_21:04:05_CET_2020
kali   NO    NO       NO       Sun Nov  8 20:28:35 CET 2020

Templates:

Si no queremos que nadie arranque una VM por accidente o haga alguna modificación en esta VM arrancándola, reinstalándola, renombrándola o borrándola tendremos que setearle el parámetro template a YES.

Pongamos el siguiente ejemplo en el que kali está parada:

iohyve list
Guest  VMM?  Running  rcboot?  Description
kali   NO    NO       NO       Sun Nov  8 20:28:35 CET 2020

Le asignamos el parámetro template=YES:

iohyve set kali template=YES

Intentamos arrancar la VM

iohyve start kali
kali is a template. Cannot start

Intentamos eliminarla:

iohyve delete kali
kali is a template. Cannot delete

Forzar parada:

En algunos casos extremos el comando stop no logrará parar la VM, podemos forzar la parada pero este comando debe utilizarse como último recurso:

iohyve forcekill kali

Backup mediante exportaciones:

Mediante el comando export podremos generar un tarball con todos los datos de la VM, incluída su configuración Iohyve, este tarball será almacenado en el path: /iohyve/VM_NAME/VM_NAME.tar.gz el único inconveniente es que requiere que apaguemos la VM. Pero siempre podemos clonar la VM, hacer el export del clon, copiar el backup y eliminar el clon.

iohyve clone kali backup
iohyve list
Guest  VMM?  Running  rcboot?  Description
backup NO    NO       NO       Tue_Nov__8_21:14:05_CET_2020
kali   NO    NO       NO       Sun Nov  8 20:28:35 CET 2020
iohyve export backup
Exporting backup. Note this may take some time depending on the size.
Creating temp directory...
Exporting properties...
Exporting disks...
15360+0 records in
15360+0 records out
16106127360 bytes transferred in 170.564576 secs (94428326 bytes/sec)
Compressing to archive...
Removing temp directory...

Comprobamos el tamaño de la exportación:

du -h /iohyve/backup/backup.tar.gz
3.2G /iohyve/backup/backup.tar.gz

Movemos el tarball a algún lugar seguro, sería aconsejable moverlo a un servidor remoto en otra localización física, como prueba de concepto lo moveré a /root:

mv /iohyve/backup/backup.tar.gz /root/

Eliminamos la VM clonada:

iohyve delete backup
[WARNING] Are you sure you want to permanently delete backup and all child datasets?
Location: zroot/iohyve/backup [Y/N]? Y
Deleting backup at zroot/iohyve/backup...

Eliminamos la VM original:

iohyve stop kali
iohyve delete kali
[WARNING] Are you sure you want to permanently delete kali and all child datasets?
Location: zroot/iohyve/kali [Y/N]? Y
Deleting kali at zroot/iohyve/kali...

Para restaurarlo tan solo debemos descomprimirlo, crear una VM con los parámetros del fichero de configuración y volcar el contenido de la imagen de disco:

cd /root/
tar xvzf backup.tar.gz
x ./
x ./disk0.img
x ./properties.ucl
cat ./properties.ucl
bargs=-A_-H_-P
bhyve_path=/usr/sbin/bhyve
boot=0
con=nmdm0
cpu=1
description=Sun_Nov__8_20:08:03_CET_2020
install=no
loader=grub-bhyve
name=backup
os=debian
persist=1
ram=2048M
size=15G
tap=tap0
template=NO
utc=YES
vnc=NO
vnc_h=600
vnc_ip=127.0.0.1
vnc_tablet=NO
vnc_w=800
vnc_wait=NO

Creamos la VM con el tamaño de disco indicado en el fichero ucl:

iohyve create kali 15G

Asignamos los parámetros de la VM tal como aparecen en el fichero ucl:

iohyve set kali ram=2048M loader=grub-bhyve os=debian

Comprobamos que se haya creado correctamente:

iohyve list
Guest  VMM?  Running  rcboot?  Description
kali   NO    NO       NO       Sun Nov  8 20:28:35 CET 2020

Volcamos el contenido de la imagen de disco:

dd if=/root/disk0.img of=/dev/zvol/zroot/iohyve/kali/disk0
31457280+0 records in
31457280+0 records out
16106127360 bytes transferred in 397.031970 secs (40566324 bytes/sec)

Arrancamos la VM y accedemos a ella:

iohyve start kali
iohyve console kali

Diferencia entre VMM y Running:

Cuando arrancamos una VM esta pasa por el bootloader donde todavía no se ha cargado el kernel, esta fase es VMM, si se empieza a cargar el kernel ya aparece como Running.

Si paramos una VM pero VMM no se para pueden quedar recursos ocupados por esta VM, en tal caso debemos ejecutar el comando destroy:

iohyve destroy kali

Troubleshooting:

Alguna vez la consola muestra carácteres incorrectos, reseteándola se solventa el problema:

iohyve conreset kali
iohyve console kali

Si estamos probando Iohyve en un equipo de escritorio es muy probable que tengamos el proceso gvfs arrancado, esto puede causar problemas cuando eliminemos VMs ya que el proceso de Trash de gvfs puede estar accediendo al filesystem, en tal caso el error mostrado al intentar eliminar la VM es el siguiente:

iohyve delete kaliVNC
[WARNING] Are you sure you want to permanently delete kaliVNC and all child datasets?
Location: zroot/iohyve/kaliVNC [Y/N]? Y
Deleting kaliVNC at zroot/iohyve/kaliVNC...
cannot unmount '/iohyve/kaliVNC': Device busy

Localizamos el proceso que mantiene ocupado el dispositivo:

lsof +f -- /iohyve/kaliVNC
COMMAND   PID USER   FD   TYPE                DEVICE SIZE/OFF NODE NAME
gvfsd-tra 68671 kr0m   29r  VDIR 2635944363,1737022982      512   34 /iohyve/kaliVNC

Matamos el proceso:

kill -9 68671

Ahora ya podemos eliminar la VM sin problemas:

iohyve delete kaliVNC

Si el error que nos muestra es el siguiente:

iohyve delete kali
[WARNING] Are you sure you want to permanently delete kali and all child datasets?
Location: zroot/iohyve/kali [Y/N]? Y
Deleting kali at zroot/iohyve/kali...
cannot destroy 'zroot/iohyve/kali/disk0': dataset is busy

Tendremos que reiniciar el servicio, el inconveniente de esto es que parará todas las VMs:

service iohyve stop
iohyve delete kaliVNC
service iohyve start

Si tenemos algún problema de red podemos identificar rápidamente las interfaces tap de las VMs con el siguiente comando:

iohyve taplist
Listing all network taps:
zroot/iohyve/kali......tap0

Podemos comprobar manualmente como en el bridge están las dos interfaces de red, la del host padre y la tap de la VM:

ifconfig
em0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
 options=812099<RXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,VLAN_HWFILTER>
 ether 34:97:f6:36:bf:45
 inet 192.168.69.4 netmask 0xffffff00 broadcast 192.168.69.255
 media: Ethernet autoselect (1000baseT <full-duplex>)
 status: active
 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
 options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
 inet6 ::1 prefixlen 128
 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
 inet 127.0.0.1 netmask 0xff000000
 groups: lo
 nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
 description: iohyve-bridge-em0
 ether 02:89:af:f3:c6:00
 id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
 maxage 20 holdcnt 6 proto stp-rstp maxaddr 2000 timeout 1200
 root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
 member: tap0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
       ifmaxaddr 0 port 5 priority 128 path cost 2000000
 member: em0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
         ifmaxaddr 0 port 1 priority 128 path cost 20000
 groups: bridge
nd6 options=9<PERFORMNUD,IFDISABLED>
tap0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500
 description: iohyve-kali--
 options=80000<LINKSTATE>
 ether 58:9c:fc:10:ff:fd
 groups: tap
 media: Ethernet autoselect
 status: active
 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
Opened by PID 30627

Debo advertiros de que la gestión de discos parece funcionar bien en la mayoría de los casos probados pero eliminar el disco0 de una VM es problemático, parece que hay algún que otro bug, además luego resulta imposible arrancar la VM con el disco1.

Si te ha gustado el artículo puedes invitarme a un redbull aquí.
Si tienes cualquier pregunta siempre puedes enviarme un Email o escribir en el grupo de Telegram de AlfaExploit.
Autor: kr0m -- 10/11/2020 04:43:44 -- Categoria: Virtualizacion FreeBSD