3 ポイント 投稿者 GN⁺ 2024-08-01 | 1件のコメント | WhatsAppで共有
  • Docker-OSX は、Dockerコンテナ内で QEMU + KVM ベースの macOS を実行し、X11 出力、SSH、VNC、iPhone USB 連携、iMessage セキュリティ研究向けのシリアル生成などを提供する
  • 実行方式は、/dev/kvm デバイス、X11 ソケット、ポートフォワーディング、SHORTNAME 環境変数を Docker に渡して macOS バージョンを選択する構成で、Catalina 10.15 から Tahoe 16 までの例が含まれる
  • イメージ構成は latestautonakednaked-auto のように用途別に分かれており、自作した .img を接続したり、事前構成済みの Catalina イメージでコマンドライン作業を実行できる
  • 要件は x86_64 KVM 対応ホスト、BIOS の仮想化有効化、最低 20GB 以上のディスク容量で、Xcode 使用時は 50GB、:auto 使用時も最低 50GB が必要
  • Linux だけでなく、Windows 11 build 22000+ の WSL2 ネスト仮想化 でも実行可能だが、ディスプレイ出力は WSLg、VNC、デスクトップ環境のいずれかを設定する必要がある

Dockerコンテナ内で macOS を実行

  • Docker-OSX は macOS を Dockerコンテナ内で実行するプロジェクト
    • QEMU + KVM 上で動作する
    • X11 フォワーディングをサポートする
    • iPhone USB が動作する構成を提供する
    • Linux と Windows で macOS のセキュリティ研究を行えると案内している
  • プロジェクトは OSX-KVM をベースに作られており、KVM-OpenCoreOpenCorePkg にも言及している
  • Docker Hub イメージも提供されている: sickcodes/docker-osx

対応 macOS バージョンとクイックスタート

  • Quick Start は docker run で次の要素を渡す方式
    • --device /dev/kvm
    • SSH 用 -p 50922:10022
    • X11 用 /tmp/.X11-unix ボリューム
    • DISPLAY
    • macOS バージョン選択用 SHORTNAME
  • README に含まれる実行対象は次の通り
    • High Sierra 10.13

    • Mojave 10.14

    • Catalina 10.15

    • Big Sur 11

    • Monterey 12

    • Ventura 13

    • Sonoma 14

    • Sequoia 15

      • Tahoe 16
      • Monterey 以降の一部の例では GENERATE_UNIQUE=trueMASTER_PLIST_URL を併用する
      • Sonoma、Sequoia、Tahoe の例には CPU='Haswell-noTSX'CPUID_FLAGS も含まれる

イメージの種類と用途

  • Docker-OSX は用途別のコンテナイメージを提供する
    • sickcodes/docker-osx:latest: すぐに試したい場合や、自分で macOS イメージを作成する際に使用
    • sickcodes/docker-osx:auto: 事前構成済みの Catalina システムを使用し、ユーザー名は user、パスワードは alpine
    • sickcodes/docker-osx:naked: ユーザーが持つ .img ファイルを接続して実行
    • sickcodes/docker-osx:naked-auto: ユーザーイメージに USERNAMEPASSWORDOSX_COMMANDS を渡して SSH とコマンド実行を自動化
    • sickcodes/docker-osx:big-sur:monterey:ventura:sonoma:high-sierra:mojave: 特定バージョン実行用
  • naked イメージは、既存のディスクイメージを繰り返し起動したり、コンテナを以前の状態に戻したりするワークフローに向いている
  • autonaked-autoコマンドライン中心の作業 や Homebrew ベースのビルドのようなヘッドレス作業に使える

主な機能

  • Docker-OSX が明記している機能は次の通り
    • Linux で usbfluxd を使った iPhone OSX KVM 利用
    • macOS Monterey VM の実行
    • フォルダ共有
    • USB パススルーとホットプラグ
    • SSH 有効化: localhost:50922
    • VNC 有効化: ./vnc バージョン使用時は localhost:8888
    • serial number generator による iMessage セキュリティ研究
    • X11 フォワーディング
    • Big Sur、カスタムイメージ、Xvfb ヘッドレスモードのサポート
    • docker commit によるコンテナ複製が可能
  • Kubernetes もサポートしており、Helm Chart とドキュメントは helm ディレクトリにあると案内している

