miércoles, octubre 05, 2011

Debian mediante chroot en Android

Llevo tiempo sin escribir ningún artículo pero os aseguro que la espera ha valido la pena.

En esta ocasión vamos a instalar nuestra distro preferida en nuestro teléfono móvil, lo haremos mediante la técnica de "chrooting", de este modo conservaremos nuestro Android intacto y solo arrancaremos la Debian cuando lo deseemos.
Bueno dicho lo dicho empezamos:

Tendremos que ganar acceso root en nuestro terminal, este paso es diferente para cada móvil, para el mío(LG Optimus 2X) se puede hacer siguiendo este procedimiento.

Instalaremos un servidor ssh para acceder a nuestro Android de forma remota, el sshdroid funciona muy bien y además podremos encontrarlo de forma gratuita en el market.

Necesitaremos saber el esquema de particiones que tenemos en Android, para ello conectamos por ssh al móvil y empleamos el comando mount, buscamos la línea que corresponde con el punto de montaje /system:

/dev/block/mmcblk0p1 on /system type ext4 (ro,noatime,errors=continue,barrier=1,data=ordered)

El dato que debemos anotar es: /dev/block/mmcblk0p1

Ahora instalamos en la Debian de nuestra computadora un software llamado debootstrap y generamos el fichero de la Debian del chroot, este fichero puede tener el tamaño que deseemos, pero en mi caso como quiero poder almacenarlo en la tarjeta MicroSD(VFAT) será de 4Gb(el máximo tamaño en VFAT):

apt-get install debootstrap
dd if=/dev/zero of=debian.img bs=1024 count=3955078
mke2fs -F debian.img
mkdir debian
mount -o loop debian.img debian/
debootstrap --verbose --arch armel --foreign squeeze debian http://ftp.us.debian.org/debian
umount debian/
rm -r debian/


Con esto ya tenemos un fichero llamado debian.img con un sistema Debian mínimo, lo copiamos a la tarjeta MicroSD.

Para poder montar la imagen debemos poder escribir en la partición /system, por defecto se monta con permisos de solo eslectura, así que accedemos al móvil por ssh y ejecutamos:
mount -o remount,rw -t ext4 /dev/block/mmcblk0p1 /system

Montamos la imagen de Debian en /data/local/debian:
mkdir /data/local/debian
mount -t ext2 -o rw,noatime,nodiratime,loop /mnt/sdcard/_ExternalSD/debian.img /data/local/debian

Vinculamos proc y sysfs al entorno chroot:
mount -t proc /proc /data/local/debian/proc
mount -t sysfs /sysfs /data/local/debian/sys


Habilitamos el enrutado:
sysctl -w net.ipv4.ip_forward=1

Definimos DNS y /etc/hosts en el chroot:
echo "nameserver 8.8.8.8" > /data/local/debian/etc/resolv.conf
echo "nameserver 8.8.4.4" >> /data/local/debian/etc/resolv.conf
echo "127.0.0.1 localhost" > /data/local/debian/etc/hosts


Montamos las Tarjetas SD(tanto interna del móvil como la MicroSD):
mkdir /data/local/debian/mnt/sdcard
mkdir /data/local/debian/mnt/sdcard/_ExternalSD


mount --bind /mnt/sdcard/ /data/local/debian/mnt/sdcard
mount --bind /mnt/sdcard/_ExternalSD /data/local/debian/mnt/sdcard/_ExternalSD


Accedemos al entorno chroot:
chroot /data/local/debian /bin/bash

Terminamos la instalación e instalamos software interesante:
/debootstrap/debootstrap --second-stage
echo 'deb http://ftp.us.debian.org/debian
squeeze main' > /etc/apt/sources.list
apt-get install lxde tightvncserver ettercap-gtk nmap vim netcat

Nos pedirá la configuración de teclado.

apt-get autoclean
apt-get update


Salimos del chroot:
exit

Desmontamos el chiringuito:
umount /data/local/debian/mnt/sdcard/_ExternalSD
umount /data/local/debian/mnt/sdcard
umount /data/local/debian



Ya está ya tenemos una Debian chrooteada, así de fácil, cada vez que queramos acceder a ella tendremos que realizar el proceso de montaje de la imagen, vinculación de /proc /sysfs,......

