3 puntos por GN⁺ 2024-08-01 | 1 comentarios | Compartir por WhatsApp
  • Docker-OSX ejecuta macOS basado en QEMU + KVM dentro de un contenedor Docker y ofrece salida X11, SSH, VNC, integración USB con iPhone y generación de seriales para investigación de seguridad de iMessage
  • La forma de ejecución consiste en pasar a Docker el dispositivo /dev/kvm, el socket de X11, el reenvío de puertos y la variable de entorno SHORTNAME para elegir la versión de macOS; incluye ejemplos desde Catalina 10.15 hasta Tahoe 16
  • La composición de imágenes se divide por propósito, como latest, auto, naked y naked-auto; se puede adjuntar un .img creado por el usuario o ejecutar tareas de línea de comandos con una imagen Catalina preconfigurada
  • Los requisitos son un host x86_64 con soporte KVM, virtualización activada en BIOS y al menos 20 GB de espacio en disco; con Xcode se requieren 50 GB y con :auto también se necesitan al menos 50 GB
  • Además de Linux, también puede ejecutarse en virtualización anidada de WSL2 en Windows 11 build 22000+, pero la salida de pantalla requiere configurar una de estas opciones: WSLg, VNC o un entorno de escritorio

Ejecutar macOS dentro de un contenedor Docker

  • Docker-OSX es un proyecto para ejecutar macOS dentro de un contenedor Docker
    • Funciona sobre QEMU + KVM
    • Soporta reenvío X11
    • Ofrece una configuración donde funciona el USB de iPhone
    • Indica que puede usarse para investigación de seguridad de macOS en Linux y Windows
  • El proyecto está construido sobre OSX-KVM y también menciona KVM-OpenCore y OpenCorePkg
  • También ofrece imagen en Docker Hub: sickcodes/docker-osx

Versiones de macOS soportadas y forma de inicio rápido

  • El inicio rápido consiste en pasar los siguientes elementos en docker run
    • --device /dev/kvm
    • -p 50922:10022 para SSH
    • volumen /tmp/.X11-unix para X11
    • DISPLAY
    • SHORTNAME para elegir la versión de macOS
  • Los destinos de ejecución incluidos en el README son los siguientes
    • High Sierra 10.13

    • Mojave 10.14

    • Catalina 10.15

    • Big Sur 11

    • Monterey 12

    • Ventura 13

    • Sonoma 14

    • Sequoia 15

      • Tahoe 16
      • Algunos ejemplos posteriores a Monterey usan GENERATE_UNIQUE=true junto con MASTER_PLIST_URL
      • Los ejemplos de Sonoma, Sequoia y Tahoe también incluyen CPU='Haswell-noTSX' y CPUID_FLAGS

Tipos de imágenes y propósito de uso

  • Docker-OSX ofrece imágenes de contenedor según el objetivo
    • sickcodes/docker-osx:latest: para probar rápido o crear tu propia imagen de macOS
    • sickcodes/docker-osx:auto: usa un sistema Catalina preconfigurado; el nombre de usuario es user y la contraseña alpine
    • sickcodes/docker-osx:naked: ejecuta adjuntando un archivo .img del usuario
    • sickcodes/docker-osx:naked-auto: automatiza SSH y ejecución de comandos en una imagen del usuario pasando USERNAME, PASSWORD y OSX_COMMANDS
    • sickcodes/docker-osx:big-sur, :monterey, :ventura, :sonoma, :high-sierra, :mojave: para ejecutar versiones específicas
  • La imagen naked está pensada para iniciar repetidamente una imagen de disco existente o restaurar el contenedor a un estado anterior
  • auto y naked-auto pueden usarse para tareas centradas en línea de comandos o trabajos sin interfaz, como builds basados en Homebrew

Funciones principales

  • Las funciones indicadas por Docker-OSX son las siguientes
    • Uso de iPhone en OSX KVM en Linux mediante usbfluxd
    • Ejecución de VM de macOS Monterey
    • Compartición de carpetas
    • USB passthrough y hotplug
    • SSH habilitado: localhost:50922
    • VNC habilitado: con la versión ./vnc, localhost:8888
    • serial number generator para investigación de seguridad de iMessage
    • Reenvío X11
    • Soporte para Big Sur, imágenes personalizadas y modo headless con Xvfb
    • Posibilidad de clonar el contenedor con docker commit
  • También soporta Kubernetes y señala que el Helm Chart y la documentación están en el directorio helm

