Esta pagina se ve mejor con JavaScript habilitado

CBSD Gestor de Jails, Bhyve, Qemu y Xen

 ·  🎃 kr0m

CBSD es un software de gestión de Jails, máquinas virtuales Bhyve, máquinas virtuales Qemu de otras arquitecturas y Xen bajo FreeBSD, el proyecto ofrece una única cli para construir y gestionar entornos virtuales de forma rápida y sencilla. Además es posible la instalación de una interfaz web llamada Clonos que a algunos les puede resultar atractiva, pero ya sabéis que la cli siempre será mas potente ya que es posible automatizar todo tipo de tareas.

El artículo se compone de distintas partes:


Configuración inicial:

Antes de empezar mencionar que en este manual no vamos a utilizar Xen ya que implicaría sustituir nuestro sistema operativo por el hipervisor de Xen e instalar FreeBSD como DOM0, en este enlace podemos ver FreeBSD como DOM0 gestionando los DOMU desde CBSD.

Las versiones de CBSD están compuestas de varias partes, los dos primeros números indican la versión de FreeBSD en la que fué probado durante su desarrollo, el tercer número indica la versión de CBSD, por ejemplo con la versión CBSD v.12.1.13 se trata de la versión de CBSD 13 que fué probado en FreeBSD 12.1.

Instalamos el software necesario desde paquetes binarios, como cliente VNC utilizaremos Vinagre ya que es muy sencillo de utilizar:

pkg install -y cbsd tmux vinagre

Para utilizar Bhyve necesitaremos cargar el módulo vmm(Virtual Machine Monitor), lo cargamos en el arranque:

vi /boot/loader.conf

vmm_load="YES"

Para proveer de red a las Jails utilizaremos alias y para las VMs Bhyve interfaces tap y bridges, para el acceso por TTY a las jails utilizaremos nmdm(null modem terminal driver).
Cargamos los módulos correspondientes:

vi /etc/rc.conf

kld_list="vmm if_tap if_bridge nmdm"

Reiniciamos para aplicar la configuración:

reboot

Inicializamos el nodo:

env workdir="/usr/jails" /usr/local/cbsd/sudoexec/initenv

En la mayoría de casos los valores por defecto son aceptables, simplemente presionamos ENTER si estamos de acuerdo con ellos. Si mas adelante deseamos modificar algún parámetro podremos ejecutar los comandos cbsd initenv-tui, bsdconfig cbsd, modificar la base de datos sqlite ${workdir}/var/db/local.sqlite o cargando los valores desde un fichero de configuración.

-------[CBSD v.12.1.13]-------
 This is install/upgrade scripts for CBSD.
 Don't forget to backup.
-----------------------------
Do you want prepare or upgrade hier environment for CBSD now?
[yes(1) or no(0)]
yes

Shall i add cbsd user into /usr/local/etc/sudoers.d/cbsd_sudoers sudo file to obtain root privileges for the most cbsd commands?
[yes(1) or no(0)]
no

Shall i modify the /etc/rc.conf to sets cbsd_workdir="/usr/jails"?: 
[yes(1) or no(0)]
yes

nat_enable: Enable NAT for RFC1918 networks?
[yes(1) or no(0)]
no

fbsdrepo: Use official FreeBSD repository? When no (0) the repository of CBSD is preferred (useful for stable=1) for fetching base/kernel?
[yes(1) or no(0)]
yes

zfsfeat: You are running on a ZFS-based system. Enable ZFS feature?
[yes(1) or no(0)]
yes

stable: Use STABLE branch instead of RELEASE by default? Attention: only the CBSD repository has a binary base for STABLE branch ?
(STABLE_X instead of RELEASE_X_Y branch for base/kernel will be used), e.g.: 0 (use release)
0

sqlreplica: Enable sqlite3 replication to remote nodes ?
(0 - no replica, 1 - try to replicate all local events to remote nodes) e.g: 1
0

statsd_bhyve_enable: Configure CBSD statsd services for collect RACCT bhyve statistics? ?
(EXPERIMENTAL FEATURE)? e.g: 0
0

statsd_jail_enable: Configure CBSD statsd services for collect RACCT jail statistics? ?
(EXPERIMENTAL FEATURE)? e.g: 0
0

statsd_hoster_enable: Configure CBSD statsd services for collect RACCT hoster statistics? ?
(EXPERIMENTAL FEATURE)? e.g: 0
0

Configure RSYNC services for jail migration?
[yes(1) or no(0)]
1

Do you want to enable RACCT feature for resource accounting?
[yes(1) or no(0)]
yes

Shall i modify the /etc/rc.conf to sets cbsdd_enable=YES ?
[yes(1) or no(0)]
yes

Shall i modify the /etc/rc.conf to sets rcshutdown_timeout="900"?
[yes(1) or no(0)]
yes

