3 pontos por GN⁺ 2024-08-01 | 1 comentários | Compartilhar no WhatsApp
  • Docker-OSX é um projeto que executa macOS em um contêiner Docker com base em QEMU + KVM, oferecendo saída X11, SSH, VNC, integração USB com iPhone e geração de seriais para pesquisa de segurança do iMessage
  • O modo de execução passa para o Docker a estrutura com o dispositivo /dev/kvm, socket X11, redirecionamento de portas e a variável de ambiente SHORTNAME para selecionar a versão do macOS, com exemplos incluídos do Catalina 10.15 ao Tahoe 16
  • A composição das imagens é dividida por objetivo, como latest, auto, naked e naked-auto, permitindo anexar um .img criado pelo usuário ou executar tarefas de linha de comando com uma imagem Catalina pré-configurada
  • Os requisitos são host x86_64 com suporte a KVM, virtualização ativada na BIOS e pelo menos 20 GB de espaço em disco; com Xcode são necessários 50 GB, e o uso de :auto também exige no mínimo 50 GB
  • Além do Linux, também pode ser executado em virtualização aninhada do WSL2 no Windows 11 build 22000+, mas a saída de vídeo exige configurar WSLg, VNC ou um ambiente desktop

Executando macOS dentro de um contêiner Docker

  • Docker-OSX é um projeto para executar macOS dentro de um contêiner Docker
    • Funciona sobre QEMU + KVM
    • Suporta encaminhamento X11
    • Oferece uma configuração com USB de iPhone funcional
    • Indica que é possível fazer pesquisa de segurança de macOS em Linux e Windows
  • O projeto foi construído sobre OSX-KVM e também menciona KVM-OpenCore e OpenCorePkg
  • Também há imagens no Docker Hub: sickcodes/docker-osx

Versões de macOS suportadas e modo de execução rápida

  • O Quick Start usa docker run passando os seguintes elementos
    • --device /dev/kvm
    • -p 50922:10022 para SSH
    • volume /tmp/.X11-unix para X11
    • DISPLAY
    • SHORTNAME para selecionar a versão do macOS
  • Os alvos de execução incluídos no README são os seguintes
    • High Sierra 10.13

    • Mojave 10.14

    • Catalina 10.15

    • Big Sur 11

    • Monterey 12

    • Ventura 13

    • Sonoma 14

    • Sequoia 15

      • Tahoe 16
      • Alguns exemplos a partir do Monterey usam GENERATE_UNIQUE=true junto com MASTER_PLIST_URL
      • Os exemplos de Sonoma, Sequoia e Tahoe também incluem CPU='Haswell-noTSX' e CPUID_FLAGS

Tipos de imagem e finalidade de uso

  • Docker-OSX oferece imagens de contêiner para diferentes finalidades
    • sickcodes/docker-osx:latest: para testar rapidamente ou criar sua própria imagem do macOS
    • sickcodes/docker-osx:auto: usa um sistema Catalina pré-configurado, com nome de usuário user e senha alpine
    • sickcodes/docker-osx:naked: executa anexando um arquivo .img que o usuário já possui
    • sickcodes/docker-osx:naked-auto: automatiza SSH e execução de comandos passando USERNAME, PASSWORD e OSX_COMMANDS para a imagem do usuário
    • sickcodes/docker-osx:big-sur, :monterey, :ventura, :sonoma, :high-sierra, :mojave: para executar versões específicas
  • A imagem naked é voltada para fluxos em que uma imagem de disco existente é inicializada repetidamente ou em que o contêiner é revertido ao estado anterior
  • auto e naked-auto podem ser usados para tarefas centradas em linha de comando ou trabalhos headless, como builds com Homebrew

Principais recursos

  • Os recursos declarados pelo Docker-OSX são os seguintes
    • Uso de iPhone com OSX KVM no Linux por meio do usbfluxd
    • Execução de VM macOS Monterey
    • Compartilhamento de pastas
    • USB passthrough e hotplug
    • SSH ativado em localhost:50922
    • VNC ativado em localhost:8888 ao usar a versão ./vnc
    • serial number generator para pesquisa de segurança do iMessage
    • Encaminhamento X11
    • Suporte a Big Sur, imagens personalizadas e modo headless com Xvfb
    • Possibilidade de clonar contêineres com docker commit
  • Também há suporte a Kubernetes, e o projeto informa que o Helm Chart e a documentação ficam no diretório helm

