Cifrado de datos en discos duros externos
Contents
Primeros pasos
De nuevo voy a cifrar los contenidos de un disco duro USB en el que voy a ir guardando los directorios de trabajo de los proyectos pasados en los que participé, que ya comienza a pesar demasiado como para llevarlo siempre en el disco duro del portátil. Por otro lado, los discos duros sólidos tienen menos capacidad que los de cabezas, por lo que quiero necesitar menos espacio.
Una opción es utilizar dispositivos loop pero dm-crypt sigue pareciendo la mejor solución para cifrar particiones e incluso poder meter el sistema raíz cifrado. Seguimos este HOWTO.
root@reborn:/home/acs# apt-get install cryptsetup hashalot root@reborn:/home/acs# modprobe dm_crypt root@reborn:/home/acs# modprobe dm_mod root@reborn:/home/acs# modprobe aes root@reborn:/home/acs# cat /proc/crypto name : aes .... type : cipher blocksize : 16 min keysize : 16 max keysize : 32 name : md5 .... type : digest blocksize : 64 digestsize : 16 root@reborn:/home/acs# umount /dev/sdb1 root@reborn:/home/acs# cryptsetup -y create granero /dev/sdb1 Enter passphrase: Verify passphrase: root@reborn:/home/acs# dmsetup ls granero (254, 0)
You now have a "virtual" block device called /dev/mapper/granero, which is mapped (through the crypt target) to /dev/sdb1.
root@reborn:/home/acs# mkfs -t ext3 /dev/mapper/granero
Automatizando el montaje
Es básico que sea sencillo de manejar el disco duro cifrado ya que dentro de unos meses no me acordaré de todo esto y no quiero tener que estas viniendo a leer esto cada vez que quiera utilizar el disco. Por ello he añadido a "fstab":
acs@reborn:~$ tail -3 /etc/fstab # crypto USB /dev/mapper/granerob /media/granerob ext3 defaults,noauto,user 0 0 /dev/mapper/graneroc /media/graneroc ext3 defaults,noauto,user 0 0
y basta con que enchufe el disco duro y reinicie el sistema:
/etc/init.d/cryptdisks restart
que utiliza la configuración en:
acs@reborn:~$ cat /etc/crypttab # <target name> <source device> <key file> <options> granerob /dev/sdb1 none cipher=aes graneroc /dev/sdc1 none cipher=aes
y luego solo hay que montar "/media/granerob" o "/media/graneroc" en función de como se haya detectado el disco usb ... ¿un poco cochino no? Vamos a buscar algo más elegante gracias a HAL.
Mucho ojo al meter la clave que si te equivocas en "/etc/init.d/cryptdisks restart" no dice nada pero luego no puedes acceder a los contenidos del disco.
Trabajando con HAL
HAL es la "Hardware Abstraction Layer" y es usada por el demonio "hald" para ir informando al sistema de los eventos de hardware que se van produciendo, entre ellos el de que un nuevo disco USB ha sido introducido. Si capturamos este evento cuando se pincha el disco USB podríamos hacer todo el proceso transparente de configuración y acceso al disco.
Los discos duros tienen un identificador de serie único. Lo podemos ver con HAL una vez enchufado el disco USB con:
acs@reborn:~$ hal-device > /tmp/info acs@reborn:~$ cat /tmp/info .... 1: udi = '/org/freedesktop/Hal/devices/storage_serial_Ext_Hard_Disk_S07I2501A00000308845_0_0' .... storage.serial = 'Ext_Hard_Disk_S07I2501A00000308845-0:0' (string) ...
HAL tiene mucha información, por ejemplo como localizar el disco en el sistema "block.device = '/dev/sdc'". Por ejemplo si queremos saber como montar el disco basta con:
acs@reborn:~$ hal-device /org/freedesktop/Hal/devices/storage_serial_Ext_Hard_Disk_S07I2501A00000308845_0_0 | grep block.device | cut -d\' -f2 /dev/sdc
y de forma más elegante
acs@reborn:tmp$ hal-get-property --udi /org/freedesktop/Hal/devices/storage_serial_Ext_Hard_Disk_S07I2501A00000308845_0_0 --key block.device /dev/sdc
y esto funcionará independientemente de que se identifique el disco a veces como "sdb" y a veces como "sdc" o "sdd" o lo que sea. Pero, ¿cómo sabemos cuando el disco se ha enchufado? El núcleo avisa con un evento a "udevd" de que hay un nuevo dispositivo disponible y udevd ejecuta las reglas asociadas a ese dispositivo. Para saber como "udev" identifica un dispositivo:
acs@reborn:~$ hal-device /org/freedesktop/Hal/devices/storage_serial_Ext_Hard_Disk_S07I2501A00000308845_0_0 | grep sysfs linux.sysfs_path = '/sys/block/sdc' (string) acs@reborn:~$ udevinfo --query=all --path=/sys/block/sdc P: /block/sdc N: sdc S: disk/by-id/usb-Ext_Hard_Disk_S07I2501A00000308845-0:0 S: disk/by-path/pci-0000:00:1d.7-usb-0:2:1.0-scsi-0:0:0:0 E: DEVTYPE=disk E: ID_VENDOR=Ext_Hard E: ID_MODEL=Disk E: ID_REVISION=0000 E: ID_SERIAL=Ext_Hard_Disk_S07I2501A00000308845-0:0 E: ID_SERIAL_SHORT=S07I2501A00000308845 E: ID_TYPE=disk E: ID_INSTANCE=0:0 E: ID_BUS=usb E: ID_PATH=pci-0000:00:1d.7-usb-0:2:1.0-scsi-0:0:0:0
Esta información no es útil para saber como crear el script que se ejecute sólo cuando se pinche este disco. Las reglas que ejecuta udevd se encuentran en:
acs@reborn:~$ tree /etc/udev/rules.d/ /etc/udev/rules.d/ |-- 00-init.rules ... |-- README `-- libmtp.rules -> ../libmtp.rules
Por ejemplo para informar a HAL de las cosas que pasan:
acs@reborn:~$ cat /etc/udev/rules.d/95-hal.rules # Have udev pass data over a socket to hal RUN+="socket:/org/freedesktop/hal/udev_event"
Tras reflexionar un poco, lo ideal sería que gnome-volume-manager que escucha siempre el bus DBUS de sesión por si hay nuevos dispositivos, se encargara de gestionar el montar dispositivos cifrados. Pero es algo muy específico y que aún no está soportado, y "gnome-volume-manager" no parece sencillo de extender con plugins. Y el tener un programa siempre funcionando aparte para montar dispositivos cifrados tampoco parece el sistema más adecuado. Lo ideal sería que "gnome-volume-manager" permitiera que se ejecutaran programas ante la aparición de nuevos dispositivos, algo que hace pero no para volúmenes de datos. Todo apunta a tendremos que trabajar a nivel de udev y crear un nuevo programa a ejecutar.
Configurando udev para la automatización total
Cuando se pincha un dispositivo se ejecutan los programas indicando la acción "add". Basta con poner este programa en el directorio "/etc/udev/rules.d/" para que se ejecute siempre que haya un evento de hardware comunicado por el núcleo. Son programas macro cuya ejecución debe de ser muy rápida. Estoy terminando de retocar un script que tendrá una pinta como:
# For automounting a crypted device
ACTION!="add", RUN+="/bin/sh -c 'echo NO ES ADD>> /tmp/CRYPTED', "GOTO="persistent_storage_end"
SUBSYSTEM!="block", GOTO="persistent_storage_end"
ENV{DEVTYPE} != "partition", RUN+="/bin/sh -c 'echo NO ES partition>> /tmp/CRYPTED', GOTO="persistent_storage_end"
# Montar aquí la partición ... habrá que dejar la clave en algún fichero protegido
LABEL="persistent_storage_end"