Shall i modify the /etc/sysctl.conf to sets kern.init_shutdown_timeout="900"?
[yes(1) or no(0)]
yes

NOTA: Para conocer que versión de FreeBSD deseamos utilizar podemos consultar este artículo anterior .

Los parámetros RC añadidos deberían de ser:

vi /etc/rc.conf

# CBSD
# kld_list="vmm if_tap if_bridge nmdm"
# /boot/loader.conf: kern.racct.enable=1 vmm_load="YES"
cbsd_workdir="/usr/jails"
cbsdd_enable=\"yes\"
rcshutdown_timeout="900"

Arrancamos el servicio:

service cbsdd start

CBSD almacena los datos introducidos en una base de datos SQLite pero también se guardan en un fichero en plano para una rápida consulta.

cat ~cbsd/nc.inventory

Si queremos cambiar alguno de los parámetros configurados podemos ejecutar alguno de los asistentes existentes:

cbsd initenv-tui
bsdconfig cbsd

NOTA: Hay parámetros que no se pueden modificar desde los asistentes, pero podemos configurar los parámetros en un fichero y cargarlos.

La lista completa de parámetros la podemos encontrar aquí:

/usr/local/cbsd/share/initenv.conf

La mejor manera de hacerlo es fusionando nuestra configuración actual con lo parámetros del fichero genérico:

cat ~cbsd/nc.inventory > customConfig.txt
echo “#——————-” » customConfig.txt
cat /usr/local/cbsd/share/initenv.conf » customConfig.txt

Ahora editamos el fichero para dejarlo a nuestro gusto:

vi customConfig.txt

Finalmente cargamos los parámetros:

/usr/local/cbsd/sudoexec/initenv /root/customConfig.txt

Debemos tener en cuenta que cada vez que se actualice la versión de cbsd habrá que ejecutar:

cbsd initenv

Si instalamos CBSD desde paquetes precompilados puede venir con una versión desactualizada de los templates, estos son utilizados para lanzar máquinas virtuales Bhyve. Si estos no están actualizados puede que el template haga referencia a una ISO antigua que ya no esté disponible en los servidores de imágenes y la descarga dará error.

Podemos actualizar los templates desde el propio asistente:

cbsd bconstruct-tui


Si aparece un mensaje advirtiéndonos de que nuestra configuración de git está incompleta y se queja del modo en que mergear los cambios git, tendremos que ir al directorio del repositorio y ejecutar los comandos de configuración:

cd /usr/jails/etc
git config pull.rebase false

Ahora ya podemos lanzar el asistente y no se quejará.

Si lo preferimos podemos hacer un pull directamente, obteniendo el mismo resultado que con el asistente:

cd /usr/jails/etc/
git pull

La configuración por defecto de CBSD se encuentra en el directorio: /usr/jails/etc/defaults/

Si queremos modificar algún valor lo haremos al estilo FreeBSD, es decir generando el mismo fichero en un directorio superior al directorio donde se encuentra el fichero por defecto, este nuevo fichero contendrá solo los parámetros que queramos sobreescribir.

Para cambiar el nombre del dominio editaremos los siguientes ficheros:

vi /usr/jails/etc/bhyve-default-default.conf

default_domain="alfaexploit.com"
vi /usr/jails/etc/jail-freebsd-default.conf
default_domain="alfaexploit.com"
vi /usr/jails/etc/jail-freebsd-vnet.conf
default_domain="alfaexploit.com"
vi /usr/jails/etc/jail-freebsd-trusted.conf
default_domain="alfaexploit.com"

Una funcionalidad muy útil si estamos probando CBSD en nuestro pc de sobremesa es el comando blogin que nos permite especificar el comando a ejecutar para hacer login en la VM Bhyve, en mi caso deseo lanzar Vinagre contra la ip loopback en el puerto VNC que se le haya asignado a la VM, pero para poder hacer esto desde root tendremos que exportar la variable DISPLAY, definir el path del fichero Xauthority del usuario que arrancó la sesión gráfica actual y finalmente lanzar como ese usuario el comando Vinagre.

vi /usr/jails/etc/blogin.conf

login_cmd="export DISPLAY=:0.0 && export XAUTHORITY=/home/kr0m/.Xauthority && su -m kr0m -c \"xhost si:kr0m:root\" && su -m kr0m -c \"vinagre 127.0.0.1:${vnc_port}\""

NOTA: Si necesitamos modificar el comando login para una VM en concreto deberemos editar el fichero:  /usr/jails/jails-system/VM_NAME/etc/blogin.conf