Requisitos e configuração inicial

  • Os requisitos mínimos são os seguintes
    • Mais de 20 GB de espaço em disco
    • 50 GB ao usar Xcode
    • No mínimo 50 GB ao usar :auto
    • Virtualização ativada na BIOS
    • Host x86_64 com suporte a KVM
  • A configuração inicial segue o fluxo de instalar QEMU e dependências relacionadas no host e depois ativar libvirtd, virtlogd e os módulos de kernel do KVM
  • São fornecidos comandos de instalação de pacotes para Arch, Ubuntu/Debian e CentOS/RHEL/Fedora
  • Em alguns casos, o usuário precisa pertencer aos grupos Docker, KVM e libvirt, além de verificar se o daemon do Docker está em execução

Condições para execução no Windows

  • A execução do Docker-OSX no Windows é possível em um ambiente Windows 11 + WSL2
    • É necessário Windows 11 build 22000+, versão 21H2 ou superior
    • Após instalar o WSL, adiciona-se nestedVirtualization=true em .wslconfig
    • Na distribuição WSL, usa-se kvm-ok para verificar se /dev/kvm e a aceleração KVM estão disponíveis
    • No Docker for Windows, é preciso ativar o engine baseado em WSL2 e a integração com a distribuição WSL padrão
  • Os métodos de saída de vídeo se dividem em 3 opções
    • WSLg: a opção mais simples e recomendada, embora possa haver problemas com envio do teclado ou exibição de um segundo cursor
    • VNC: usar a configuração de VNC do QEMU ou a seção de VNC
    • Desktop Environment: consome mais recursos, mas oferece uma experiência completa de desktop Linux

Compartilhamento de arquivos e gerenciamento de disco

  • O método de compartilhamento mais fácil e seguro sugerido é o sshfs
    • Em Linux/Windows, monta-se o rootfs do macOS no espaço do usuário com algo como sshfs user@localhost: -p 50922 ~/mnt/osx
  • Também é possível usar compartilhamento QEMU 9p
    • A pasta do host é passada ao contêiner como /mnt/hostshare
    • Dentro do macOS, monta-se com sudo -S mount_9p hostshare
  • O compartilhamento por NFS também é explicado
    • Registra-se o diretório compartilhado do host em /etc/exports
    • O contêiner Docker-OSX é iniciado com --network host
    • No terminal do macOS, usa-se mount_nfs
  • Quando falta espaço em disco para o Docker, é possível mover /var/lib/docker para um drive externo, armazenamento em bloco, NFS ou similar e depois criar um link simbólico
    • O projeto orienta seguir esse tutorial apenas se você aceitar a possibilidade de remover as imagens e camadas atuais do Docker

USB de iPhone e USB passthrough

  • Em PCs desktop, o método de USB passthrough de iPhone baseado em VFIO é indicado em um link separado
  • Em notebooks, PCs e outros dispositivos, pode-se usar USB passthrough em modo de rede com usbfluxd
    • No Linux, conecta-se o iPhone ou iPad via USB
    • Expõe-se o usbmuxd na porta TCP 5000
    • No guest macOS, conecta-se ao host com algo como usbfluxd -f -r 172.17.0.1:5000
    • O projeto informa que o dispositivo aparece ao fechar e abrir novamente aplicativos como Xcode
  • Para USB passthrough genérico, é informado que o QEMU precisa ser iniciado como root
    • Usa-se lsusb -t para verificar bus e porta
    • Utilizam-se --privileged, /dev/kvm, EXTRA="-device ... usb-host ..." e afins
    • Enquanto a VM estiver em execução, o sistema host não poderá acessar esse dispositivo USB

Headless, VNC, SPICE e execução remota

  • A execução headless é feita removendo duas linhas relacionadas ao X11 em docker run
    • remover o volume /tmp/.X11-unix
    • remover a variável de ambiente DISPLAY
  • O projeto indica que contêineres headless baseados em imagens personalizadas são úteis em pipelines de CI/CD
  • O VNC pode ser usado apenas localmente, mas o README declara explicitamente que não há qualquer criptografia TLS/HTTPS
    • O projeto orienta que usar túnel SSH e fechar portas externas torna o uso mais seguro
  • SPICE também pode ser usado
    • A conexão é feita com remote-viewer spice://localhost:3001
    • O exemplo com -disable-ticketing permite acesso à VM sem autenticação, então o projeto recomenda consultar o manual do SPICE para configurar autenticação