要件と初期設定

  • 最低要件は次の通り
    • 20GB 以上 のディスク容量
    • Xcode 使用時は 50GB
    • :auto 使用時は最低 50GB
    • BIOS で仮想化を有効化
    • x86_64 KVM 対応ホスト
  • 初期設定は、ホストに QEMU と関連依存関係をインストールした後、libvirtdvirtlogd、KVM カーネルモジュールを有効化する流れ
  • Arch、Ubuntu/Debian、CentOS/RHEL/Fedora 向けのパッケージインストールコマンドがそれぞれ用意されている
  • Docker、KVM、libvirt グループへの所属が必要な場合があり、Docker デーモンの実行状態も確認する必要がある

Windows での実行条件

  • Windows での Docker-OSX 実行は Windows 11 + WSL2 環境で可能
    • Windows 11 build 22000+、21H2 以上が必要
    • WSL インストール後、.wslconfignestedVirtualization=true を追加する
    • WSL ディストリビューションで kvm-ok を使って /dev/kvm と KVM アクセラレーションの利用可否を確認する
    • Docker for Windows で WSL2 ベースのエンジンと既定の WSL ディストリビューション統合を有効にする必要がある
  • 画面出力方法は 3 種類に分かれる
    • WSLg: 最も簡単で推奨される選択肢だが、キーボード入力の受け渡しや 2 個目のマウス表示に問題が出ることがある
    • VNC: QEMU VNC または VNC セクションの設定を使う
    • Desktop Environment: より多くのリソースを使うが、完全な Linux デスクトップ体験を提供する

ファイル共有とディスク運用

  • 最も簡単で安全な共有方法として sshfs を提示している
    • Linux/Windows で sshfs user@localhost: -p 50922 ~/mnt/osx の形で macOS rootfs をユーザー空間にマウントする
  • QEMU 9p 共有も可能
    • ホストフォルダを /mnt/hostshare としてコンテナに渡す
    • macOS 内で sudo -S mount_9p hostshare によりマウントする
  • NFS 共有も案内している
    • ホストの /etc/exports に共有ディレクトリを登録する
    • Docker-OSX コンテナは --network host で起動する
    • macOS ターミナルで mount_nfs を使用する
  • Docker のディスク容量が不足する場合は、/var/lib/docker を外付けドライブ、ブロックストレージ、NFS などに移動してからシンボリックリンクを作成できる
    • 現在の Docker イメージやレイヤーが削除される可能性を受け入れる場合にのみ、関連チュートリアルに従うよう案内している

iPhone USB と USB パススルー

  • デスクトップ PC では VFIO ベースの iPhone USB パススルー方法を別リンクで案内している
  • ノートPC や PC では usbfluxd を使ったネットワーク方式の USB パススルーを使用できる
    • Linux で iPhone または iPad を USB 接続する
    • usbmuxd を TCP ポート 5000 で公開する
    • macOS ゲストで usbfluxd -f -r 172.17.0.1:5000 の形でホストに接続する
    • Xcode のようなアプリを閉じて再度開くとデバイスが表示されると案内している
  • 一般的な USB パススルーは、QEMU を root で起動する必要があると案内している
    • lsusb -t で bus と port を確認する
    • --privileged/dev/kvmEXTRA="-device ... usb-host ..." などを使用する
    • VM 実行中はホストシステムがその USB デバイスにアクセスできない

ヘッドレス、VNC、SPICE、リモート実行

  • ヘッドレス実行は docker run から X11 関連の 2 行を削除する方式
    • /tmp/.X11-unix ボリュームを削除
    • DISPLAY 環境変数を削除
  • カスタムイメージベースのヘッドレスコンテナは CI/CD パイプラインに有用だと案内している
  • VNC はローカル専用で使えるが、README では TLS/HTTPS 暗号化が一切ない と明記している
    • SSH トンネルを使い、外部ポートを閉じれば安全性が高まると案内している
  • SPICE も利用可能
    • remote-viewer spice://localhost:3001 で接続する
    • 例の -disable-ticketing は認証なしの VM アクセスを許可するため、SPICE マニュアルの認証設定を参照するよう案内している

