3 điểm bởi GN⁺ 2024-08-01 | 1 bình luận | Chia sẻ qua WhatsApp
  • Docker-OSX là dự án chạy macOS dựa trên QEMU + KVM bên trong container Docker, cung cấp đầu ra X11, SSH, VNC, tích hợp USB iPhone, tạo serial phục vụ nghiên cứu bảo mật iMessage, v.v.
  • Cách chạy có cấu trúc truyền thiết bị /dev/kvm, socket X11, chuyển tiếp cổng và biến môi trường SHORTNAME vào Docker để chọn phiên bản macOS; có ví dụ từ Catalina 10.15 đến Tahoe 16.
  • Các image được chia theo mục đích như latest, auto, naked, naked-auto; có thể gắn file .img tự tạo hoặc chạy tác vụ dòng lệnh bằng image Catalina đã cấu hình sẵn.
  • Yêu cầu gồm host x86_64 hỗ trợ KVM, bật ảo hóa trong BIOS, tối thiểu hơn 20GB dung lượng đĩa; cần 50GB khi dùng Xcode và tối thiểu 50GB khi dùng :auto.
  • Ngoài Linux, dự án cũng có thể chạy trên ảo hóa lồng nhau WSL2 của Windows 11 build 22000+, nhưng cần thiết lập một trong các cách xuất màn hình: WSLg, VNC hoặc môi trường desktop.

Chạy macOS bên trong container Docker

  • Docker-OSX là dự án chạy macOS bên trong container Docker
    • Hoạt động trên QEMU + KVM
    • Hỗ trợ chuyển tiếp X11
    • Cung cấp cấu hình để USB iPhone hoạt động
    • Cho biết có thể thực hiện nghiên cứu bảo mật macOS trên Linux và Windows
  • Dự án được xây dựng trên OSX-KVM, đồng thời nhắc đến KVM-OpenCore, OpenCorePkg
  • Cũng có image trên Docker Hub: sickcodes/docker-osx

Các phiên bản macOS được hỗ trợ và cách chạy nhanh

  • Quick Start dùng cách truyền các thành phần sau trong docker run
    • --device /dev/kvm
    • -p 50922:10022 cho SSH
    • volume /tmp/.X11-unix cho X11
    • DISPLAY
    • SHORTNAME để chọn phiên bản macOS
  • Các mục tiêu chạy có trong README như sau
    • High Sierra 10.13

    • Mojave 10.14

    • Catalina 10.15

    • Big Sur 11

    • Monterey 12

    • Ventura 13

    • Sonoma 14

    • Sequoia 15

      • Tahoe 16
      • Một số ví dụ từ Monterey trở về sau dùng chung GENERATE_UNIQUE=trueMASTER_PLIST_URL
      • Các ví dụ Sonoma, Sequoia, Tahoe cũng bao gồm CPU='Haswell-noTSX'CPUID_FLAGS

Các loại image và mục đích sử dụng

  • Docker-OSX cung cấp các container image theo từng mục đích
    • sickcodes/docker-osx:latest: dùng để thử nhanh hoặc tự tạo image macOS
    • sickcodes/docker-osx:auto: dùng hệ thống Catalina đã cấu hình sẵn, tên người dùng là user, mật khẩu là alpine
    • sickcodes/docker-osx:naked: gắn file .img của người dùng để chạy
    • sickcodes/docker-osx:naked-auto: truyền USERNAME, PASSWORD, OSX_COMMANDS vào image của người dùng để tự động hóa SSH và thực thi lệnh
    • sickcodes/docker-osx:big-sur, :monterey, :ventura, :sonoma, :high-sierra, :mojave: dùng để chạy phiên bản cụ thể
  • Image naked phù hợp với luồng khởi động lặp lại image đĩa hiện có hoặc đưa container về trạng thái trước đó
  • autonaked-auto có thể dùng cho các tác vụ thiên về dòng lệnh hoặc tác vụ headless như build dựa trên Homebrew