Por supuesto si la instalación de CBSD se realizó en un servidor remoto el comando blogin es totalmente inútil, tendremos que configurar los parámetros VNC de la VM para poder acceder desde el exterior o bindear VNC a la loopback y cada VM en un puerto distinto, el acceso desde fuera se haría mediante túneles Ssh. Ambos procedimientos se detallan mas adelante en este mismo manual.

Por defecto la red de las jails se gestiona mediante alias en el padre, en cambio en Bhyve se hace mediante dispositivos tap y un bridge, pongamos un ejemplo de Jail y Bhyve para que se vea mas claro.


Gestión Jails:

Iniciamos el asisten de construcción de una Jail:

cbsd jconstruct-tui


Arrancamos la Jail:

cbsd jstart jail1
cbsd jls

JNAME  JID  IP4_ADDR       HOST_HOSTNAME    PATH                    STATUS
jail1  4    192.168.69.77  jail1.alfaexploit.com  /usr/jails/jails/jail1  On       

Si dejamos la dirección ip en DHCP nos dará una del rango: 10.0.0.0/16. Si queremos asignar ips por DHCP a las Jails tendremos que utilizar el modo de red VNET, no alias.

Si le asignamos una ip de nuestro rango de red(192.168.69.77) en el padre se creará un alias de forma automática:

ifconfig

em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
 options=81249b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,LRO,WOL_MAGIC,VLAN_HWFILTER>
 ether 34:97:f6:36:bf:45
 inet 192.168.69.4 netmask 0xffffff00 broadcast 192.168.69.255
 inet 192.168.69.77 netmask 0xffffffff broadcast 192.168.69.77
 media: Ethernet autoselect (1000baseT <full-duplex>)
 status: active
 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

Entramos dentro de la Jail:

cbsd jlogin jail1
uname -a

FreeBSD jail1.alfaexploit.com 12.1-RELEASE-p10 FreeBSD 12.1-RELEASE-p10 GENERIC  amd64
ifconfig em0
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
 options=81249b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,LRO,WOL_MAGIC,VLAN_HWFILTER>
 ether 34:97:f6:36:bf:45
 inet 192.168.69.77 netmask 0xffffffff broadcast 192.168.69.77
 media: Ethernet autoselect (1000baseT <full-duplex>)
 status: active

Para proporcionar red a las Jails se utilizan alias en la interfaz del padre, al ser alias estas son ips del padre y de la Jail simultáneamente, esto implica ciertos problemas si bindeamos en todas las direcciones disponibles los servicios del padre, por ejemplo si lo hacemos con el servicio Ssh mientras la Jail tenga el servicio arrancado se servirá en esa ip el Ssh de la Jail, si se apaga el Ssh de la Jail se servirá el Ssh del padre, esto puede llevar a confusión.

Cualquier servicio del padre se debe bindear exclusivamente a su dirección ip, en la jail no hay problema ya que solo ve la ip asignada y con un wildcard se bindea a esta única ip existente.

En el padre debemos evitar los bindeos genéricos como estos:

ListenAddress 0.0.0.0  
listen *

Esto podría evitarse utilizando la tecnología de red VNET que proveerá de una pila TCP/IP completa a la jail, pero se trata de otra historia que explicaré en un futuro artículo.

Accedemos a la Jail vía SSH:

ssh root@192.168.69.77
jail1:/root@[19:04] #

Si estamos probando CBSD en un equipo de escritorio es muy probable que tengamos el proceso gvfs arrancado, esto puede causar problemas cuando eliminemos jails ya que el proceso de Trash de gvfs puede estar accediendo al filesystem.

Comprobamos si algún filesystem pertenece a alguna jail eliminada:

zfs list

zroot/ROOT/default/jail1                88K  17.6G    88K  /usr/jails/jails-data/jail1-data

Para localizar el proceso problemático ejecutaremos lsof de una forma similar a la siguiente:

lsof +f – /usr/jails/jails-data/jail1-data

COMMAND     PID USER   FD   TYPE                DEVICE SIZE/OFF NODE NAME
gvfsd-tra 71064 kr0m   31r  VDIR 2588486123,3870875304        2    4 /usr/jails/jails-data/jail1-data

Matamos el proceso:

kill PID

Desmontamos el filesystem y lo destruimos:

umount /usr/jails/jails-data/jail1-data
zfs destroy zroot/ROOT/default/jail1


Gestión VMs Bhyve:

Iniciamos el asistente de construcción de una VM Bhyve:

cbsd bconstruct-tui

En el caso de Bhyve la configuración de red se regirá por la configuración que se realice mediante el instalador del SO invitado ignorando los parámetros del asistente. Estos parámetros simplemente se guardan en la base de datos SQLite por si fuese necesaria la integración con algún servicio externo como puede ser un servidor DHCP, de este modo podríamos ejecutar un script de configuración del DHCP en base a la IP indicada y la dirección MAC de la VM justo antes de arrancarla, en este artículo podemos ver un ejemplo completo.