シリアル番号と iMessage/iCloud 研究

  • iMessage または iCloud の利用にあたって変更すべき値として次を挙げている
    • SERIAL
    • BOARD_SERIAL
    • UUID
    • MAC_ADDRESS
    • ROM はコロンを除いた小文字の MAC アドレスだと説明している
  • Docker-OSX は 2 つの方式を提供する
    • GENERATE_UNIQUE=true: 実行時に固有値を生成
    • GENERATE_SPECIFIC=true: 指定した値を使用
  • ./custom/generate-unique-machine-values.sh は、シリアル番号、MAC アドレス、CSV/TSV 出力、ブートディスクイメージを生成できる
  • ioreg -l | grep IOPlatformSerialNumber で macOS 内からシリアル番号を確認できる

パフォーマンス、解像度、ネットワーク設定

  • osx-optimizer を使ってコンテナを高速化できると案内している
    • GUI ログイン画面をスキップ
    • Spotlight インデックス作成を無効化
    • 重いログイン画面背景を無効化
    • 更新を無効化
  • 解像度は WIDTHHEIGHT 環境変数で変更できる
    • GENERATE_UNIQUE=true または GENERATE_SPECIFIC=true と併用する必要がある
    • 新しいブートパーティションを作成するため、起動に約 30 秒余分にかかる
    • 無効な解像度は 800x600 にフォールバックする
  • ネットワークアダプタは環境変数で変更できる
    • 高速なインターネット接続: NETWORKING=vmxnet3
    • 低速なインターネット接続: NETWORKING=e1000-82545em
  • リモート環境で IPv4 フォワーディングを有効にすると性能が改善する場合があるが、コンテナ内で VPN を使っていてもホスト IP が漏れる可能性があると案内している

トラブルシューティングと制約

  • Docker デーモンが実行中でない場合、docker: unknown server OS: . エラーが出ることがある
    • sudo dockerd
    • sudo systemctl --start dockerd
    • sudo systemctl --enable --now dockerd
  • RAM は物理マシン以上には割り当てられない
    • 既定値は -e RAM=3
    • 過剰に割り当てると cannot set up guest memory 'pc.ram': Cannot allocate memory エラーが出ることがある
  • ALSA 関連のエラーはコンテナ初期化時や起動中に表示される場合があるが、起動と機能が正常なら気にしなくてよいと案内している
  • TODO には次の項目が残っている
    • セキュリティ研究者向けドキュメント
    • GPU アクセラレーション
    • virt-manager サポート

ライセンスと告知

  • Docker-OSX は GPL v3+ でライセンスされている
  • Docker-OSX をプロプライエタリソフトウェア作成ツールとして使うことは許可されると明記している
  • Apple セキュリティ研究と Apple Bug Bounty Program に関する告知を含み、Hackintosh、OSX-KVM、Docker-OSX の法的問題についての別記事にもリンクしている
  • プロジェクト内で言及される製品名、ロゴ、ブランド、商標は各所有者の資産であり、当該商標権者はリポジトリと提携しておらず、後援や保証もしていないと案内している