Para automatizar esto he escrito un script que lo hace por nosotros.
cd /system/xbin/
vi bootdebian.sh

clear
echo " "
echo " "
echo " "
echo +---------------------------------------+
echo "|||| CyberDyne Systems ||||"
echo +---------------------------------------+
echo " "
echo " "
echo " "


echo "Montando /system como R/W"
mount -o remount,rw -t ext4 /dev/block/mmcblk0p1 /system

echo ----------------------------------------
echo "Definiendo variables"
export bin=/system/bin
export img=/mnt/sdcard/_ExternalSD/debian.img
export mnt=/data/local/debian
export PATH=$bin:/usr/bin:/usr/sbin:/bin:$PATH
export TERM=linux
export HOME=/root

if [ ! -d $mnt ]; then
mkdir $mnt
fi

echo ----------------------------------------
echo LISTADO VARIABLES:
echo BIN: $bin
echo IMG: $img
echo MNT: $mnt
echo PATH: $PATH
echo TERM: $TERM
echo HOME: $HOME
echo ----------------------------------------



echo ----------------------------------------
echo "Montando la imagen Debian"
echo "mount -t ext2 -o rw,noatime,nodiratime,loop $img $mnt"
busybox mount -t ext2 -o rw,noatime,nodiratime,loop $img $mnt

echo ----------------------------------------
echo "Vinculando pts, proc y sysfs al entorno chroot"
busybox mount -t devpts /dev/pts $mnt/dev/pts
busybox mount -t proc /proc $mnt/proc
busybox mount -t sysfs /sysfs $mnt/sys

echo ----------------------------------------
echo "Habilitando enrutado"
echo 1 > /proc/sys/net/ipv4/ip_forward
echo ----------------------------------------
echo "Definiendo DNS y /etc/hosts en el chroot"
echo "nameserver 8.8.8.8" > $mnt/etc/resolv.conf
echo "nameserver 8.8.4.4" >> $mnt/etc/resolv.conf
echo "127.0.0.1 localhost" > $mnt/etc/hosts

echo ----------------------------------------
echo "Montando /mnt/sdcard en el chroot"
if [ ! -d $mnt/mnt/sdcard ]; then
mkdir $mnt/mnt/sdcard
fi

busybox mount --bind /mnt/sdcard/ $mnt/mnt/sdcard


echo ----------------------------------------
echo "Montando /mnt/sdcard/_ExternalSD en el chroot"
if [ ! -d $mnt/mnt/sdcard/_ExternalSD ]; then
mkdir $mnt/mnt/sdcard/_ExternalSD
fi

busybox mount --bind /mnt/sdcard/_ExternalSD $mnt/mnt/sdcard/_ExternalSD



echo #####################################
echo "Entering The MATRIX... "
echo " "
chroot $mnt /bin/bash

echo " "
echo #####################################
echo "Saliendo The MATRIX... "
echo " "

echo ----------------------------------------
echo "Desmontando /mnt/sdcard/_ExternalSD en el chroot"
busybox umount $mnt/mnt/sdcard/_ExternalSD

echo ----------------------------------------
echo "Desmontando /mnt/sdcard en el chroot"
busybox umount $mnt/mnt/sdcard

echo ----------------------------------------
echo "Deshabilitando enrutamiento"
sysctl -w net.ipv4.ip_forward=0

echo ----------------------------------------
echo "Desvinculando pts, proc y sysfs del chroot"
busybox umount $mnt/dev/pts
busybox umount $mnt/proc
busybox umount $mnt/sys

echo ----------------------------------------
echo "Desmontando imagen Debian"
busybox umount $mnt

echo ----------------------------------------
echo "Remontando /system como solo lectura"
busybox mount -o remount,ro -t ext4 /dev/block/mtdblock3 /system
echo ----------------------------------------

Guardamos y salimos.

Le asignamos el 777 de la muerte:
chmod 777 /system/xbin/bootdebian.sh

Lo ejecutamos:
bootdebian.sh

Con todo esto tenemos una Debian totalmente operativa, pero vamos a ponerle la guinda al pastel consiguiendo las X en este sistema, yo personalmente no he sido capaz de arrancar las X dentro del chroot, lo que hago es arrancar un servidor VNC y conectar desde Android a la Debian del chroot.

