macOS chạy bằng QEMU trong Docker
(github.com/sickcodes)- 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ườngSHORTNAMEvà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.imgtự 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:10022cho SSH- volume
/tmp/.X11-unixcho X11 DISPLAYSHORTNAMEđể 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=truevàMASTER_PLIST_URL - Các ví dụ Sonoma, Sequoia, Tahoe cũng bao gồm
CPU='Haswell-noTSX'và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 macOSsickcodes/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àalpinesickcodes/docker-osx:naked: gắn file.imgcủa người dùng để chạysickcodes/docker-osx:naked-auto: truyềnUSERNAME,PASSWORD,OSX_COMMANDSvào image của người dùng để tự động hóa SSH và thực thi lệnhsickcodes/docker-osx:big-sur,:monterey,:ventura,:sonoma,:high-sierra,:mojave: dùng để chạy phiên bản cụ thể
- Image
nakedphù 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 đó autovànaked-autocó 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:8888khi 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,virtlogdvà 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=truevào.wslconfig - Trong bản phân phối WSL, dùng
kvm-okđể kiểm tra/dev/kvmvà 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
- Trên Linux/Windows, mount rootfs của macOS vào không gian người dùng bằng dạng
- 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
- Truyền thư mục host vào container dưới dạng
- Cũng hướng dẫn chia sẻ NFS
- Đăng ký thư mục chia sẻ vào
/etc/exportstrên host - Khởi động container Docker-OSX bằng
--network host - Dùng
mount_nfstrong terminal macOS
- Đăng ký thư mục chia sẻ vào
- Khi Docker thiếu dung lượng đĩa, có thể chuyển
/var/lib/dockersang ổ 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ở
usbmuxdra cổng TCP5000 - 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 đó
- Kiểm tra bus và port bằng
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
- Xóa volume
- 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-ticketingtrong 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
- Kết nối bằng
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
SERIALBOARD_SERIALUUIDMAC_ADDRESSROMđượ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ạyGENERATE_SPECIFIC=true: dùng giá trị được chỉ định
./custom/generate-unique-machine-values.shcó 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
WIDTHvàHEIGHT- Cần dùng cùng
GENERATE_UNIQUE=truehoặcGENERATE_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ần dùng cùng
- 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
- Kết nối Internet nhanh:
- 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 dockerdsudo systemctl --start dockerdsudo 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
- Giá trị mặc định là
- 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
Ý 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
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
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 installhoặ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ỳ
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á
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
--recursivehoặc dùnggit 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
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 đủ
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
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
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
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 :)
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
https://github.com/steilerDev/icloud-photos-sync
https://github.com/icloud-photos-downloader/icloud_photos_do...
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
rsyncthư 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 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? ;)
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ó
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