Requisitos y configuración inicial

  • Los requisitos mínimos son los siguientes
    • 20 GB o más de espacio en disco
    • 50 GB si se usa Xcode
    • 50 GB como mínimo si se usa :auto
    • Virtualización habilitada en BIOS
    • Host x86_64 con soporte KVM
  • La configuración inicial consiste en instalar QEMU y dependencias relacionadas en el host, y luego habilitar libvirtd, virtlogd y los módulos del kernel KVM
  • Proporciona comandos de instalación de paquetes para Arch, Ubuntu/Debian y CentOS/RHEL/Fedora
  • En algunos casos, el usuario debe pertenecer a los grupos Docker, KVM y libvirt, y también verificar que el daemon de Docker esté en ejecución

Condiciones para ejecutarlo en Windows

  • Ejecutar Docker-OSX en Windows es posible en un entorno de Windows 11 + WSL2
    • Se requiere Windows 11 build 22000+, versión 21H2 o superior
    • Tras instalar WSL, se agrega nestedVirtualization=true a .wslconfig
    • En la distribución WSL, se verifica con kvm-ok si /dev/kvm y la aceleración KVM están disponibles
    • En Docker for Windows deben activarse el motor basado en WSL2 y la integración con la distribución WSL predeterminada
  • Los métodos de salida de pantalla se dividen en tres opciones
    • WSLg: la opción más simple y recomendada, aunque puede tener problemas con la entrega del teclado o mostrar un segundo cursor
    • VNC: usar la configuración de QEMU VNC o la sección de VNC
    • Desktop Environment: consume más recursos, pero ofrece una experiencia completa de escritorio Linux

Compartición de archivos y manejo de discos

  • Se propone sshfs como la forma más fácil y segura de compartir
    • En Linux/Windows se monta el rootfs de macOS en espacio de usuario con algo como sshfs user@localhost: -p 50922 ~/mnt/osx
  • También es posible compartir con QEMU 9p
    • Se pasa la carpeta del host al contenedor como /mnt/hostshare
    • Dentro de macOS se monta con sudo -S mount_9p hostshare
  • También se describe el uso de NFS
    • Se registra el directorio compartido en /etc/exports del host
    • El contenedor Docker-OSX se inicia con --network host
    • En la terminal de macOS se usa mount_nfs
  • Si falta espacio en disco para Docker, /var/lib/docker puede moverse a una unidad externa, almacenamiento en bloques o NFS, y luego crear un enlace simbólico
    • Se indica seguir ese tutorial solo si se acepta el riesgo de borrar las imágenes y capas actuales de Docker

USB de iPhone y USB passthrough

  • Para PCs de escritorio se enlaza aparte un método de USB passthrough de iPhone basado en VFIO
  • En laptops y PCs puede usarse USB passthrough por red mediante usbfluxd
    • En Linux se conecta el iPhone o iPad por USB
    • Se expone usbmuxd por el puerto TCP 5000
    • En el invitado macOS se conecta al host con algo como usbfluxd -f -r 172.17.0.1:5000
    • Se indica que, al cerrar y volver a abrir apps como Xcode, el dispositivo aparecerá
  • Para USB passthrough general se indica que QEMU debe iniciarse como root
    • Se identifica bus y puerto con lsusb -t
    • Se usan --privileged, /dev/kvm, EXTRA="-device ... usb-host ...", etc.
    • Mientras la VM está en ejecución, el sistema host no podrá acceder a ese dispositivo USB

Headless, VNC, SPICE y ejecución remota

  • La ejecución headless se hace quitando dos líneas relacionadas con X11 en docker run
    • Quitar el volumen /tmp/.X11-unix
    • Quitar la variable de entorno DISPLAY
  • Se indica que un contenedor headless basado en imágenes personalizadas puede ser útil en pipelines de CI/CD
  • VNC puede usarse solo en local, pero el README aclara que no tiene ningún cifrado TLS/HTTPS
    • Se indica que usar un túnel SSH y cerrar los puertos externos mejora la seguridad
  • También puede usarse SPICE
    • Se accede con remote-viewer spice://localhost:3001
    • Se advierte que -disable-ticketing en el ejemplo permite acceso a la VM sin autenticación, por lo que conviene revisar la configuración de autenticación del manual de SPICE