Números seriais e pesquisa com iMessage/iCloud

  • Para usar iMessage ou iCloud, os valores a serem alterados são os seguintes
    • SERIAL
    • BOARD_SERIAL
    • UUID
    • MAC_ADDRESS
    • ROM, descrito como o endereço MAC em minúsculas sem os dois-pontos
  • Docker-OSX oferece duas formas
    • GENERATE_UNIQUE=true: gera valores únicos em tempo de execução
    • GENERATE_SPECIFIC=true: usa valores especificados
  • ./custom/generate-unique-machine-values.sh pode gerar número serial, endereço MAC, saída CSV/TSV e imagem de disco de boot
  • Dentro do macOS, o número serial pode ser conferido com ioreg -l | grep IOPlatformSerialNumber

Desempenho, resolução e configuração de rede

  • O projeto informa que é possível deixar o contêiner mais rápido com osx-optimizer
    • Pular a tela de login da GUI
    • Desativar indexação do Spotlight
    • Desativar o plano de fundo pesado da tela de login
    • Desativar atualizações
  • A resolução pode ser alterada com as variáveis de ambiente WIDTH e HEIGHT
    • Devem ser usadas junto com GENERATE_UNIQUE=true ou GENERATE_SPECIFIC=true
    • O boot leva cerca de 30 segundos a mais para criar uma nova partição de inicialização
    • Resoluções inválidas voltam para o padrão 800x600
  • O adaptador de rede pode ser alterado por variável de ambiente
    • Conexão de internet rápida: NETWORKING=vmxnet3
    • Conexão de internet lenta: NETWORKING=e1000-82545em
  • Em instalações remotas, ativar o encaminhamento IPv4 pode melhorar o desempenho, mas o projeto avisa que o IP do host pode vazar mesmo se um VPN estiver em uso no contêiner

Solução de problemas e limitações

  • Se o daemon do Docker não estiver em execução, pode ocorrer o erro docker: unknown server OS: .
    • sudo dockerd
    • sudo systemctl --start dockerd
    • sudo systemctl --enable --now dockerd
  • Não é possível alocar mais RAM do que a máquina física possui
    • O valor padrão é -e RAM=3
    • Ao exceder isso, pode ocorrer o erro cannot set up guest memory 'pc.ram': Cannot allocate memory
  • Erros relacionados ao ALSA podem aparecer durante a inicialização do contêiner ou o boot, e o projeto informa que não há motivo para preocupação se a inicialização e os recursos estiverem funcionando normalmente
  • O TODO ainda inclui os seguintes itens
    • Documentação para pesquisadores de segurança
    • Aceleração por GPU
    • Suporte a virt-manager

Licença e avisos

  • Docker-OSX é licenciado sob GPL v3+
  • O projeto declara explicitamente que é permitido usar Docker-OSX como ferramenta para criar software proprietário
  • Inclui avisos relacionados à pesquisa de segurança da Apple e ao Apple Bug Bounty Program, além de um link para um texto separado sobre questões legais envolvendo Hackintosh, OSX-KVM e Docker-OSX
  • O projeto informa que os nomes de produtos, logos, marcas e trademarks mencionados pertencem a seus respectivos proprietários, e que esses detentores de marca não são afiliados ao repositório nem o patrocinam ou endossam