Tính năng chính

  • Các tính năng Docker-OSX nêu rõ gồm
    • Dùng iPhone OSX KVM trên Linux thông qua usbfluxd
    • Chạy VM macOS Monterey
    • Chia sẻ thư mục
    • USB passthrough và hot-plug
    • Bật SSH: localhost:50922
    • Bật VNC: localhost:8888 khi dùng phiên bản ./vnc
    • Nghiên cứu bảo mật iMessage thông qua serial number generator
    • Chuyển tiếp X11
    • Hỗ trợ Big Sur, image tùy chỉnh, chế độ headless Xvfb
    • Có thể nhân bản container bằng docker commit
  • Cũng hỗ trợ Kubernetes; Helm Chart và tài liệu được cho biết nằm trong thư mục helm

Yêu cầu và thiết lập ban đầu

  • Yêu cầu tối thiểu như sau
    • Dung lượng đĩa hơn 20GB
    • 50GB khi dùng Xcode
    • Tối thiểu 50GB khi dùng :auto
    • Bật ảo hóa trong BIOS
    • host x86_64 hỗ trợ KVM
  • Thiết lập ban đầu là cài QEMU và các phụ thuộc liên quan trên host, sau đó bật libvirtd, virtlogd và các mô-đun kernel KVM
  • Cung cấp riêng các lệnh cài đặt gói cho Arch, Ubuntu/Debian, CentOS/RHEL/Fedora
  • Trong một số trường hợp, người dùng cần thuộc các nhóm Docker, KVM, libvirt, và cũng cần kiểm tra trạng thái chạy của Docker daemon

Điều kiện chạy trên Windows

  • Chạy Docker-OSX trên Windows có thể thực hiện trong môi trường Windows 11 + WSL2
    • Cần Windows 11 build 22000+, 21H2 trở lên
    • Sau khi cài WSL, thêm nestedVirtualization=true vào .wslconfig
    • Trong bản phân phối WSL, dùng kvm-ok để kiểm tra /dev/kvm và khả năng dùng tăng tốc KVM
    • Trong Docker for Windows, cần bật engine dựa trên WSL2 và tích hợp bản phân phối WSL mặc định
  • Có 3 cách xuất màn hình
    • WSLg: tùy chọn đơn giản nhất và được khuyến nghị, nhưng có thể gặp vấn đề truyền bàn phím hoặc hiển thị chuột thứ hai
    • VNC: dùng QEMU VNC hoặc thiết lập trong phần VNC
    • Desktop Environment: dùng nhiều tài nguyên hơn nhưng cung cấp trải nghiệm desktop Linux đầy đủ

Chia sẻ file và vận hành đĩa

  • sshfs được đưa ra là cách chia sẻ dễ nhất và an toàn nhất
    • Trên Linux/Windows, mount rootfs của macOS vào không gian người dùng bằng dạng sshfs user@localhost: -p 50922 ~/mnt/osx
  • Cũng có thể chia sẻ bằng QEMU 9p
    • Truyền thư mục host vào container dưới dạng /mnt/hostshare
    • Mount trong macOS bằng sudo -S mount_9p hostshare
  • Cũng hướng dẫn chia sẻ NFS
    • Đăng ký thư mục chia sẻ vào /etc/exports trên host
    • Khởi động container Docker-OSX bằng --network host
    • Dùng mount_nfs trong terminal macOS
  • Khi Docker thiếu dung lượng đĩa, có thể chuyển /var/lib/docker sang ổ ngoài, block storage, NFS, v.v. rồi tạo symbolic link
    • Chỉ nên làm theo tutorial liên quan khi chấp nhận khả năng xóa các Docker image và layer hiện tại

USB iPhone và USB passthrough

  • Với desktop PC, dự án hướng dẫn riêng phương pháp passthrough USB iPhone dựa trên VFIO bằng liên kết riêng
  • Trên laptop, PC, v.v. có thể dùng USB passthrough qua mạng bằng usbfluxd
    • Kết nối iPhone hoặc iPad với Linux qua USB
    • Mở usbmuxd ra cổng TCP 5000
    • Trong guest macOS, kết nối đến host theo dạng usbfluxd -f -r 172.17.0.1:5000
    • Cho biết thiết bị sẽ xuất hiện nếu đóng rồi mở lại ứng dụng như Xcode
  • USB passthrough thông thường yêu cầu khởi động QEMU với quyền root
    • Kiểm tra bus và port bằng lsusb -t
    • Dùng --privileged, /dev/kvm, EXTRA="-device ... usb-host ...", v.v.
    • Trong lúc VM chạy, hệ thống host không thể truy cập thiết bị USB đó