Números de serie e investigación de iMessage/iCloud

  • Para usar iMessage o iCloud se presentan los siguientes valores que deben cambiarse
    • SERIAL
    • BOARD_SERIAL
    • UUID
    • MAC_ADDRESS
    • Se explica que ROM es la dirección MAC en minúsculas sin dos puntos
  • Docker-OSX ofrece dos formas
    • GENERATE_UNIQUE=true: genera valores únicos en tiempo de ejecución
    • GENERATE_SPECIFIC=true: usa valores especificados
  • ./custom/generate-unique-machine-values.sh puede generar número de serie, dirección MAC, salida CSV/TSV e imagen de disco de arranque
  • Dentro de macOS se puede verificar el número de serie con ioreg -l | grep IOPlatformSerialNumber

Rendimiento, resolución y configuración de red

  • Se indica que osx-optimizer puede hacer que el contenedor sea más rápido
    • Saltar la pantalla de inicio de sesión GUI
    • Desactivar la indexación de Spotlight
    • Desactivar el fondo pesado de la pantalla de inicio de sesión
    • Desactivar actualizaciones
  • La resolución puede cambiarse con las variables de entorno WIDTH y HEIGHT
    • Deben usarse junto con GENERATE_UNIQUE=true o GENERATE_SPECIFIC=true
    • El arranque tarda unos 30 segundos más para crear una nueva partición de arranque
    • Una resolución inválida vuelve al valor predeterminado 800x600
  • El adaptador de red puede cambiarse por variable de entorno
    • Conexión rápida a internet: NETWORKING=vmxnet3
    • Conexión lenta a internet: NETWORKING=e1000-82545em
  • Se indica que activar el reenvío IPv4 en instalaciones remotas puede mejorar el rendimiento, pero que la IP del host podría filtrarse aunque se use una VPN dentro del contenedor

Solución de problemas y limitaciones

  • Si el daemon de Docker no está en ejecución, puede aparecer el error docker: unknown server OS: .
    • sudo dockerd
    • sudo systemctl --start dockerd
    • sudo systemctl --enable --now dockerd
  • No es posible asignar más RAM de la que tiene la máquina física
    • El valor predeterminado es -e RAM=3
    • Si se sobreasigna, puede aparecer el error cannot set up guest memory 'pc.ram': Cannot allocate memory
  • Los errores relacionados con ALSA pueden aparecer durante la inicialización del contenedor o el arranque, y se indica que no hay de qué preocuparse si el inicio y las funciones operan normalmente
  • En TODO todavía quedan estos puntos
    • Documentación para investigadores de seguridad
    • Aceleración por GPU
    • Soporte para virt-manager

Licencia y avisos

  • Docker-OSX está licenciado bajo GPL v3+
  • Se especifica que está permitido usar Docker-OSX como herramienta para crear software propietario
  • Incluye avisos relacionados con la investigación de seguridad de Apple y el Apple Bug Bounty Program, y enlaza un texto aparte sobre los temas legales de Hackintosh, OSX-KVM y Docker-OSX
  • Se indica que los nombres de productos, logotipos, marcas y marcas registradas mencionados en el proyecto son propiedad de sus respectivos dueños, y que esos titulares no están afiliados, ni patrocinan ni avalan el repositorio