Al crear la VM se crean dos interfaces tap en el padre, una para la VM y otra para el padre, estas dos interfaces junto con la interfaz física se meten dentro de un bridge.

Si estamos creando una máquina Linux debemos cambiar el firmware de arranque de disco a refind en otros sistemas como DragonFlyBSD parece que el firmware Bhyve funciona sin problemas:


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.

Bhyve VNC-loopback:
Accedemos a las opciones VNC del asistente:

Configuramos un puerto distinto para cada VM:

Bhyve VNC-Ip:
Accedemos a las opciones VNC del asistente:

Configuramos una dirección ip:

Quedando del siguiente modo:

Configuramos la ip como alias en el padre, 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"

Manualmente:

ifconfig INTERFAZ IP_VM netmask NETMASK alias

Terminamos de crear la VM:

Si quisiesemos modificar algún parámetro tan solo debemos ejecutar el comando bconfig:

cbsd bconfig jname=kali1

Cuando arranquemos la VM nos preguntará si queremos arrancar desde cdrom:

cbsd bstart kali1

May be you want to boot from CD?   
[yes(1) or no(0)]  
1  
Temporary boot device: cd  
vm_iso_path: iso-kali-linux-mate-2020.2-amd64  
No such media: /usr/jails/src/iso/cbsd-iso-kali-linux-2020.2-installer-amd64.iso in /usr/jails/src/iso

En caso de no encontrar la imagen ISO de la distro a instalar nos preguntará si debe bajársela de los mirrors:

Shall i download it from: https://gemmei.ftp.acc.umu.se/mirror/kali.org/kali-images/kali-2020.2/ https://cdimage.kali.org/kali-2020.2/ http://mirrors.dotsrc.org/kali-images/kali-2020.2/ http://mirror-1.truenetwork.ru/kali-images/kali-2020.2/ ?  
[yes(1) or no(0)]  
1

Consultamos las VMs disponibles, dependiendo de como configuramos el acceso VNC obtendremos distintas salidas:
VNC-Loopback:

cbsd bls

JNAME  JID    VM_RAM  VM_CURMEM  VM_CPUS  PCPU  VM_OS_TYPE  IP4_ADDR  STATUS  VNC  
kali1  75966  2048    25         1        0     linux       DHCP      On      127.0.0.1:5900  

VNC-Ip:

cbsd bls

JNAME  JID    VM_RAM  VM_CURMEM  VM_CPUS  PCPU  VM_OS_TYPE  IP4_ADDR  STATUS  VNC  
kali1  75903  2048    264        1        0     linux       DHCP      On      192.168.69.144:5900

 
Hacemos login mediante VNC y procedemos con la instalación.

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

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

Accedemos por el túnel:

vinagre 127.0.0.1:5900

VNC-Ip:

vinagre 192.168.69.144:5900

En el bridge podemos ver una interfaz para el padre, otra para la VM y la interfaz física:

ifconfig

bridge1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500  
 description: em0  
 ether 02:89:af:f3:c6:01  
 id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15  
 maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200  
 root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0  
 member: tap2 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>  
         ifmaxaddr 0 port 5 priority 128 path cost 2000000  
 member: tap1 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>  
         ifmaxaddr 0 port 4 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>  
tap1: flags=8903<UP,BROADCAST,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500  
 description: CBSDSYSTEM0  
 options=80000<LINKSTATE>  
 ether 00:bd:3a:47:f7:01  
 groups: tap  
 media: Ethernet autoselect  
 status: no carrier  
 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>  
tap2: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500  
 description: kali1-nic0  
 options=80000<LINKSTATE>  
 ether 00:bd:15:46:c5:02  
 groups: tap vm-port  
 media: Ethernet autoselect  
 status: active  
 nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>  
 Opened by PID 43480

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

Para solventarlo tendremos 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:

Desinstalamos el paquete:

apt remove xserver-xorg-video-vesa
reboot

Rehabilitamos Ctrl+Alt+FX:

setxkbmap -option

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


Otra forma de tener las X funcionando es instalar el SO mediante el VNC de CBSD y luego acceder por Ssh a la VM para instalar un servidor VNC dentro de esta, así ya no dependeríamos del VNC de Bhyve.

Como apunte final destacar que si solo queremos arrancar ciertas aplicaciones gráficas podemos hacerlo mediante el ssh-xforward sin necesidad de arrancar las X enteras.

Autorizamos la ip de la Kali para que pueda lanzar aplicaciones en local a través de la red, conectamos por Ssh y lanzamos de forma remota la aplicación:

xhost +inet:192.168.69.99
ssh -vYC kr0m@192.168.69.99 burpsuite

Si te ha gustado el artículo puedes invitarme a un RedBull aquí