LUKS: cifrado de discos completos en Linux

LUKS (Linux Unified Key Setup) es el formato estándar de cifrado de bloques en Linux. No cifra ficheros individuales —eso es territorio de herramientas como gpg o age— sino el dispositivo de bloques completo: todo lo que se escribe en /dev/sdb queda cifrado antes de llegar al hardware físico. El sistema de ficheros, los metadatos, los nombres de fichero: nada es legible sin la clave.

El mecanismo subyacente es dm-crypt, un módulo del kernel que se inserta entre el dispositivo físico y el sistema de ficheros a través del device mapper. Cuando abres un volumen LUKS con cryptsetup luksOpen, el kernel crea un dispositivo virtual en /dev/mapper/<nombre> que descifra las lecturas y cifra las escrituras en tiempo real usando AES-XTS-plain64 por defecto (en Debian Bookworm, cryptsetup usa LUKS2 con Argon2id como KDF). Lo que hace LUKS como formato sobre dm-crypt es estandarizar la cabecera: los primeros sectores del dispositivo almacenan los parámetros del algoritmo, el salt, y hasta 32 key slots en LUKS2, cada uno conteniendo la master key cifrada con una passphrase o fichero de clave distinto. La master key en sí nunca cambia aunque cambies la passphrase —lo que cambia es el slot que la protege.

Cuándo tiene sentido: laptops con datos sensibles, servidores físicos en colocación donde alguien podría extraer el disco, dispositivos de backup externos. Cuándo no ayuda tanto: instancias cloud donde el hipervisor ya tiene acceso al bloque subyacente, o cuando la amenaza es un atacante con acceso a la máquina encendida, porque el dispositivo mapper ya está abierto. LUKS protege datos en reposo frente a acceso físico al dispositivo, nada más.

Si lo configuras mal —passphrase débil, copia de la cabecera sin proteger, keyfile con permisos 644— la protección es ilusoria. Y si pierdes todas las passphrases y no hay copia de la cabecera, los datos desaparecen para siempre. cryptsetup no tiene backdoor.

# Requisito: cryptsetup instalado
apt install cryptsetup

# --- 1. Preparar el dispositivo ---
# Sobrescribir con ceros aleatorios antes de formatear dificulta
# el análisis forense de qué sectores contienen datos reales.
# En discos grandes, al menos los primeros y últimos sectores.
dd if=/dev/urandom of=/dev/sdb bs=4M count=10 status=progress

# --- 2. Crear el volumen LUKS2 ---
# --cipher y --key-size son los valores por defecto en Bookworm,
# los ponemos explícitos para que el comando sea autodocumentado.
# Argon2id como KDF: resiste ataques de GPU mucho mejor que PBKDF2.
cryptsetup luksFormat \
  --type luks2 \
  --cipher aes-xts-plain64 \
  --key-size 512 \
  --hash sha256 \
  --iter-time 3000 \
  /dev/sdb

# El comando pide confirmación ("YES" en mayúsculas) y la passphrase.

# --- 3. Inspeccionar la cabecera ---
cryptsetup luksDump /dev/sdb
# Fíjate en "Keyslots": el slot 0 está activo, los demás vacíos.

# --- 4. Abrir el volumen ---
cryptsetup luksOpen /dev/sdb datos_sensibles
# Aparece /dev/mapper/datos_sensibles

# --- 5. Crear sistema de ficheros sobre el dispositivo virtual ---
mkfs.ext4 -L datos_sensibles /dev/mapper/datos_sensibles

# --- 6. Montar y usar ---
mkdir -p /mnt/datos
mount /dev/mapper/datos_sensibles /mnt/datos

# --- 7. Agregar un segundo slot con keyfile ---
# Útil para montaje automático al arranque sin passphrase interactiva.
dd if=/dev/urandom bs=512 count=4 of=/etc/luks/datos_sensibles.key
chmod 400 /etc/luks/datos_sensibles.key
# El directorio /etc/luks debe estar en el sistema raíz cifrado
# o en una ubicación con acceso restringido equivalente.

cryptsetup luksAddKey /dev/sdb /etc/luks/datos_sensibles.key
# Pide la passphrase existente para autorizar la operación.