Headless, VNC, SPICE, chạy từ xa

  • Chạy headless là cách xóa hai dòng liên quan đến X11 khỏi docker run
    • Xóa volume /tmp/.X11-unix
    • Xóa biến môi trường DISPLAY
  • Container headless dựa trên image tùy chỉnh được cho là hữu ích cho pipeline CI/CD
  • VNC có thể dùng chỉ cục bộ, nhưng README nêu rõ hoàn toàn không có mã hóa TLS/HTTPS
    • Cho biết sẽ an toàn hơn nếu dùng SSH tunnel và đóng các cổng bên ngoài
  • Cũng có thể dùng SPICE
    • Kết nối bằng remote-viewer spice://localhost:3001
    • -disable-ticketing trong ví dụ cho phép truy cập VM không cần xác thực, nên nên tham khảo thiết lập xác thực trong hướng dẫn SPICE

Serial number và nghiên cứu iMessage/iCloud

  • Các giá trị cần thay đổi để dùng iMessage hoặc iCloud được nêu như sau
    • SERIAL
    • BOARD_SERIAL
    • UUID
    • MAC_ADDRESS
    • ROM được giải thích là địa chỉ MAC viết thường đã bỏ dấu hai chấm
  • Docker-OSX cung cấp hai cách
    • GENERATE_UNIQUE=true: tạo giá trị duy nhất khi chạy
    • GENERATE_SPECIFIC=true: dùng giá trị được chỉ định
  • ./custom/generate-unique-machine-values.sh có thể tạo serial number, địa chỉ MAC, đầu ra CSV/TSV và image bootdisk
  • Có thể kiểm tra serial number trong macOS bằng ioreg -l | grep IOPlatformSerialNumber

Hiệu năng, độ phân giải, thiết lập mạng

  • Cho biết có thể dùng osx-optimizer để làm container nhanh hơn
    • Bỏ qua màn hình đăng nhập GUI
    • Tắt lập chỉ mục Spotlight
    • Tắt nền màn hình đăng nhập nặng
    • Tắt cập nhật
  • Có thể thay đổi độ phân giải bằng biến môi trường WIDTHHEIGHT
    • Cần dùng cùng GENERATE_UNIQUE=true hoặc GENERATE_SPECIFIC=true
    • Quá trình boot mất thêm khoảng 30 giây để tạo phân vùng boot mới
    • Độ phân giải không hợp lệ sẽ mặc định về 800x600
  • Có thể thay đổi network adapter bằng biến môi trường
    • Kết nối Internet nhanh: NETWORKING=vmxnet3
    • Kết nối Internet chậm: NETWORKING=e1000-82545em
  • Việc bật IPv4 forwarding khi cài đặt từ xa có thể cải thiện hiệu năng, nhưng cho biết IP host có thể bị rò rỉ ngay cả khi dùng VPN trong container

Khắc phục sự cố và hạn chế

  • Nếu Docker daemon không chạy, có thể gặp lỗi docker: unknown server OS: .
    • sudo dockerd
    • sudo systemctl --start dockerd
    • sudo systemctl --enable --now dockerd
  • Không thể cấp phát RAM nhiều hơn máy vật lý
    • Giá trị mặc định là -e RAM=3
    • Nếu cấp phát vượt mức, có thể gặp lỗi cannot set up guest memory 'pc.ram': Cannot allocate memory
  • Lỗi liên quan đến ALSA có thể xuất hiện khi khởi tạo container hoặc trong lúc boot; nếu boot và chức năng vẫn bình thường thì không cần lo lắng
  • TODO còn các mục sau
    • Tài liệu cho nhà nghiên cứu bảo mật
    • Tăng tốc GPU
    • Hỗ trợ virt-manager