Para arrancar el servidor VNC dentro del chroot es necesario definir cierta variable y eliminar ficheros de sesiones VNC anteriores:
export USER=root
rm /tmp/.X*-lock
rm /tmp/.X11-unix/X*
vncserver -geometry 800x480


Pedirá password

Para no tener que hacer esto cada vez que queremos arrancar el servicio nos creamos un mini-script:

vi vnc.sh

#!/bin/bash
export USER=root
rm /tmp/.X*-lock 2>/dev/null
rm /tmp/.X11-unix/X* 2>/dev/null
vncserver -geometry 800x480

chmod +x vnc.sh
./vnc.sh

Ahora desde Android con algún cliente VNC del estilo androidVNC ya podremos conectar en local al servidor del chroot y obtendremos un bonito gestor de ventanas como respuesta ;)

Cuando se salga del chroot hay que matar vnc y la sesión lxde:
vi kill_VNC.sh

#!/bin/bash

PIDS_VNC=$(pidof Xtightvnc)
echo -------------------------
echo Matando Procesos VNC
for i in $PIDS_VNC
do
echo Matando proceso: $i
kill $i
done

PIDS_LXDE=$(pidof lxsession)
echo -------------------------
echo Matando Procesos LXDE
for i in $PIDS_LXDE
do
echo Matando proceso: $i
kill $i
done
echo -------------------------

chmod +x kill_VNC.sh

Ahun así cuando se sale no es capaz de desmontar la imagen de Debian pero si se entra y se sale de nuevo suele funcionar.
Misterios de la vida.....

Bueno esto es todo, espero que le saqueis provecho a todo esto y recordad que tener Linux instalado en el móvil es como llevar siempre encima un micro portatil ;)))

7 comentarios:

jvicent dijo...

Hola,

Antes que nada felicitarte por tu gran artículo. Estoy probando paso a paso tus líneas de comando pero me he parado una especialmente, porque tengo dudas.

mount -o remount,rw -t ext4 /dev/block/mmcblk0p1 /system

no sería ext3?, me he parado antes de seguir, porque estoy un poco acojonado.

Gracias por hacer esto.
Vicent.

Kr0m dijo...

Hola jvicent

Gracias por apreciar mi artículo, siempre me anima que a alguien le resulte útil lo que publico.

Por otra parte comentarte que ext3 o ext4 depende de la ROM que tenga cargada el móvil, la primera vez que hice el chroot tenía instalada la ROM Modaco, en esa ocasión la partición /system estaba en ext3, al pasar a MIUI está en ext4.

Si conectas por SSH al móvil y ejecutas el comando mount podrás ver una línea que corresponde con el punto de montaje /system en la cual podrás ver también el sistema de ficheros.

En cuanto al acojone, yo estuve a punto de quedarme sin juguete un par de veces pero hay una herramienta de recuperación que permite restaurar el firmware como venía de casa(StockROM), eso sí tarda lo suyo ya que tiene que cargar unos 700Mb.

Espero que te haya quedado claro, cualquier duda o sugerencia estaré encantado de responderte.

Un saludo.

sanreikaj dijo...

Hola como estas? estoy siguiendo el tutorial pero tengo este mensaje al momento de terminar la instalacion con el debootstrap

E: No pkgdetails available; either install perl, or build pkgdetails.c from source

He seguido todo paso a paso, que esta mal??

sanreikaj dijo...

Hola como estas? estoy siguiendo el tutorial pero tengo este mensaje al momento de terminar la instalacion con el debootstrap

E: No pkgdetails available; either install perl, or build pkgdetails.c from source

He seguido todo paso a paso, que esta mal??

Miguel dijo...

Podrías indicarme cómo conectarme mediante droidvnc? la dirección a la que hay que conectarse es localhost no? el puerto cual seria?
gracias y saludos

Miguel dijo...

Podrías indicarme cómo conectarme mediante droidvnc? la dirección a la que hay que conectarse es localhost no? el puerto cual seria?
gracias y saludos

Kr0m dijo...

Hola sanreikaj
El problema que tienes debe de ser alguna dependencia incumplida de perl.

En cuanto a ti Miguel la dirección es localhost y el puerto el que viene por defecto, si no recuerdo mal el 5900


Un saludo a todos.