1 comentarios

 
GN⁺ 2024-08-01
Opiniones en Hacker News
  • Para quienes realmente quieren usar el proyecto, esto es importante, pero no entiendo por qué tantas recetas de build como Dockerfile están hechas para descargar material arbitrario de internet durante el proceso de compilación.
    El Dockerfile de este proyecto también trae 2 repositorios Git y 1 script en tiempo de build.
    Por supuesto que falla en servidores de build en sandbox sin acceso a internet, y cualquiera que se preocupe aunque sea un poco por la seguridad tiene que auditar toda la receta de build antes de usarla.
    Ya no alcanza con revisar solo las dependencias indicadas en especificaciones de build como README, requirements.txt o package.json, y viendo las fallas recientes en infraestructura crítica y el aumento de ataques a la cadena de suministro, es una tendencia muy preocupante.

    • Detesto que los proyectos traigan archivos de build desde internet. Normalmente ocurre de forma inesperada, y no solo es un problema de seguridad: también hace mucho más difícil empaquetar el software que depende de eso.
      Aparecen sorpresas desagradables: problemas de versiones, falta de internet o, en el peor de los casos, que la dependencia ya no esté disponible. La distribución autocontenida debería ser lo predeterminado.
    • La respuesta es el churn de cambios. El área de DevOps cambia tanto que ya nadie tiene tiempo de entender cuál es la “forma correcta”.
    • El camino correcto es esperar a que grandes actores de open source como Red Hat, SUSE y Canonical hagan que los builds sean seguros.
      Fedora y openSUSE normalmente tienen políticas para que los paquetes del repositorio, incluidas las imágenes de contenedores y los paquetes de la distribución, se construyan solo con paquetes del repositorio o usen únicamente binarios agregados explícitamente durante el build.
      Por eso, si puedes instalarlo con dnf/zypper install o traerlo desde el registro de contenedores del proveedor, puedes confiar en los artefactos.
      Si necesitas lo último en bleeding edge, tienes que aceptar material arbitrario de internet.
      Es difícil que un desarrollador open source cualquiera produzca artefactos de build confiables, listos para usarse offline, y no existe esa infraestructura. Por eso existen empresas como Red Hat o SUSE.
      Las empresas de miles de millones de dólares están dispuestas a pagar para que alguien haga el trabajo de plomería y convierta artefactos arbitrarios de internet en artefactos confiables, reproducibles y firmados, además de hacer seguimiento de CVE y actualizaciones periódicas.
    • No veo en qué se diferencia de que JavaScript arrastre decenas de miles de dependencias solo para mostrar una página web.
      En los 80 se imaginaban componentes de software reutilizables y modulares que se encajaban como bloques de Lego, y entonces se llamaba CASE. Ahora eso se hizo realidad, pero por supuesto tiene un costo.
    • Probablemente la razón principal sea mantener la organización de la configuración en repositorios Git separados.
      Si no se hace clone desde el Dockerfile, se necesitan instrucciones previas al build del tipo “usa --recursive al clonar o trae otros repositorios al directorio de trabajo actual con git submodule init”.
  • La única posibilidad de aceleración por GPU es pasar una dGPU soportada mediante PCI passthrough. Las AMD RX 6xxx o superiores funcionan en macOS 14.x, pero con Nvidia moderna no hay posibilidad.
    Las iGPU de Intel funcionan hasta Comet Lake y algunas Ice Lake, pero las más nuevas no.
    macOS en builds para Apple Silicon parece difícil de emular por ahora, aunque hay algo de trabajo inicial sobre el arranque de ARM Darwin.
    Además, como AMD no tiene Intel VT-x, la virtualización se rompe en hosts AMD, pero con un hack raro usando una versión antigua de VirtualBox se puede hacer que Docker funcione en cierta medida mediante emulación.

    • En teoría, alguien podría crear un driver de pantalla para aceleración 3D de libvirt/kvm/qemu como los que existen en Windows y Linux. Entonces, aunque el rendimiento no sería óptimo, se podría usar rendimiento de GPU en casi cualquier GPU.
      AMD tiene su propia alternativa a VT-x, AMD-V, así que debería funcionar sin problemas. Eso sí, arrancar macOS en una CPU AMD tiene otros obstáculos, que normalmente se resuelven cargando kexts o con otros trucos.
      No entiendo bien el sentido de correr un sistema operativo completo con Docker. Bastaría con distribuirlo como OVA o en el formato de virtualización que prefieras. Probablemente un qcow2 y un script bash para iniciar la VM serían suficientes.
    • La parte de “como AMD no tiene Intel VT-x, la virtualización se rompe en hosts AMD”, ¿no se resuelve con AMD-V?
  • Artículos relacionados:
    Docker-OSX: Run macOS VM in a Docker - https://news.ycombinator.com/item?id=34374710 - enero de 2023, 110 comentarios
    macOS in QEMU in Docker - https://news.ycombinator.com/item?id=23419101 - junio de 2020, 186 comentarios

  • Lo configuré como experimento hace unos meses y funcionó bastante bien. Pero descubrí que, para que iMessage funcione, la aplicación envía a Apple el ID de hardware, y este proyecto usa valores falsos.
    A partir de ese momento empecé a deslizarme por la pendiente del “esto no va a salir bien”, y descubrí que los valores falsos pueden ser marcados por Apple, con el resultado de que el ID de iCloud quede señalado como potencial spammer y se restrinja el acceso desde otros dispositivos.
    La única opción es seguir probando valores con un script de generación de ID de hardware enlazado de forma algo ambigua hasta encontrar uno que “funcione”, pero no hay una señal clara de que realmente encaje bien y no dañe la reputación de iCloud.
    Fuera de eso, funcionó realmente bien y es muy útil en un apuro.

    • El método de “seguir cambiando el HWID hasta que funcione” también era común para hacer funcionar iMessage en Hackintosh. Se podía verificar si funcionaba en checkcoverage.apple.com.
      Pronto me di cuenta de que era más fácil copiar el Serial de una Mac real aunque fuera vieja.
      Dicho eso, esta herramienta parece más útil para cosas como scripts de build que dependen de frameworks propietarios de macOS, más que para usarla como una computadora personal.
    • Para investigación de seguridad, por lo general conviene no usar tu cuenta principal de iCloud ni ninguna otra cuenta principal.
  • Solo quiero probar si se puede compilar para iOS. Por ejemplo, cosas como Unity o React Native.
    Aunque la compilación tarde 5 veces más, en términos de libertad podría ser bastante genial.

    • Es muy probable que la compilación cruzada sea un mejor enfoque: https://github.com/tpoechtrager/osxcross
      Así es también como Godot compila para iOS: https://github.com/godotengine/build-containers/blob/main/Do...
      También hay una imagen de Docker con las herramientas preinstaladas, pero para apuntar a iOS requiere algunas modificaciones: https://github.com/shepherdjerred/macos-cross-compiler
      Cuando estaba en RStudio, ahora Posit, trabajé en compilación cruzada de C/C++/Fortran/Rust desde hosts Linux apuntando a macOS x86_64/aarch64.
      Si descargas desde Posit Package Manager(https://p3m.dev/client/) paquetes de R con código nativo, fueron compilados en forma cruzada de esta manera :)
    • Lo probé personalmente. Tuve que compartir de alguna forma el puerto USB más allá de Docker y, siguiendo las instrucciones del repositorio, era casi magia negra, pero después de compilar la app de iOS pude ejecutarla en un iPhone.
    • Sería impresionante si en este entorno sobre una máquina Windows se pudiera compilar React Native iOS con módulos Swift nativos y ejecutarlo en el simulador.
  • Hace un tiempo entrevisté a Sick Codes sobre el enfoque de este producto: https://www.vice.com/en/article/akdmb8/open-source-app-lets-...
    También está OSX-PROXMOX, que hace algo parecido en un homeserver con Proxmox: https://github.com/luchina-gabriel/OSX-PROXMOX
    Personalmente uso este último en un HP Z420 Xeon y es muy estable, especialmente si se le agrega GPU passthrough.

  • Sería bueno poder correr sincronización de iCloud en un homeserver. Actualmente no hay una buena forma de hacer backup físico de iCloud en un homeserver/NAS, y solo funciona en Windows/Apple.

    • Esto podría ayudar a sincronizar esos datos y luego guardarlos localmente o respaldarlos en otro lugar:
      https://github.com/steilerDev/icloud-photos-sync
      https://github.com/icloud-photos-downloader/icloud_photos_do...
    • Estoy trabajando en una solución usando OSX-Docker y OSXPhotos. Ya estoy bastante cerca, pero quería respaldar toda la información de iCloud incluyendo también los cambios de metadatos.
      Resulta que iCloud no actualiza las fotos originales. Se entiende, pero no ayuda a quien esperaba que esos cambios estuvieran incluidos al hacer el backup.
    • Me da curiosidad cómo esto ayudaría con ese problema. ¿Qué permitiría hacer de forma distinta en comparación con hacer rsync de la carpeta de iCloud desde una Mac/PC conectada hacia un NAS?
  • Me pregunto si la redistribución de imágenes de macOS está permitida por la licencia. ¿O este proyecto está distribuyendo abiertamente copias pirata en Docker Hub?

    • No lo sé, pero Corellium virtualizó instancias de iOS, Apple la demandó y luego llegaron a un acuerdo.
    • Esto es claramente ilegal.
  • Me pregunto si el avance se detendrá cuando salgan versiones más nuevas de macOS sin soporte para Intel.
    ¿Se puede ejecutar Docker dentro de este contenedor para correr macOS dentro de macOS? ;)

    • En teoría, siempre se puede ejecutar qemu en modo de emulación completa.
    • Se puede hacer simplemente así en cualquier programa de VM compatible.
  • Realmente odio cuando la expresión “USB passthrough” se usa para situaciones que, en el mejor de los casos, son “proxy de USB sobre Ethernet”.
    Eso no es passthrough. Tiene varias desventajas que no existen en el passthrough común y que quizá tampoco existan en el passthrough avanzado.

    • El passthrough USB de QEMU sí es USB passthrough real. Los problemas del passthrough USB vienen del propio controlador USB y de la forma en que se enumeran los dispositivos; la única solución mejor es hacer passthrough PCIe de todo el controlador USB.
      Pero ese enfoque trae otros problemas. Lo digo por experiencia operando grandes granjas de pruebas con VM y mucho hardware pasado directamente.
      Dicho eso, “proxy de USB sobre Ethernet” también es passthrough real; solo es passthrough con más latencia que VirtIO.