Giấy phép và thông báo

  • Docker-OSX được cấp phép theo GPL v3+
  • Nêu rõ rằng việc dùng Docker-OSX làm công cụ để tạo phần mềm độc quyền là được phép
  • Bao gồm thông báo liên quan đến nghiên cứu bảo mật Apple và Apple Bug Bounty Program, đồng thời liên kết một bài viết riêng về vấn đề pháp lý của Hackintosh, OSX-KVM, Docker-OSX
  • Các tên sản phẩm, logo, thương hiệu, nhãn hiệu được nhắc đến trong dự án là tài sản của chủ sở hữu tương ứng; các chủ sở hữu nhãn hiệu đó không liên kết, tài trợ hoặc bảo chứng cho repository này

1 bình luận

 
GN⁺ 2024-08-01
Ý kiến trên Hacker News
  • Điều này quan trọng với những người thực sự muốn dùng dự án, nhưng tôi không hiểu vì sao lại có nhiều công thức build kiểu Dockerfile đến vậy được viết để tải các tài nguyên tùy ý từ Internet trong quá trình build
    Dockerfile của dự án này cũng lấy 2 kho Git và 1 script tại thời điểm build
    Không chỉ thất bại trên các máy chủ build sandbox bị chặn truy cập Internet, mà bất kỳ ai có chút quan tâm đến bảo mật cũng phải audit toàn bộ công thức build trước khi dùng
    Chỉ rà soát các dependency được ghi trong đặc tả build như README, requirements.txt hay package.json đã không còn đủ nữa; nhìn vào các sự cố hạ tầng cốt lõi gần đây và sự gia tăng của tấn công chuỗi cung ứng, đây là một xu hướng rất đáng lo ngại

    • Tôi thật sự ghét việc dự án kéo các file build từ Internet. Chuyện này thường xảy ra ngoài dự kiến, và ngoài vấn đề bảo mật, nó còn khiến việc đóng gói phần mềm phụ thuộc vào nó khó hơn nhiều
      Sẽ xuất hiện những bất ngờ khó chịu như vấn đề phiên bản, không có Internet, hoặc tệ nhất là dependency không còn được cung cấp nữa. Phân phối tự túc nên là mặc định
    • Câu trả lời là churn do thay đổi. Lĩnh vực DevOps thay đổi quá dữ dội đến mức giờ không ai còn thời gian để tìm ra “cách đúng” nữa
    • Hướng đi đúng là chờ các ông lớn nguồn mở như Red Hat, SUSE, Canonical làm cho build trở nên an toàn
      Fedora và openSUSE thường có chính sách yêu cầu build chỉ bằng các package trong repository, bao gồm package phân phối và container image, hoặc chỉ dùng các binary được thêm rõ ràng trong lúc build
      Vì vậy nếu có thể cài bằng dnf/zypper install hoặc lấy từ container registry của vendor, bạn có thể tin tưởng artifact đó
      Nếu cần bản bleeding edge mới nhất thì phải chấp nhận các tài nguyên tùy ý trên Internet
      Một developer nguồn mở bất kỳ khó có thể tạo ra artifact build sẵn sàng offline và đáng tin cậy, và họ không có hạ tầng như vậy. Đó là lý do các công ty như Red Hat hay SUSE tồn tại
      Các doanh nghiệp trị giá hàng chục tỷ đô sẵn sàng trả tiền để ai đó làm phần “đường ống”, biến các artifact tùy ý trên Internet thành artifact đáng tin cậy, tái lập được, có chữ ký, đồng thời theo dõi CVE và cập nhật định kỳ
    • Tôi không thấy khác gì việc JavaScript kéo theo hàng chục nghìn dependency chỉ để hiển thị một trang web
      Vào thập niên 80, người ta từng hình dung các component phần mềm tái sử dụng dạng module có thể lắp vào như khối Lego, khi đó gọi là CASE. Giờ thì điều đó đã thành hiện thực, nhưng tất nhiên phải trả giá
    • Lý do chính có lẽ là muốn giữ tổ chức cấu hình trong các kho Git riêng
      Nếu không clone trong Dockerfile, sẽ cần có chỉ dẫn trước khi build kiểu “khi clone hãy dùng --recursive hoặc dùng git submodule init để lấy các kho khác vào thư mục làm việc hiện tại”
  • Khả năng duy nhất để tăng tốc GPU là chuyển qua một dGPU được hỗ trợ bằng PCI passthrough. AMD RX 6xxx trở lên có thể dùng trên macOS 14.x, nhưng Nvidia hiện đại thì không có cửa
    Intel iGPU hoạt động đến Comet Lake và một số Ice Lake, nhưng mới hơn thì không
    macOS bản Apple Silicon có vẻ còn khó mô phỏng trong thời gian tới, dù đã có một chút công việc ban đầu về việc boot ARM Darwin
    Ngoài ra AMD không có Intel VT-x nên ảo hóa bị hỏng trên host AMD, nhưng bằng một kiểu hack kỳ quặc dùng VirtualBox bản cũ, có thể làm Docker chạy phần nào thông qua emulation

    • Về lý thuyết, ai đó có thể viết driver hiển thị cho tăng tốc 3D của libvirt/kvm/qemu giống như trên Windows và Linux. Khi đó dù hiệu năng không tối ưu, gần như GPU nào cũng dùng được sức mạnh GPU
      AMD có lựa chọn thay thế VT-x riêng là AMD-V, nên lẽ ra phải hoạt động không vấn đề. Tuy nhiên việc boot macOS trên CPU AMD còn có các trở ngại khác, thường được xử lý bằng cách nạp kext hoặc các mẹo khác
      Tôi không rõ ý nghĩa của việc chạy cả hệ điều hành bằng Docker. Chỉ cần phân phối dưới dạng OVA hoặc định dạng ảo hóa ưa thích là được. Có lẽ chỉ qcow2 và một bash script để khởi động VM cũng đủ
    • Phần “AMD không có Intel VT-x nên ảo hóa bị hỏng trên host AMD” chẳng phải có thể dùng AMD-V sao?
  • Bài liên quan:
    Docker-OSX: Run macOS VM in a Docker - https://news.ycombinator.com/item?id=34374710 - Tháng 1 năm 2023, 110 bình luận
    macOS in QEMU in Docker - https://news.ycombinator.com/item?id=23419101 - Tháng 6 năm 2020, 186 bình luận

  • Tôi đã thử thiết lập vài tháng trước và nó hoạt động khá tốt. Tuy nhiên để iMessage hoạt động, tôi phát hiện ứng dụng sẽ gửi hardware ID đến Apple, còn dự án này dùng giá trị giả
    Từ thời điểm đó, tôi bắt đầu trượt xuống con dốc “có vẻ không ổn”, và biết rằng các giá trị giả có thể bị Apple gắn cờ, khiến iCloud ID bị đánh dấu là spammer tiềm năng và bị hạn chế truy cập từ các thiết bị khác
    Lựa chọn duy nhất là tiếp tục thử các giá trị bằng script tạo hardware ID được liên kết khá mơ hồ để tìm một giá trị “hoạt động”, nhưng không có tín hiệu rõ ràng rằng nó thực sự khớp tốt và không làm hại uy tín iCloud
    Ngoài chuyện đó thì nó thật sự chạy tốt, và rất hữu ích khi cần gấp

    • Cách “cứ đổi HWID cho đến khi chạy được” cũng từng phổ biến để làm iMessage hoạt động trên Hackintosh. Có thể kiểm tra tình trạng hoạt động tại checkcoverage.apple.com
      Không lâu sau thì mọi người nhận ra sao chép Serial của một máy Mac thật, dù cũ, còn dễ hơn
      Tuy nhiên công cụ này có vẻ hữu ích hơn cho các trường hợp như build script phụ thuộc vào framework độc quyền của macOS, thay vì dùng như máy tính cá nhân
    • Với nghiên cứu bảo mật, nhìn chung không nên dùng tài khoản iCloud chính hoặc các tài khoản chính khác
  • Chỉ đơn giản muốn thử xem có thể build cho iOS hay không. Ví dụ như Unity, React Native chẳng hạn
    Dù thời gian build lâu hơn 5 lần thì xét về mặt mức độ tự do cũng có thể khá tuyệt

    • Cross-compile có lẽ là cách tiếp cận tốt hơn: https://github.com/tpoechtrager/osxcross
      Cách Godot build nhắm tới iOS cũng theo hướng này: https://github.com/godotengine/build-containers/blob/main/Do...
      Cũng có Docker image đã cài sẵn công cụ, nhưng để nhắm tới iOS thì cần chỉnh sửa một chút: https://github.com/shepherdjerred/macos-cross-compiler
      Khi còn ở RStudio, nay là Posit, tôi từng làm cross-compile C/C++/Fortran/Rust từ host Linux nhắm tới macOS x86_64/aarch64
      Nếu bạn tải xuống các gói R có native code từ Posit Package Manager(https://p3m.dev/client/) thì chúng được cross-compile theo cách này :)
    • Tôi đã tự thử rồi. Phải bằng cách nào đó chia sẻ cổng USB vượt qua Docker, và theo hướng dẫn trong repo thì gần như là hắc thuật, nhưng sau khi build ứng dụng iOS thì đã chạy được trên iPhone
    • Nếu có thể build React Native iOS có native Swift module trong môi trường này trên máy Windows và chạy trong simulator thì sẽ rất ấn tượng
  • Trước đây tôi từng phỏng vấn Sick Codes về sản phẩm này và cách tiếp cận của nó: https://www.vice.com/en/article/akdmb8/open-source-app-lets-...
    Cũng có OSX-PROXMOX làm việc tương tự trên homeserver Proxmox: https://github.com/luchina-gabriel/OSX-PROXMOX
    Cá nhân tôi đang dùng cái sau trên HP Z420 Xeon, và nó rất ổn định, đặc biệt khi gắn thêm GPU passthrough

  • Sẽ thật tốt nếu có thể chạy đồng bộ iCloud trên homeserver. Hiện không có cách tốt để backup vật lý iCloud vào homeserver/NAS, và nó chỉ hoạt động trên Windows/Apple

    • Những thứ này có thể giúp đồng bộ dữ liệu đó rồi lưu cục bộ hoặc backup sang nơi khác:
      https://github.com/steilerDev/icloud-photos-sync
      https://github.com/icloud-photos-downloader/icloud_photos_do...
    • Tôi đang làm một giải pháp dùng OSX-Docker và OSXPhotos. Đã khá gần rồi, nhưng tôi muốn backup toàn bộ thông tin trên iCloud, bao gồm cả thay đổi metadata
      Hóa ra iCloud không cập nhật ảnh gốc. Điều đó thì hiểu được, nhưng không giúp ích cho người kỳ vọng các thay đổi đó được đưa vào khi backup
    • Tôi tò mò việc này giúp gì cho vấn đề đó. So với việc rsync thư mục iCloud từ một Mac/PC được kết nối sang NAS, nó cho phép làm khác đi điều gì?
  • Tôi thắc mắc liệu tái phân phối image MacOS có được giấy phép cho phép hay không. Hay dự án này đang công khai phân phối bản sao lậu trên Docker Hub?

    • Tôi không chắc, nhưng Corellium đã ảo hóa các instance iOS, bị Apple kiện rồi sau đó dàn xếp
    • Cái này rõ ràng là bất hợp pháp
  • Tôi thắc mắc liệu mọi thứ có bị chững lại khi các phiên bản MacOS mới hơn bỏ hỗ trợ Intel hay không
    Có thể chạy Docker bên trong container này để chạy MacOS bên trong MacOS không? ;)

    • Về lý thuyết, lúc nào cũng có thể chạy qemu ở chế độ mô phỏng hoàn toàn
    • Cứ làm như vậy trong bất kỳ chương trình VM nào được hỗ trợ là được
  • Tôi rất ghét khi cụm “USB passthrough” được dùng cho tình huống thực chất nhiều nhất chỉ là “USB proxy qua Ethernet”
    Đó không phải passthrough. Nó có nhiều nhược điểm mà passthrough thông thường không có, và ngay cả passthrough nâng cao cũng có thể không có

    • QEMU USB passthrough là USB passthrough thật sự. Vấn đề của USB passthrough đến từ chính USB controller và cách liệt kê thiết bị; giải pháp tốt hơn duy nhất là PCIe passthrough toàn bộ USB controller
      Nhưng cách đó lại đem đến các vấn đề khác. Kinh nghiệm vận hành các trang trại kiểm thử VM quy mô lớn với nhiều phần cứng được chuyển tiếp cho thấy như vậy
      Tuy nhiên “USB proxy qua Ethernet” cũng là passthrough thật, chỉ là passthrough có độ trễ lớn hơn VirtIO mà thôi