
Marco de manipulación de máquinas virtuales.
Mofos es una herramienta diseñada para crear, ejecutar y gestionar máquinas virtuales. Utiliza Libvirt/QEMU/KVM y Python, lo que la hace compatible con cualquier distribución de Linux. Fuertemente inspirada en Qubes OS (https://www.qubes-os.org/), Mofos pretende replicar muchas de sus características.
La herramienta ha sido probada exhaustivamente en Debian con máquinas virtuales basadas en Debian. Aunque se espera que otras distribuciones de Linux funcionen, puede ser necesaria configuración adicional. Se añadirán más detalles.
Mofos proporciona una gama de características centradas en la gestión segura de máquinas virtuales, incluyendo:
Una máquina de mofos consta de dos discos combinados mediante overlayfs. El primer disco, conocido como capa inferior, es un disco de plantilla de solo lectura, mientras que el segundo disco almacena todos los cambios realizados por la máquina virtual. Este disco de plantilla se comparte entre múltiples máquinas virtuales. Como resultado, crear una nueva máquina virtual solo requiere clonar un disco vacío que ya está particionado para contener los datos modificados. Este enfoque garantiza que las nuevas máquinas virtuales puedan crearse rápidamente, al tiempo que permite actualizar la plantilla de forma independiente. Cualquier actualización de la plantilla tendrá efecto para las máquinas virtuales dependientes en su próximo reinicio.
Dependiendo de la distribución de Linux, el Makefile se puede utilizar para generar un paquete deb o instalar los archivos directamente.```
make deb
apt install ./mofos-VERSION.deb
Durante la instalación mediante `apt`, se solicitarán varios ajustes. Las opciones predeterminadas generalmente pueden aceptarse. El único ajuste que requiere atención es la dirección de subred utilizada por la red libvirt de mofos (predeterminada: `192.168.90.0/24`).
O
Instale las siguientes dependencias:
- guestfs-tools
- libnotify-bin
- libvirt
- libvirt-clients
- libvirt-daemon
- make
- python3-click
- python3-click-completion
- python3-colorama
- python3-cryptography
- python3-dbus
- python3-jinja2
- python3-lxml
- python3-prettytable
- python3-pyroute2
- python3-tqdm
- qemu-system-common
- qemu-system-modules-spice
- socat
- spice-client-gtk
- sudo
- virtinst
- virt-install
- virtiofsd
- virt-manager
- virt-viewer```
make install_files
Según la distribución, es posible que el intérprete de Python no detecte los archivos Python copiados en /usr/lib/python3/dist-packages, por lo que deben colocarse en otra ubicación. Por ejemplo, en Fedora, los archivos Python deben copiarse en /usr/lib/python3.11/site-packages.
[!WARNING] Atención, desde Debian trixie,
xpraya no se distribuye como paquete; debes instalarlo manualmente desde sus repositorios personalizados. Consulta https://github.com/Xpra-org/xpra/wiki/Download#-for-debian-based-distributions para obtener instrucciones detalladas.
Mofos utiliza la sesión de sistema QEMU/KVM, por lo que para permitir que el comando virsh acceda a las máquinas virtuales y recursos relacionados, establece la variable de entorno LIBVIRT_DEFAULT_URI en qemu:///system:```console
export LIBVIRT_DEFAULT_URI=qemu:///system
### Consideraciones de seguridad
El uso de sesiones de sistema QEMU/KVM mejora el aislamiento entre las máquinas virtuales anfitrionas e invitadas al ejecutar las instancias de qemu bajo un usuario dedicado (`libvirt-qemu`) y aplicar perfiles de seguridad específicos a cada instancia.
Sin embargo, de forma predeterminada, los usuarios normales no pueden interactuar con el socket del sistema `libvirtd` para gestionar máquinas, redes y otros recursos. Para obtener acceso, los usuarios deben ser miembros del grupo Unix de libvirt o usar sudo. Históricamente, las vulnerabilidades locales de escalada de privilegios han explotado la pertenencia al grupo libvirt para obtener privilegios de root.
Para mitigar estos riesgos, este repositorio proporciona un perfil AppArmor reforzado para el proceso `libvirtd` en sistemas que usan AppArmor. Este perfil restringe significativamente dónde puede escribir archivos `libvirtd` y qué programas puede ejecutar.
Además, se incluyen reglas de `polkit` para controlar aún más las acciones permitidas a los miembros del grupo `libvirt`.
Tenga en cuenta que los perfiles AppArmor se incluyen en el paquete `deb`, pero no se instalan mediante el objetivo `install_files` del Makefile, por lo que deben instalarse por separado.
## Configuración de Mofos
Mofos requiere un archivo de configuración ubicado en `$HOME/.config/mofos/config.toml` con ajustes mínimos para funcionar correctamente. En `/usr/share/mofos/config.minimal.toml` se puede encontrar un ejemplo de configuración mínima, mientras que en `/usr/share/mofos/config.sample.toml` se documenta una configuración más completa.
El siguiente error indica que no se encontró el archivo de configuración:```
[-] Copy the sample configuration file from /usr/share/mofos/config.minimal.toml to ~/.config/mofos/config.toml
El siguiente error indica que el usuario actual no es miembro del grupo libvirt:``` [-] libvirtError("authentication unavailable: no polkit agent available to authenticate action 'org.libvirt.unix.manage'")
Los ajustes de configuración principales que se deben personalizar en los archivos de configuración son los siguientes:
- key (ruta): El archivo de clave privada SSH utilizado para acceder a las máquinas virtuales. Se recomienda crear una clave dedicada para este propósito.
- user (cadena): El nombre de usuario para el acceso SSH a las máquinas virtuales.
- root_password (valor hash): La contraseña hash de root que se establecerá durante la instalación de una nueva plantilla.
- root_ssh_pubkey (cadena): La clave pública SSH que se instalará en el directorio del usuario root durante la instalación de la plantilla.
Además, los siguientes parámetros deben configurarse para la instalación de plantillas:
- ntp
- dns (opcional si se proporciona un proxy)
- proxy
## Instalar una plantilla
### Configurar el cortafuegos
Dado que el proceso de instalación depende del arranque por red PXE, se requiere una conexión a Internet activa. Se deben configurar las siguientes reglas de cortafuegos:```
sysctl net.ipv4.ip_forward=1
iptables -t nat -I POSTROUTING -s 192.168.90.0/24 -j MASQUERADE
iptables -t nat -I POSTROUTING -s 192.168.91.0/24 -j MASQUERADE
O con nftables:``` sysctl net.ipv4.ip_forward=1 nft insert inet nat postrouting iifname "install-*" masquerade nft insert inet nat postrouting iifname "mof0" masquerade
Cuando el parámetro `ip_forward` está establecido en 1, la cadena FORWARD debe configurarse para evitar que otros dispositivos de la red utilicen el host como enrutador.
En general, se recomiendan las siguientes reglas:```
iptables -I INPUT -i mof0 -p udp --sport 68 --dport 67 -j ACCEPT -m comment --comment "mofos dhcp"
iptables -I INPUT -i mof0 -p udp --dport 69 -j ACCEPT -m comment --comment "mofos tftp"
iptables -I OUTPUT -o mof0 -j ACCEPT -m comment --comment "host -> mofos"
iptables -I FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -i mof0 -j ACCEPT -m comment --comment "mofos ->"
iptables -t nat -I POSTROUTING -s 192.168.90.0/24 -j MASQUERADE
iptables -t nat -I POSTROUTING -s 192.168.91.0/24 -j MASQUERADE
O con nftables:```
table inet filter {
chain input {
type filter hook input priority 0; policy drop
iifname "install-*" ip daddr 255.255.255.255 udp sport 68 udp dport 67 accept comment "mofos dhcp"
iifname "mof0" ip daddr 255.255.255.255 udp sport 68 udp dport 67 accept comment "mofos dhcp"
iifname "install-*" udp dport 69 accept comment "mofos tftp"
}
chain forward {
type filter hook forward priority 0; policy drop
ct state established,related accept;
ct state invalid drop;
iifname "mof0" counter accept
iifname "install-*" counter accept
}
chain output {
type filter hook output priority 0; policy drop
oifname "mof0" counter accept
}
} table inet nat { chain postrouting { type nat hook postrouting priority 100 iifname "mof0" masquerade iifname "install-*" masquerade } }
Se recomienda restringir las reglas de enmascaramiento y reenvío según tus necesidades específicas, para evitar que las máquinas virtuales de Mofos accedan a toda la red del host.
El aislamiento entre máquinas virtuales se aplica automáticamente mediante un hook de libvirt, que requiere nft para funcionar correctamente.
### Instalación
El primer paso es construir la capa inicial: la plantilla. Por defecto, Mofos puede instalar una plantilla basada en Debian 12.```
mofos template create debian-template
Nota: Para cada comando, la opción --debug se puede utilizar para obtener información técnica detallada en caso de comportamiento inesperado. Específicamente para este comando, la marca --debug también fuerza una ventana gráfica para mostrar el progreso de la instalación. Alternativamente, la instalación se puede supervisar usando virt-manager.
Actualmente, solo la plantilla Debian 12 es compatible para la instalación. El diccionario de Python a continuación especifica la imagen de instalación que se utilizará:```python NETBOOT = { "debian-stable-amd64": { "variant": "debian11", "url": "https://deb.debian.org/debian/dists/stable/main/installer-amd64/current/images/netboot/netboot.tar.gz", } }
La variante se establece en `debian11` porque en Debian 12, la variante `osinfo` para Debian 12 aún no se puede instalar mediante libvirt.
Para instalar otra distribución, modifique el diccionario ubicado en `/usr/lib/python3/dist-packages/mofos/settings.py`.
Cuando se ejecuta el comando anterior, Mofos descarga los archivos netboot y almacena en caché el archivo `tar.gz` en `$HOME/.cache/template-installer`. Actualmente, si el archivo netboot ya existe, Mofos no lo descargará de nuevo. Esto puede causar errores si la caché está desactualizada. Si ocurren tales errores durante la instalación, eliminar la caché forzará a Mofos a descargar una versión actualizada, lo que debería resolver el problema.
A continuación, el archivo se extrae en `/tmp`, y libvirt se configura para servir su contenido mediante TFTP.
Luego se crea la máquina virtual de plantilla y se configura para arrancar mediante PXE, instalando la distribución especificada usando el archivo preseed proporcionado (por defecto `/usr/share/mofos/templates/debian/preseed.cfg.j2`). Este archivo es una plantilla `jinja2`; antes de copiarlo al directorio raíz de TFTP, se inyectan las variables de los archivos de configuración (`ntp`, `proxy`, `dns`, `root_password`).
Al final de la instalación, el script `postinstall` se coloca en el directorio TFTP y se ejecuta en la plantilla. Por defecto, se utiliza el script ubicado en `/usr/share/mofos/templates/postinstall.sh.j2`. Esta plantilla `jinja2` inyecta la clave pública SSH que se configurará en la plantilla.
Además de configurar la clave pública SSH de root, se realizan las siguientes operaciones:
- Deshabilitar el servicio SSH estándar y habilitar un SSHD sobre sockets virtuales (vsock).
- Vaciar el archivo `/etc/resolv.conf`.
- Configurar el tiempo de espera de GRUB a 0 segundos.
- Instalar un hook de initramfs que monta el overlayfs cuando se detecta una partición etiquetada como `overlay`.
Una vez completada la instalación, la máquina virtual de libvirt se recupera y se comprime en un archivo local `qcow2` guardado en el directorio actual.```
$ mofos template create debian-template
[*] Installing debian-template
[*] Configure the SSH host key of the template
[*] Waiting for the installation to be complete
[*] Installation is complete
[*] Downloading the resulting qcow2 disk
[*] Compressing the disk
[*] Save template's public ssh host key
[+] Template installation finished
[+] Template disk is debian-template-disk.qcow2
Además del archivo qcow2, este proceso también crea una entrada en el archivo $HOME/.local/share/mofos/ssh.json que contiene el nombre de la máquina y su clave pública SSH:```json
{
"disk": {
"debian-template-disk.qcow2": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrbOdOPENEj2KeHrYLdorQe9Ez1b9Bu5agZmgNDMayy"
}
}
Este archivo se utiliza automáticamente durante el proceso de importación.
### Importación
El siguiente paso es importar el archivo de plantilla `qcow2` creado en Mofos.```
$ mofos template import debian-template debian-template-disk.qcow2 http://debian.org/debian/11
[*] Uploading debian-template-disk.qcow2 to mofos pool
[*] Creating the virtual machine debian-template
[*] Configuring the template metadata
[*] Configuring the SSH key
[+] debian-template successfully imported
Por ahora, la variante osinfo es obligatoria. Se pueden encontrar en el archivo:
/usr/lib/python3/dist-packages/mofos/settings.py.
Una vez importado, la plantilla se puede ver en el comando mofos ls:```
$ mofos ls
+----+-----------------+---------+-------------+-------+-----+--------------+
| Id | Name | State | Description | Alias | Cid | IPv4 address |
+----+-----------------+---------+-------------+-------+-----+--------------+
| | debian-template | shutoff | | | | |
+----+-----------------+---------+-------------+-------+-----+--------------+
A partir de este punto, la plantilla se puede iniciar y acceder a ella para modificarla según sea necesario.```
$ mofos start debian-template
$ mofos ls
+----+-----------------+---------+-------------+-------+-----+----------------+
| Id | Name | State | Description | Alias | Cid | IPv4 address |
+----+-----------------+---------+-------------+-------+-----+----------------+
| 3 | debian-template | running | | | 3 | 192.168.90.202 |
+----+-----------------+---------+-------------+-------+-----+----------------+
No se ha proporcionado contenido para traducir.``` $ mofos ssh debian-template --user root root@linux:~#
## Crear el disco vacío de la capa superior
El siguiente comando crea una capa superior vacía con la etiqueta especificada en la única partición del disco:```
$ mofos template create-overlay-disk
Por defecto, este disco está configurado con 50 GB, pero inicialmente solo ocupa alrededor de 100 MB. Este tamaño se puede personalizar en el archivo de configuración.
Nota: Se recomienda apagar siempre una plantilla antes de manipular las máquinas virtuales de Mofos. Aunque ejecutar una plantilla y sus máquinas virtuales simultáneamente es compatible, puede provocar inestabilidad.``` $ mofos new test [] New virtual machine name is test [+] Virtual machine test successfully created [] Triggering post install actions [] Create SSH known_hosts entries for test [] Waiting for test to be up [+] test is ready $ mofos ssh test -u root Last login: Mon Jun 2 11:09:51 2025 from UNKNOWN root@linux:~#
Ten en cuenta que las conexiones SSH se realizan a través de sockets virtuales, por lo que no puedes conectarte por SSH directamente a la máquina recién creada. En su lugar, debes usar el comando mofos ssh. Alternativamente, puedes crear una configuración SSH que especifique un `ProxyCommand `para acceder al puerto SSH de la máquina:```
$ mofos inventory --format ssh
Host debian-template
User user
PasswordAuthentication no
IdentityFile /home/user/.ssh/id_ed25519
ProxyCommand /usr/bin/mofos proxy-cmd %h
CanonicalizeHostname=no
Host test
User user
PasswordAuthentication no
IdentityFile /home/user/.ssh/id_ed25519
ProxyCommand /usr/bin/mofos proxy-cmd %h
CanonicalizeHostname=no
No se ha proporcionado ningún contenido en el campo INPUT. El chunk 41 está vacío, por lo que no hay texto que traducir.``` $ mofos inventory --format ssh > ~/.ssh/mofos $ echo "Include ~/.ssh/mofos" >> ~/.ssh/config $ ssh root@test Linux linux 6.1.0-37-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.140-1 (2025-05-22) x86_64
The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Mon Jun 2 11:09:51 2025 from UNKNOWN root@linux:~#
Durante una sesión de `mofos ssh`, se establece previamente un socket `ControlMaster` para acelerar las conexiones posteriores. Por eso no se muestra el MOTD.
## Personalización
Para simplificar la personalización de plantillas y máquinas virtuales, Mofos introduce el concepto de hooks y tags. Para cada tag, se puede ejecutar un hook correspondiente (un script de Bash) para realizar acciones automatizadas en la máquina virtual o plantilla objetivo y configurarla en consecuencia.
Los hooks mínimos se encuentran en `/usr/share/mofos/hooks`. Son scripts de Bash sencillos que reciben las siguientes entradas:```
TAG=$1
NAME=$2
OS=$3
DISTRIB=$4
HOSTNAME=$5
Este mecanismo se puede aprovechar con Ansible para ejecutar playbooks durante la instalación de plantillas:```bash #!/bin/bash
TAG=$1 NAME=$2 OS=$3 DISTRIB=$4 HOSTNAME=$5
if [ -z "${TAG}" ] || [ -z "${NAME}" ] || [ -z "${DISTRIB}" ] ; then exit 1 fi
ANSIBLE_DIRECTORY="/home/user/Documents/ansible" RANDOM_SUFFIX=$(printf "%x" $RANDOM) INVENTORY_FILE="${ANSIBLE_DIRECTORY}/inventory-${NAME}-${RANDOM_SUFFIX}.ini"
trap 'rm -f "${INVENTORY_FILE}"; exit' EXIT
cat > $INVENTORY_FILE <<EOF [all:vars] ansible_ssh_common_args="-o ProxyCommand='mofos proxy-cmd %h' -o CanonicalizeHostname=no"
[${TAG}] ${NAME}
[${DISTRIB}] ${NAME} EOF
export ANSIBLE_CONFIG="/home/user/Documents/ansible/ansible.cfg" export ANSIBLE_VERBOSITY=1
/usr/bin/ansible-playbook
-i "${INVENTORY_FILE}"
-l "${NAME}"
/home/user/Documents/ansible/playbooks/pentest/install.yml
Este script crea dinámicamente un inventario y ejecuta un playbook contra él.
### Máquina virtual: nuevo hook
Durante la creación de máquinas virtuales, se puede utilizar otro hook, por ejemplo, para aleatorizar el nombre de host.
Por defecto, Mofos genera un alias basado en la convención clásica de nombres de Windows (p. ej., `DESKTOP-2BF9753`). Este nombre, junto con otra información, se pasa al script del hook:```
#!/bin/bash
TAG=$1
NAME=$2
OS=$3
DISTRIB=$4
HOSTNAME=$5
if [ -z "${TAG}" ] || [ -z "${NAME}" ] || [ -z "${OS}" ] ; then
exit 1
fi
if [ -z "${HOSTNAME}" ] ; then
HOSTNAME="${NAME}"
fi
mofos run -u root "${NAME}" "echo ${HOSTNAME} > /etc/hostname && hostname ${HOSTNAME}"
A continuación, la configuración debe editarse para habilitar este hook:``` [hooks.test] new = "/home/user/.config/mofos/hooks/new.sh"
Luego, durante la creación de la máquina virtual, se ejecutará este script:```
$ mofos new test2 --tags test
[*] New virtual machine name is test2
[+] Virtual machine test2 successfully created
[*] Triggering post install actions
[*] Create SSH known_hosts entries for test2
[*] Waiting for test2 to be up
[*] Running new hook: test
[+] test2 is ready
I don't see any input text to translate. The message ends with "INPUT:" but no source content follows.
Please provide the chunk content so I can translate it from English to Spanish following all the specified rules.``` $ mofos ssh test2 -u root Last login: Mon Jun 2 11:09:51 2025 from UNKNOWN root@DESKTOP-2BF9753:~#
Al igual que en la fase de instalación, los playbooks de Ansible también se pueden ejecutar en esta etapa. En este caso, se puede usar el comando `mofos inventory` para generar un inventario de Ansible, lo que simplifica el proceso de seleccionar y acceder a las máquinas virtuales:```
$ mofos inventory
{
"_meta": {
"hostvars": {
"debian-template": {
"ansible_host": "debian-template",
"ansible_ssh_common_args": "-o ProxyCommand='/usr/bin/mofos proxy-cmd %h' -o CanonicalizeHostname=no"
},
"test": {
"ansible_host": "test",
"ansible_ssh_common_args": "-o ProxyCommand='/usr/bin/mofos proxy-cmd %h' -o CanonicalizeHostname=no"
},
"test2": {
"ansible_host": "test2",
"ansible_ssh_common_args": "-o ProxyCommand='/usr/bin/mofos proxy-cmd %h' -o CanonicalizeHostname=no"
}
}
},
"debian": [
"debian-template",
"test",
"test2"
],
"test": [
"test2"
]
Nótese que los grupos se crean en función de la variante de distribución, así como de las etiquetas. Estos grupos se pueden utilizar para cargar diferentes variables.
Por ejemplo, el siguiente script ejecuta un playbook arbitrario:```bash #!/bin/bash
TAG=$1 NAME=$2 OS=$3 DISTRIB=$4 HOSTNAME=$5
if [ -z "${TAG}" ] || [ -z "${NAME}" ] || [ -z "${OS}" ] ; then exit 1 fi
if [ -z "$HOSTNAME" ] ; then HOSTNAME=$NAME fi
if [ $OS == "windows" ] ; then TAGS="hostname,desktop" else TAGS="hostname,hosts,desktop" fi
export ANSIBLE_CONFIG="/home/user/Documents/ansible/ansible.cfg" export ANSIBLE_VERBOSITY=0
/usr/bin/ansible-playbook
-i /home/user/Documents/ansible/inventory.py
-l "${NAME}"
-t "${TAGS}"
-e "hostname=${HOSTNAME}"
/home/user/Documents/ansible/playbooks/pentest/update.yml
### Máquina virtual - hook de inicio
De manera similar, el hook de inicio se ejecuta cuando una máquina virtual arranca. Normalmente se utiliza para lanzar servicios que la máquina virtual necesita.
Por ejemplo, para habilitar una integración perfecta con Windows dentro de la máquina virtual, puedes instalar `Xpra`.
Primero instala `ansible`:```
# apt install ansible
A continuación, ejecute el playbook de usuario ubicado en el directorio ansible. Antes de hacerlo, edite el archivo playbooks/user.yml para actualizar el hash de la contraseña y la clave pública SSH que se instalará en el directorio de inicio del usuario.```
~/mofos/ansible$ ls
ansible.cfg ansible.log inventory.sh playbooks
Admitimos una amplia gama de opciones para `list-unused` para **enumerar todos los permisos excedentes**, como:
- **La acción excedente es solo "read"** : `--excess-actions read`
- **Si solo quieres ver si hay acciones "write" sin usar**: `--excess-actions write`
- **Ver todos los permisos excedentes (potencialmente peligrosos)**: No necesitarás esto porque es el predeterminado
- **Para escanear permisos excedentes de un tipo de recurso específico**: Por ejemplo `--include-types sqs` o `--include-types s3,sqs,sns,ec2`
- **Para excluir un tipo de recurso del escaneo**: `--exclude-types rds`
- **Para escanear un rol específico**: `--include-roles MyRoleName`
- **Modificar el número de días para que un permiso se considere no utilizado**: Por defecto, la herramienta obtendrá los datos máximos disponibles (actualmente 90 días), y todos los permisos que no se usaron hasta el último día disponible se reportarán como no utilizados.
- **Pero, ¿qué pasa si el usuario verificó el último inicio de sesión en los últimos 30 días?**```
$ ansible-playbook playbooks/user.yml -l test2
Using /home/user/mofos/ansible/ansible.cfg as config file
[WARNING]: Found both group and host with same name: test
PLAY [Create and configure a user]
[...]
PLAY RECAP
test2 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Después, puedes iniciar sesión por SSH en esta cuenta de usuario, siempre que la configuración especifique a este usuario como el predeterminado:``` $ mofos ssh test2 user@DESKTOP-2BF9753:~$
A continuación, ejecuta el playbook `Xpra`. Este playbook instala paquetes desde los mirrors de Debian. Ten en cuenta que la red Mofos no configura DNS, proxy ni una puerta de enlace predeterminada por defecto. Estos deben configurarse antes de ejecutar el playbook.
No se requieren modificaciones al playbook por defecto.```
ansible-playbook playbooks/xpra.yml -l test2
Este playbook instala y configura Xpra e inicia el servicio xpra en la máquina virtual.
El servicio remoto puede iniciarse manualmente usando:``` user@DESKTOP-2BF9753:~$ systemctl --user start xpra
De lo contrario, el servicio se iniciará automáticamente en el próximo reinicio.
Luego, el servicio del cliente local también se puede iniciar manualmente:```
$ mofos xpra start test2
De vuelta en la máquina virtual, la pantalla debe estar configurada en :10 (el valor predeterminado), tras lo cual se puede iniciar una aplicación gráfica que aparecerá dentro del entorno de escritorio del host.```
user@DESKTOP-2BF9753:$ export DISPLAY=:10
user@DESKTOP-2BF9753:$ xterm
Para asegurar que este mecanismo funcione sin problemas y automáticamente, el comando `mofos xpra` puede iniciarse desde el hook de inicio.```bash
#!/bin/bash
TAG=$1
NAME=$2
OS=$3
DISTRIB=$4
HOSTNAME=$5
if [ -z "${TAG}" ] || [ -z "${NAME}" ] ; then
exit 1
fi
mofos xpra start "${NAME}"
Para estar informado del inicio y detención de las máquinas libvirt/qemu, el hook qemu de libvirt puede modificarse para especificar el nombre del usuario del host (por defecto user):```
### Portapapeles
Mofos también puede gestionar el portapapeles entre las máquinas virtuales y el host. La idea es configurar una combinación de teclas específica para activar una conexión SSH a la VM enfocada actualmente, ya sea para extraer el portapapeles X11 o para enviar contenido a él.
Para enviar contenido al portapapeles X11 de la máquina virtual:```
mofos clipboard in pentest-0
Para extraer contenido del portapapeles X11 de la máquina virtual:``` mofos clipboard out pentest-0
Para cada operación, mofos establecerá una conexión SSH a la máquina virtual y usará `xclip` y en el host `wl-copy` o `xclip` según la tecnología de ventanas (wayland vs X11).
El nombre de la máquina en el trace anterior puede omitirse; en ese caso, el script identificará la máquina virtual enfocada actualmente y la tomará como objetivo.
Si estás usando Gnome wayland, es posible que necesites instalar la extensión de shell de Gnome `[email protected]` con `sudo make install_gnome_extension`.
Tendrás que cerrar la sesión y volver a iniciarla para asegurarte de que la extensión queda instalada.
### Configurar el enrutamiento entre máquinas
En mofos existen dos opciones para enrutar una VM:
- `mofos route`, que toma una puerta de enlace y configura una `ip rule` en el host para enrutar la máquina virtual a través de esa puerta de enlace.
- `mofos pivot`, que toma otra máquina mofos, recupera su dirección IP y la configura como puerta de enlace predeterminada para la máquina virtual actual.
Ambas opciones pueden aceptar un servidor DNS para configurarlo.
### Configurar túneles a través de cajas de pentest
El comando `mofos tunnel` configura una VPN SSH (`ssh -w`) para enrutar el tráfico de una máquina mofos a través de un servidor. Esta funcionalidad depende de unas pocas configuraciones:
Concretamente, el comando `mofos tunnel` realiza las siguientes acciones (aquí no hay magia negra):
1. Crea una interfaz tun local (`sudo /usr/libexec/mofos/mofosnet.py tun add pentest_box`) y asigna una dirección IP a esta interfaz.
2. Ejecuta el `tunneling.command` en el servidor remoto; este comando debería crear una interfaz tun para luego enlazarla con la local (`/usr/libexec/mofos/mofosnet.py sshvpn start pentest_box`).
3. Enruta el tráfico de una máquina mofos a través de la puerta de enlace de la caja remota (`/usr/libexec/mofos/mofosnet.py route mofos_vm_ip gateway_ip`); la puerta de enlace predeterminada de la máquina virtual mofos también se cambia.
El `tunneling.command` debe definirse en el archivo de configuración `/etc/mofos/mofosnet.toml`. Por ejemplo:```toml
[tunneling.command]
start = "sudo ssh-vpn start" # the peer remote address will be supplied as argv[1]
stop = "sudo ssh-vpn stop"
En cuanto a los comandos route y pivot, también se puede proporcionar un DNS para configurarlo.
El comando mofos usb permite gestionar dispositivos USB.
Los dispositivos se identifican por su ID (vendor_id:product_id), que es necesario para los comandos attach y detach:```console $ mofos ls usb +-----------+------------------------------------------------+-------------+ | ID | Device | Attached to | +-----------+------------------------------------------------+-------------+ | 0bda:8153 | Realtek, RTL8153 Gigabit Ethernet Adapter | | | 046d:c077 | Logitech, Mouse | | | 0a5c:5842 | Broadcom Corp, 58200 | | | 1bcf:28d2 | CN0Y9V728LG003AGBCJZA01, Integrated_Webcam_FHD | | +-----------+------------------------------------------------+-------------+ $ mofos usb attach pentest-1 0bda:8153 $ mofos usb +-----------+------------------------------------------------+-------------+ | ID | Device | Attached to | +-----------+------------------------------------------------+-------------+ | 0bda:8153 | Realtek, RTL8153 Gigabit Ethernet Adapter | pentest-1 | | 046d:c077 | Logitech, Mouse | | | 0a5c:5842 | Broadcom Corp, 58200 | | | 1bcf:28d2 | CN0Y9V728LG003AGBCJZA01, Integrated_Webcam_FHD | | +-----------+------------------------------------------------+-------------+ $ mofos usb detach pentest-4 0bda:8153
La opción `force` desconecta y vuelve a conectar un dispositivo. Se usa normalmente para
volver a conectar un dispositivo que se ha desenchufado sin haber sido desconectado antes.
Nota: conectar un dispositivo USB solo es válido durante la vida actual de la máquina virtual. Cuando esta se detiene, el dispositivo se desconecta automáticamente.
### Gestión de dispositivos PCI
Al igual que con los dispositivos USB, mofos permite conectar un dispositivo PCI a una máquina virtual en ejecución; los comandos son los mismos.
Una limitación adicional afecta a algunos dispositivos PCI que pertenecen a un grupo. Por ejemplo, conectar la tarjeta Ethernet a una máquina virtual en ejecución puede requerir mover todo el grupo PCI dentro de la máquina virtual. Como no se puede hacer de forma secuencial, aún no está soportado. Sin embargo, para un dispositivo PCI único, como una tarjeta de red Wi-Fi, funciona correctamente.
### Carpetas compartidas
El comando `mofos mount` crea carpetas compartidas y puede montar el sistema de archivos recién agregado en un directorio dentro de la máquina virtual. `mofos umount` desmontará el directorio y eliminará las carpetas compartidas de la configuración de la máquina virtual.
Este mecanismo se basa en la tecnología `virtiofsd`, que requiere habilitar la memoria compartida; esto ahora se hace por defecto al crear una máquina virtual. De lo contrario, el siguiente comando la habilitará:```console
virt-xml -c qemu:///system --edit --memorybacking source.type=memfd,access.mode=shared DOMAIN
Además, las políticas de AppArmor proporcionadas restringen los directorios que el host puede compartir. Esto se hace para impedir que tu usuario configure un recurso compartido en el directorio /etc o en la raíz del sistema de archivos y lo modifique usando privilegios de root dentro de la máquina virtual. Por lo tanto, es necesario modificar la política usr.lib.qemu.virtiofsd para permitir compartir directorios arbitrarios.
Se deben adaptar dos líneas:``` @{SHARE_DIRS}=/data/libvirt/shares// /home/user/Public/**/ [...] pivot_root /data/libvirt/shares//, pivot_root /home/user/Public/**/,
La variable `SHARE_DIRS` se reutiliza en la política, sin embargo, debido a las limitaciones de apparmor, no es posible reutilizarla para las directivas `pivot_root`. Por lo tanto, es necesario adaptar manualmente las directivas `pivot_root` para cada uno de los directorios compartidos.
Para montar un directorio local:```
mofos mount test ./Public/share -d /home/user/share
Para no interrumpir la máquina virtual donde se va a montar el recurso compartido, si el directorio remoto no está vacío se emite una advertencia y el script le permite realizar manualmente la operación de montaje.
Finalmente, la operación de montaje no es persistente y debe volver a ejecutarse en cada reinicio.
Para crear máquinas virtuales Windows, primero debe crearse manualmente una máquina plantilla. El disco de esta plantilla se utiliza luego como archivo de respaldo para crear máquinas hijas. De forma predeterminada, las máquinas virtuales Windows creadas con Mofos no están preconfiguradas. Sin embargo, es posible configurar Mofos para realizar tareas de postconfiguración, como cambiar el nombre de host y añadir una entrada dedicada en el archivo known_hosts, mediante hooks.
Para habilitar la configuración posterior a la creación, son obligatorios los siguientes requisitos:
authorized_keys debe crearse en C:\Program Data\ssh\administrators_authorized_keys y con una ACL específica.```powershell
$admin_group = "Administrators"
$system = "SYSTEM"$acl = Get-Acl C:\ProgramData\ssh\administrators_authorized_keys $acl.SetAccessRuleProtection($true, $false) $administratorsRule = New-Object system.security.accesscontrol.filesystemaccessrule($admin_group,"FullControl","Allow") $systemRule = New-Object system.security.accesscontrol.filesystemaccessrule($system,"FullControl","Allow") $acl.SetAccessRule($administratorsRule) $acl.SetAccessRule($systemRule) $acl | Set-Acl
- OpenSSH debería configurarse con un shell `PowerShell` en lugar de `cmd.exe`.```powershell
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" `
-Name DefaultShell `
-Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" `
-PropertyType String `
-Force
$HOME/.local/share/mofos/ssh.json. Esto garantizará que se cree una entrada known_hosts correspondiente para cada nueva máquina con la clave de host de la plantilla.## Autocompletado
El autocompletado debería funcionar de fábrica para `bash` y `fish`. Para `zsh`, puede ser necesario ejecutar los siguientes comandos:```
autoload -Uz compinit
compinit
source /usr/share/zsh/vendor-completions/_mofos
Las máquinas virtuales basadas en el mismo disco de plantilla pueden obtener la misma dirección IP aunque la dirección MAC de su tarjeta de red cambie debido al identificador DHCP. Este comportamiento se puede cambiar editando la configuración de red de la plantilla:
Con systemd-networkd:``` [Match] Name=eth0
[Network] DHCP=yes MulticastDNS=no IPv6AcceptRA=no
[DHCP] ClientIdentifier=mac
Con interfaces de red heredadas `/etc/network/interfaces`:```
iface eth0 inet dhcp
client no