1 comentários

 
GN⁺ 2024-08-01
Opiniões no Hacker News
  • Para quem realmente pretende usar o projeto, isso é importante, mas não entendo por que tantas receitas de build como Dockerfiles são feitas para baixar materiais aleatórios da internet durante o processo de build
    O Dockerfile deste projeto também busca 2 repositórios Git e 1 script no momento do build
    Além de falhar, é claro, em servidores de build em sandbox sem acesso à internet, qualquer pessoa que se preocupe minimamente com segurança precisa auditar toda a receita de build antes de usá-la
    Já não basta revisar apenas as dependências descritas em especificações de build como README, requirements.txt ou package.json; considerando as recentes falhas em infraestruturas críticas e o aumento dos ataques à cadeia de suprimentos, essa é uma tendência muito preocupante

    • Eu realmente detesto quando um projeto puxa arquivos de build da internet. Normalmente acontece de forma inesperada e, além dos problemas de segurança, torna muito mais difícil empacotar o software que depende dele
      Surgem surpresas desagradáveis, como problemas de versão, falta de internet ou, no pior caso, a dependência deixar de estar disponível. Distribuição autossuficiente deveria ser o padrão
    • A resposta é churn de mudanças. A área de DevOps muda tanto que agora ninguém tem tempo para descobrir qual é o “jeito certo”
    • O caminho correto é esperar que grandes players de código aberto como Red Hat, SUSE e Canonical tornem os builds seguros
      Fedora e openSUSE geralmente têm políticas para que tudo, incluindo pacotes da distribuição e imagens de contêiner, seja buildado apenas com pacotes dos repositórios, ou use somente binários explicitamente adicionados durante o build
      Por isso, se você consegue instalar com dnf/zypper install ou baixar do registro de contêineres do fornecedor, pode confiar no artefato
      Se precisar do que há de mais bleeding edge, vai ter que aceitar materiais aleatórios da internet
      É difícil para um desenvolvedor open source qualquer produzir artefatos de build prontos para offline e confiáveis, e essa infraestrutura não existe. É por isso que empresas como Red Hat ou SUSE existem
      Empresas de bilhões de dólares pagam de bom grado para alguém fazer o trabalho de encanamento que transforma artefatos aleatórios da internet em artefatos confiáveis, reproduzíveis e assinados, além de acompanhar CVEs e fazer atualizações regulares
    • Não vejo diferença em relação a JavaScript puxando dezenas de milhares de dependências só para exibir uma página web
      Nos anos 80, imaginávamos componentes de software modulares e reutilizáveis que se encaixariam como blocos de Lego, e na época chamávamos isso de CASE. Agora isso meio que se realizou, mas obviamente há um preço
    • O principal motivo provavelmente é manter a organização da configuração em repositórios Git separados
      Se o Dockerfile não fizer o clone, seriam necessárias instruções pré-build do tipo “use --recursive ao clonar ou git submodule init para trazer outros repositórios para o diretório de trabalho atual”
  • A única possibilidade de aceleração por GPU é passar uma dGPU compatível via PCI passthrough. AMD RX 6xxx ou superior funciona no macOS 14.x, mas Nvidia moderna não tem chance
    iGPU da Intel funciona até Comet Lake e em parte de Ice Lake, mas nada mais novo que isso
    O macOS em builds para Apple Silicon parece difícil de emular por enquanto, e há algum trabalho inicial em boot do ARM Darwin
    Além disso, a AMD não tem Intel VT-x, então a virtualização quebra em hosts AMD, embora seja possível fazer o Docker funcionar até certo ponto por emulação usando um hack esquisito com uma versão antiga do VirtualBox

    • Em teoria, alguém poderia criar um driver de display para aceleração 3D de libvirt/kvm/qemu, como existe no Windows e no Linux. Assim, o desempenho não seria ideal, mas seria possível usar desempenho de GPU em praticamente qualquer GPU
      A AMD tem sua própria alternativa ao VT-x, o AMD-V, então isso deveria funcionar sem problemas. Mas há outros obstáculos para inicializar o macOS em CPU AMD, normalmente resolvidos carregando kexts ou com outros truques
      Não entendo muito o sentido de rodar um sistema operacional inteiro via Docker. Bastaria distribuir como OVA ou no formato de virtualização preferido. Um qcow2 e um script bash para iniciar a VM provavelmente já seriam suficientes
    • A parte “a AMD não tem Intel VT-x, então a virtualização quebra em hosts AMD” não seria resolvida com AMD-V?
  • Posts relacionados:
    Docker-OSX: Run macOS VM in a Docker - https://news.ycombinator.com/item?id=34374710 - janeiro de 2023, 110 comentários
    macOS in QEMU in Docker - https://news.ycombinator.com/item?id=23419101 - junho de 2020, 186 comentários

  • Configurei isso como experimento alguns meses atrás, e funcionou bem. Porém, para o iMessage funcionar, descobri que o aplicativo envia IDs de hardware para a Apple, e este projeto usa valores falsos
    A partir desse ponto comecei a escorregar pelo caminho do “acho que isso não vai dar certo”, e descobri que valores falsos podem ser marcados pela Apple e, como resultado, o ID do iCloud pode ser sinalizado como potencial spammer, restringindo o acesso a outros dispositivos
    A única opção é continuar tentando valores com um script de geração de ID de hardware linkado de forma meio vaga até encontrar um valor que “funcione”, mas não há um sinal claro de que ele realmente bateu bem e não vai prejudicar a reputação do iCloud
    Fora isso, funcionou muito bem e é extremamente útil em uma emergência

    • O método de “ficar trocando o HWID até funcionar” também era comum para fazer o iMessage funcionar em Hackintosh. Dava para verificar se funcionava em checkcoverage.apple.com
      Logo percebi que era mais fácil copiar o Serial de um Mac antigo, mas real
      Ainda assim, esta ferramenta parece mais útil para coisas como scripts de build que dependem de frameworks proprietários do macOS, do que para usar como um computador pessoal
    • Para pesquisa de segurança, em geral é melhor não usar a conta principal do iCloud nem outras contas principais
  • Quero apenas testar se consigo fazer build para iOS. Por exemplo, coisas como Unity e React Native
    Mesmo que o build demore 5 vezes mais, em termos de liberdade pode ser bem interessante

    • Compilação cruzada provavelmente é uma abordagem melhor: https://github.com/tpoechtrager/osxcross
      É também assim que o Godot faz build mirando iOS: https://github.com/godotengine/build-containers/blob/main/Do...
      Há também uma imagem Docker com as ferramentas pré-instaladas, mas para mirar iOS é preciso fazer alguns ajustes: https://github.com/shepherdjerred/macos-cross-compiler
      Quando eu estava na RStudio, hoje Posit, trabalhei em compilação cruzada de C/C++/Fortran/Rust em um host Linux mirando macOS x86_64/aarch64
      Se você baixa um pacote R com código nativo pelo Posit Package Manager(https://p3m.dev/client/), ele foi compilado de forma cruzada desse jeito :)
    • Eu mesmo testei. Tive que de algum modo compartilhar a porta USB através do Docker e, seguindo as instruções do repositório, parecia quase magia negra, mas consegui fazer o build de um app iOS e executá-lo no iPhone
    • Seria impressionante se desse para fazer build de React Native iOS com módulos Swift nativos nesse ambiente em uma máquina Windows e rodar no simulador
  • Entrevistei o Sick Codes no passado sobre essa abordagem de produto: https://www.vice.com/en/article/akdmb8/open-source-app-lets-...
    Também existe o OSX-PROXMOX, que faz algo parecido em um homeserver Proxmox: https://github.com/luchina-gabriel/OSX-PROXMOX
    Pessoalmente uso este último em um HP Z420 Xeon e ele é muito estável, especialmente com passthrough de GPU

  • Seria bom poder rodar sincronização do iCloud em um homeserver. Hoje não há um bom jeito de fazer backup físico do iCloud para um homeserver/NAS, e isso só funciona em Windows/Apple

    • Isto pode ajudar a sincronizar esses dados e depois armazená-los localmente ou fazer backup em outro lugar:
      https://github.com/steilerDev/icloud-photos-sync
      https://github.com/icloud-photos-downloader/icloud_photos_do...
    • Estou trabalhando em uma solução usando OSX-Docker e OSXPhotos. Cheguei bem perto, mas queria fazer backup de todas as informações do iCloud incluindo também alterações de metadados
      Pelo visto, o iCloud não atualiza as fotos originais. Faz sentido, mas não ajuda quem esperava que essas alterações fossem incluídas no backup
    • Fico curioso sobre como isso ajudaria nesse problema. O que isso permite fazer de diferente em comparação a usar rsync para copiar a pasta do iCloud de um Mac/PC conectado para o NAS?
  • Fico me perguntando se a redistribuição de imagens do macOS é permitida pela licença. Ou será que este projeto está distribuindo cópias piratas descaradamente no Docker Hub?

    • Não sei bem, mas a Corellium virtualizou instâncias de iOS, foi processada pela Apple e depois fez um acordo
    • Isso é claramente ilegal
  • Fico me perguntando se o progresso vai parar quando sair uma versão mais nova do macOS que não tenha mais suporte a Intel
    Dá para executar Docker dentro deste contêiner para rodar macOS dentro do macOS? ;)

    • Em teoria, sempre dá para rodar o qemu em modo de emulação completa
    • Dá para simplesmente fazer isso em qualquer programa de VM compatível
  • Eu realmente detesto quando a expressão “passthrough USB” é usada para uma situação que, na melhor das hipóteses, é um “proxy USB via Ethernet”
    Isso não é passthrough. Traz várias desvantagens que não existem no passthrough comum e talvez nem no passthrough avançado

    • O passthrough USB do QEMU é passthrough USB de verdade. Os problemas do passthrough USB vêm do próprio controlador USB e da forma como os dispositivos são enumerados, e a única solução melhor é fazer passthrough PCIe do controlador USB inteiro
      Mas esse método também traz outros problemas. Digo isso pela experiência de operar grandes fazendas de teste de VMs com muito hardware repassado
      Ainda assim, “proxy USB via Ethernet” também é passthrough de verdade; é apenas um passthrough com latência maior que VirtIO