1件のコメント

 
GN⁺ 2024-08-01
Hacker Newsのコメント
  • このプロジェクトを実際に使おうとする人にとって重要な点だが、なぜこれほど多くのDockerfileのようなビルドレシピが、ビルド過程でインターネット上の任意の素材をダウンロードするようになっているのか分からない
    このプロジェクトのDockerfileも、ビルド時にGitリポジトリ2つとスクリプト1つを取得する
    インターネットアクセスが遮断されたサンドボックス型ビルドサーバーで失敗するのはもちろん、少しでもセキュリティを気にする人なら使用前にビルドレシピ全体を監査しなければならない
    READMEやrequirements.txt、package.jsonのようなビルド仕様に書かれた依存関係だけを確認しても不十分になっており、最近の中核インフラ障害やサプライチェーン攻撃の増加を見ると非常に憂慮すべき流れだ

    • プロジェクトがビルドファイルをインターネットから引っ張ってくるのが本当に嫌いだ。たいてい予想外に起きるし、セキュリティ問題だけでなく、その上に依存するソフトウェアをパッケージ化するのもずっと難しくなる
      バージョンの問題が起きたり、インターネットがなかったり、最悪の場合は依存関係がもう提供されていなかったりといった不快なsurprisesが発生する。自己完結型の配布が基本であるべきだ
    • 答えは変化 churnだ。DevOpsの領域は変化が激しすぎて、もはや誰も「正しいやり方」を把握する時間がない
    • 正しい方向性は、Red Hat、SUSE、Canonicalのような大手オープンソースプレイヤーがビルドを安全にしてくれるのを待つことだ
      FedoraとopenSUSEは通常、配布パッケージやコンテナイメージを含め、リポジトリ内のパッケージだけでビルドするか、ビルド中に明示的に追加されたバイナリだけを使うようポリシーを設けている
      だからdnf/zypper installでインストールできるか、ベンダーのコンテナレジストリから取得できるなら、その成果物は信頼できる
      最新のbleeding edgeが必要なら、インターネット上の任意の素材を受け入れるしかない
      任意のオープンソース開発者がオフライン対応済みで信頼できるビルド成果物を作るのは難しく、そのためのインフラもない。だからこそRed HatやSUSEのような企業が存在する
      数十億ドル規模の企業は、誰かが配管作業を行ってインターネット上の任意の成果物を信頼可能で、再現可能で、署名付きの成果物に変え、CVEを追跡し、定期更新するためのコストを喜んで支払う
    • Webページを1つ表示するためにJavaScriptが数万の依存関係を引っ張ってくるのと何が違うのか分からない
      80年代には、レゴブロックのように組み合わせるモジュール式の再利用可能ソフトウェアコンポーネントが想像されていて、当時はCASEと呼ばれていた。今それが実現したわけだが、当然ながら代償は伴う
    • おそらく主な理由は、別個のGitリポジトリとして構成の整理を保ちたいからだろう
      Dockerfileでcloneしないなら、「clone時に--recursiveを使うか、git submodule initで別のリポジトリを現在の作業ディレクトリに持ってこい」というビルド前指示が必要になる
  • GPUアクセラレーションの唯一の可能性は、PCIパススルーでサポートされるdGPUを渡すことだ。AMD RX 6xxx以降はmacOS 14.xで可能だが、現代のNvidiaは見込みがない
    Intel iGPUはComet Lakeまで、一部のIce Lakeまで動くが、それより新しいものはだめ
    Apple SiliconビルドのmacOSは当面エミュレーションが難しそうで、ARM Darwinブートに関する初期作業は少しある
    またAMDにはIntel VT-xがないのでAMDホストでは仮想化が壊れるが、旧版VirtualBoxを使った奇妙なハックでDockerをエミュレーション経由である程度動かすことはできる

    • 理論上は、誰かがWindowsやLinuxにあるようなlibvirt/kvm/qemu向けの3Dアクセラレーション用ディスプレイドライバを作れるはずだ。そうなれば性能は最適ではなくても、ほぼすべてのGPUでGPU性能を使えるようになる
      AMDには独自のVT-x代替であるAMD-Vがあるので、問題なく動くはずだ。ただ、macOSをAMD CPUでブートするには別の難関があり、通常はkextの読み込みや他の裏技で解決する
      DockerでOS全体を動かす意味はあまり分からない。OVAや好みの仮想化形式で配布すればよい。qcow2とVM起動用のbashスクリプトだけでもたぶん十分だ
    • 「AMDにはIntel VT-xがないのでAMDホストでは仮想化が壊れる」という部分は、AMD-Vでいけるのでは?
  • 関連記事:
    Docker-OSX: Run macOS VM in a Docker - https://news.ycombinator.com/item?id=34374710 - 2023年1月、コメント110件
    macOS in QEMU in Docker - https://news.ycombinator.com/item?id=23419101 - 2020年6月、コメント186件

  • 数か月前に実験でセットアップしてみたが、かなりよく動いた。ただしiMessageを動かすにはアプリケーションがハードウェアIDをAppleに送信する必要があり、このプロジェクトが偽の値を使っていることを知った
    その時点から「これはまずそうだ」の滑り坂が始まり、偽の値がAppleにフラグされ、結果としてiCloud IDが潜在的スパマーとして扱われて他デバイスへのアクセスが制限される可能性があると分かった
    唯一の選択肢は、曖昧にリンクされたハードウェアID生成スクリプトで値を試し続けて「動く」ものを見つけることだが、それが実際に適切でiCloudの評判を傷つけないという明確なシグナルはない
    それ以外は本当によく動いたし、急ぎの時には非常に便利だ

    • 「動くまでHWIDを変え続ける」という方式は、HackintoshでiMessageを動かす時にもよく行われていた。checkcoverage.apple.comで動作確認できた
      やがて古いやり方になったが、実機MacのSerialをコピーするほうが簡単だと気づいた
      ただ、このツールは個人用コンピュータのように使うより、独占的なmacOSフレームワークに依存するビルドスクリプトのような用途により役立ちそうだ
    • セキュリティ研究では、通常はメインのiCloudアカウントや他の主アカウントを使わないほうがよい
  • 単に iOS 向けにビルドできるか試してみたいだけ。たとえば Unity や React Native のようなもの
    ビルドに 5 倍時間がかかったとしても、自由度という点ではかなり面白いかもしれない

    • クロスコンパイルのほうがより良いアプローチである可能性が高い: https://github.com/tpoechtrager/osxcross
      Godot が iOS 向けにビルドする方法もこちら: https://github.com/godotengine/build-containers/blob/main/Do...
      ツールがあらかじめ入った Docker イメージもあるが、iOS 向けにするには少し修正が必要: https://github.com/shepherdjerred/macos-cross-compiler
      RStudio、今の Posit にいた頃、Linux ホストから x86_64/aarch64 macOS 向けに C/C++/Fortran/Rust のクロスコンパイルをしていた
      Posit Package Manager(https://p3m.dev/client/) でネイティブコードを含む R パッケージをダウンロードすると、この方法でクロスコンパイルされたものになっている :)
    • 実際にやってみた。USB ポートを Docker 越しに何とか共有する必要があり、リポジトリの案内どおりに進めるとほとんど黒魔術のようだったが、iOS アプリのビルド後に iPhone で実行できた
    • Windows マシン上のこの環境で、ネイティブ Swift モジュールを含む React Native iOS をビルドしてシミュレータで実行できるなら印象的だと思う
  • 以前、Sick Codes とこの製品アプローチについてインタビューしたことがある: https://www.vice.com/en/article/akdmb8/open-source-app-lets-...
    Proxmox ホームサーバーで似たことをしてくれる OSX-PROXMOX もある: https://github.com/luchina-gabriel/OSX-PROXMOX
    個人的には HP Z420 Xeon で後者を使っているが、特に GPU パススルーを組み合わせると非常に安定している

  • ホームサーバーで iCloud 同期を動かせたらよさそう。現状、iCloud をホームサーバー/NAS に物理的にバックアップする良い方法がなく、Windows/Apple でしか動かない

    • これらはデータを同期したあとローカル保存や他所へのバックアップに役立つかもしれない:
      https://github.com/steilerDev/icloud-photos-sync
      https://github.com/icloud-photos-downloader/icloud_photos_do...
    • OSX-Docker と OSXPhotos を使う解決策を進めているところ。かなり近づいてはいるが、iCloud のすべての情報をバックアップしつつ、メタデータの変更も含めたかった
      調べてみると、iCloud は元の写真を更新しない。理屈はわかるが、バックアップ時にその変更が含まれることを期待していた人には助けにならない
    • これがその問題にどう役立つのか気になる。接続された Mac/PC 上の iCloud フォルダを NAS に rsync するのと比べて、何が違ってできるようになるのだろうか?
  • macOS イメージの再配布がライセンス上許可されるのか気になる。そうでなければ、このプロジェクトは Docker Hub で違法コピーを堂々と配布しているのだろうか?

    • よくは知らないが、Corellium は iOS インスタンスを仮想化し、Apple に訴えられたあと和解した
    • これは明らかに違法だ
  • Intel サポートが外れたさらに新しい macOS バージョンが出たら、進展が止まるのではないかと気になる
    このコンテナ内で Docker を動かして、macOS の中で macOS を動かせるのだろうか? ;)

    • 理論上は、いつでも qemu を 完全エミュレーションモードで動かせる
    • 対応している任意の VM プログラムで普通にそうできる
  • USB パススルー」という表現が、実際にはせいぜい「イーサネット経由の USB プロキシ」でしかない状況に使われるのが本当に嫌いだ
    それはパススルーではない。通常のパススルーにはないし、高度なパススルーでもないかもしれない、さまざまな欠点を持ち込む

    • QEMU の USB パススルーは本物の USB パススルーだ。USB パススルーの問題は USB コントローラ自体とデバイス列挙のやり方に由来し、より良い唯一の解決策は USB コントローラ全体を PCIe パススルーすることだ
      ただし、その方法にも別の問題がある。受け渡すハードウェアが多い大規模な VM テストファームを運用した経験からそう言える
      とはいえ、「イーサネット経由の USB プロキシ」も本物のパススルーではあり、VirtIO より遅延が大きいパススルーというだけだ