# Verificar: ahora hay dos slots activos
cryptsetup luksDump /dev/sdb | grep "Keyslot"

# --- 8. Configurar montaje automático al arranque ---
# /etc/crypttab: nombre_mapper  dispositivo  keyfile  opciones
# "luks" indica LUKS2; sin keyfile pondríamos "none" y pediría
# passphrase en el arranque.
echo "datos_sensibles  /dev/sdb  /etc/luks/datos_sensibles.key  luks" \
  >> /etc/crypttab

# /etc/fstab: montar el mapper como cualquier otro dispositivo
echo "/dev/mapper/datos_sensibles  /mnt/datos  ext4  defaults  0  2" \
  >> /etc/fstab

# --- 9. Desmontar y cerrar correctamente ---
umount /mnt/datos
cryptsetup luksClose datos_sensibles
# Después de luksClose, /dev/mapper/datos_sensibles desaparece.
# Los datos en /dev/sdb son basura ilegible sin la clave.

# --- 10. Copia de seguridad de la cabecera LUKS (CRÍTICO) ---
# Si la cabecera se corrompe (fallo de disco, escritura accidental),
# los datos son irrecuperables. Esta copia se guarda en un lugar
# físicamente separado y cifrado.
cryptsetup luksHeaderBackup /dev/sdb \
  --header-backup-file /ruta/segura/sdb_luks_header.img

Qué está pasando en cada decisión importante

El --iter-time 3000 en luksFormat le dice a Argon2id cuántos milisegundos debe tardar la derivación de clave en tu hardware actual. Tres segundos es agresivo para un portátil pero razonable para un servidor que no se reinicia a menudo. El objetivo es que un atacante con una GPU de 2024 necesite semanas en lugar de horas para un ataque de diccionario.

La línea de dd if=/dev/urandom inicial no es paranoia: en un disco nuevo con sectores vacíos, un análisis del dispositivo cifrado puede revelar qué bloques nunca se han escrito, reduciendo el espacio de ataque. No es obligatorio, pero sí buena práctica.

Cuando ejecutas luksOpen, el kernel carga la master key en memoria del kernel (no del proceso), crea el nodo de dispositivo en /dev/mapper/ y desde ese momento cualquier I/O al mapper pasa por dm-crypt de forma transparente. El proceso mkfs.ext4 y el posterior mount no saben que hay cifrado: ven un dispositivo de bloques normal.

El esquema de dos slots —passphrase en slot 0, keyfile en slot 1— refleja un patrón real de producción: la passphrase sirve para recuperación manual en un datacenter; el keyfile permite que el sistema arranque desatendido desde un initramfs con acceso al fichero de clave. luksAddKey no crea una segunda clave maestra, sino un segundo wrapper que descifra la misma clave maestra. Por eso revocar un slot con luksKillSlot es suficiente para invalidar ese método de acceso sin re-cifrar el disco.

La entrada en /etc/crypttab la procesa systemd-cryptsetup-generator durante el arranque temprano, antes de que se monten los sistemas de ficheros. El generador crea unidades transitorias systemd-cryptsetup@<nombre>.service que puedes inspeccionar con systemctl list-units 'systemd-cryptsetup*'. Si el keyfile está en el sistema raíz cifrado (escenario habitual con cifrado completo del sistema), el initramfs necesita pedir la passphrase del root primero y luego los demás volúmenes se abren automáticamente.

El paso 10, la copia de la cabecera, no es opcional en producción. La cabecera LUKS vive en los primeros 16 MB del dispositivo (LUKS2); un dd accidental al inicio del disco, un fallo de escritura parcial, o incluso algunos errores de disco en esos sectores específicos destruyen para siempre el acceso a todos los datos. Guarda esa copia en un dispositivo separado, cifrado con GPG o en un volumen LUKS independiente.

[Ubuntu]: El instalador de Ubuntu y Debian ofrecen cifrado completo del disco durante la instalación, que configura automáticamente una partición /boot sin cifrar y un volumen LUKS para el resto, incluyendo la partición raíz. En Ubuntu 24.04 con la nueva instalación experimental, el esquema usa TPM2 para desbloqueo automático; en Debian el instalador sigue usando passphrase interactiva en el initramfs, que es más explícita y no depende de firmware.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio