Как стать автором
Обновить

Запуск Linux на устройствах Android без поддержки AVF

Уровень сложностиСредний
Время на прочтение6 мин
Количество просмотров1.3K
виртуальная машина Debian
виртуальная машина Debian

В этой статье я поделюсь своим опытом запуска Linux на рутованом non-Pixel телефоне с Android 15 (также работает с Android 14 с ядром 6.1) c помощью Crosvm, без поддержки AVF. С доступом в Интернет, SSH, GUI и общим каталогом. Мой телефон Xiaomi Poco C65 c Android 15. С выходом Android 13 на телефонах Google Pixel в платформу был добавлен Android Virtualization Framework (AVF), основанный на гипервизоре KVM и инструментарии Crosvm. Это позволило запускать виртуальные машины с Linux. В Android 15 для устройств Google Pixel был добавлен Linux-терминал.

Шаги для запуска Linux на Android

  1. Использование Crosvm: Для загрузки Debian я использую Crosvm. Файл Crosvm находится по пути: /apex/com.android.virt/bin Для доступа к этой директории требуется Root на устройстве.

  2. Компиляция ядра Linux ARM64: Сначала необходимо скомпилировать ядро Linux ARM64.

  3. Создание образа с дистрибутивом: Я рекомендую использовать Debootstrap для создания образа с дистрибутивом.

  4. Настройка Интернета: Поскольку настройка интернета из официального руководства не всегда работает, я использую Gvisor.

  5. Настройка SSH: настройка виртуального сетевого устройства Tap.

  6. GUI: Для графического интерфейса можно использовать Xserver XSDL для Android.

  7. Настройка общих папок: Общие папки настраиваются по инструкции к Crosvm.

Установка зависимостей

Для начала необходимо установить некоторые зависимости

Откройте терминал и выполните следующие команды:

$ sudo apt install build-essential debootstrap qemu-user-static gcc-aarch64-linux-gnu atftpd nfs-kernel-server fdisk libcap-dev libgbm-dev pkg-config protobuf-compiler bc bison flex libssl-dev make libc6-dev libncurses5-dev crossbuild-essential-arm64
$ rm -rf /usr/local/go && tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz

После этого добавьте путь к Go в Ваш ~/.bashrc:

export PATH=$PATH:/usr/local/go/bin

Сборка ядра

Скачайте tarball ядра с kernel.org:

$ tar -xvf linux-x.x.xx.tar.xz
$ cd linux-x.x.xx
$ make ARCH=arm64 defconfig

Затем включите необходимые настройки: CONFIG_VSOCKETS=y

$ make menuconfig
$ CROSS_COMPILE=aarch64-linux-gnu- make ARCH=arm64 -j 8

Кросс-компиляция gVisor Proxy

Сначала кросс-компилируем gVisor Proxy для aarch64:

git clone https://github.com/containers/gvisor-tap-vsock gvisor-tap-vsock-arm64
GOARCH=arm64 make

Затем кросс-компилируем gVisor Proxy для Android:

git clone https://github.com/containers/gvisor-tap-vsock gvisor-tap-vsock-android
GOOS=android GOARCH=arm64 make

Создание rootfs

Создайте файловую систему rootfs:

$ mkdir rootfs
$ dd if=/dev/zero of=debian.img bs=1M count=32000
$ sudo mkfs.ext4 debian.img
$ sudo mount debian.img rootfs/
$ sudo debootstrap --arch=arm64 buster rootfs/

Настройте hostname и DNS:

$ echo "vm" | sudo tee ./rootfs/etc/hostname
$ sudo mkdir -p ./rootfs/etc/systemd/resolved.conf.d/
$ sudo nvim ./rootfs/etc/systemd/resolved.conf.d/dns_servers.conf

Установите DNS-серверы:

[Resolve]

DNS=8.8.8.8 1.1.1.1

Создайте пользователя и завершите настройку:

$ sudo chroot ./rootfs /bin/bash
$ useradd -m -g sudo <usermane>
$ passwd <username>
$ chsh -s /bin/bash <username>
$ exit

Скопируйте gVisor Proxy в rootfs:

$ sudo mkdir -p ./rootfs/gvisor-tap-vsock
$ sudo cp -r ./gvisor-tap-vsock-arm64/bin/* ./rootfs/gvisor-tap-vsock/bin
$ sudo umount ./rootfs

Подготовка файлов

Соберите необходимые файлы в архив:

$ tar -czvf gvisor-tap-vsock-android.tar.gz ./gvisor-tap-vsock-android/bin/*

Настройка сети

Создайте скрипт для настройки TAP-интерфейса:

$ nvim network.sh

Добавьте в него следующие строки:

#!/data/data/com.termux/files/usr/bin/sh
# https://crosvm.dev/book/devices/net.html
ip tuntap add mode tap user $USER vnet_hdr crosvm_tap
ip addr add 192.168.10.1/24 dev crosvm_tap
ip link set crosvm_tap up
# routing
sysctl net.ipv4.ip_forward=1
HOST_DEV=$(ip route get 8.8.8.8 | awk -- '{printf $5}')
iptables -t nat -A POSTROUTING -o "${HOST_DEV}" -j MASQUERADE
iptables -A FORWARD -i "${HOST_DEV}" -o crosvm_tap -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i crosvm_tap -o "${HOST_DEV}" -j ACCEPT
# the main route table needs to be added
ip rule add from all lookup main pref 1

На Android настройка сети из документации Crosvm не работает. Проблема в том, что Android не добавляет основную таблицу маршрута в свою файловую систему. Чтобы исправить эту проблему, необходимо добавить основную таблицу маршрута:

ip rule add from all lookup main pref 1

Установите Termux из F-Droid

Затем выполните следующие команды:

# termux-setup-storage
# mkdir kvm

Скопируйте необходимые файлы в директорию /data/data/com.termux/files/home/kvm:

debian.img

gvisor-tap-vsock-android.tar.gz

network.sh

./linux-x.x.xx/arch/arm64/boot/Image

В Termux выполните:

# su
# cd /data/data/com.termux/files/home/kvm
# chmod +x network.sh
# ./network.sh

Затем распакуйте gVisor:

# cd /data/data/com.termux/files/home/kvm
# tar -xvf gvisor-tap-vsock-android.tar.gz
# cd gvisor-tap-vsock-android/bin
# su
# chmod +x gvproxy
# ./gvproxy -debug -listen vsock://:1024 -listen unix:///data/data/com.termux/files/home/kvm/network.sock

Запуск виртуальной машины с Debian

В новой сессии Termux выполните:

# su
# cd /apex/com.android.virt/bin
# ./crosvm run --disable-sandbox --net tap-name=crosvm_tap -s /data/data/com.termux/files/home/kvm/crosvm.sock --shared-dir "/data/data/com.termux/files/home/host_shared_dir:my_shared_tag:type=fs" -p 'init=/sbin/init' --rwroot /data/data/com.termux/files/home/kvm/debian.img /data/data/com.termux/files/home/kvm/Image --vsock 3 --mem 2048 --cpus 8

В гостевой системе

Внутри виртуальной машины выполните:

$ cd /gvisor-tap-vsock/bin
$ sudo chmod +x gvforwarder
$ sudo ./gvforwarder --debug &

Или:

$ sudo ./gvforwarder --debug > /dev/null 2>&1 &

Проверьте подключение:

$ ping 8.8.8.8

Для работы интернета необходимо включить точку доступа(раздачу интернета) и подключить какой либо девайс.

Настройка SSH

Внутри виртуальной машины выполните:

$ nvim network.sh

Добавьте в него следующие строки:

#!/bin/bash
# Replace with the actual network interface name of the guest
# (use "ip addr" to list the interfaces)
GUEST_DEV=enp0s5
sudo ip addr add 192.168.10.2/24 dev "${GUEST_DEV}"
sudo ip link set "${GUEST_DEV}" up
sudo ip route add default via 192.168.10.1
# "8.8.8.8" is chosen arbitrarily as a default, please replace with your local (or preferred global)
# DNS provider, which should be visible in `/etc/resolv.conf` on the host.
echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf

Замените enp0s5 на имя своего устройства

Затем выполните:

$ sudo chmod +x network.sh
$ sudo ./network.sh

Подключитесь по SSH

ssh <username>@192.168.10.2

Остановка виртуальной машины

В новой сессии Termux выполните:

# su
# cd /apex/com.android.virt/bin
# ./crosvm stop /data/data/com.termux/files/home/kvm/crosvm.sock

GUI с Xserver XSDL

В гостевой системе

Внутри виртуальной машины выполните:

$ sudo apt install tightvncserver, xfce4, xfce4-terminal, xfce4-goodies

В новой сессии Termux выполните:

# ssh -L 5901:127.0.0.1:5901 -C -N -l <username> 192.168.10.2

Установите Xserver XSDL app для android

Выполните команды со скрина приложения

Общие папки

В Termux выполните:

# mkdir host_shared_dir
# su
# cd /apex/com.android.virt/bin
# ./crosvm run --disable-sandbox --shared-dir "/data/data/com.termux/files/home/host_shared_dir:my_shared_tag:type=fs" -p 'init=/sbin/init' --rwroot /data/data/com.termux/files/home/kvm/debian.img /data/data/com.termux/files/home/kvm/Image

В гостевой системе

Внутри виртуальной машины выполните:

$ sudo su
$ mkdir /tmp/guest_shared_dir
$ mount -t virtiofs my_shared_tag /tmp/guest_shared_dir

Используйте /tmp/guest_shared_dir и /data/data/com.termux/files/home/host_shared_dir

Решение проблем

Ошибка: ping 8.8.8.8. Network is unreachable

Решение: sudo chmod +x gvforwarder

Ошибка: ERRO[0000] gvproxy exiting: cannot listen: listen unix /data/data/com.termux/files/home/kvm/network.sock: bind: address already in use

Решение: Удалить файл network.sock

Ошибка: ERRO[0000] gvproxy exiting: cannot add network services: listen tcp 127.0.0.1:2222: bind: address already in use

Решение: Перезагрузите устройство

Ошибка: ERRO[0000] socket: address family not supported by protocol

Решение: CONFIG_VSOCKETS=y

Ошибка: ERRO[0000] dhcp not found

Решение: Создать дистрибутив с dhclient

Дополнительные возможности

Вы можете запустить несколько виртуальных машин, если разместите бинарный файл Crosvm в другую директорию с образом и ядром.

Заключение

В итоге, у меня есть ARM64 Linux в виртуальной машине на телефоне. Вы можете ознакомиться с моей инструкцией на моем [GitHub](https://github.com/bvucode/crosvm-on-android).

Теги:
Хабы:
+1
Комментарии1

Публикации

Работа

DevOps инженер
36 вакансий

Ближайшие события