Montando partição criptografada usando pendrive como chave (systemd, LUKS)

A pouco tempo compartilhei minha experiência com mais um HDD defeituoso de um array de BTRFS RAID1 criptografado (LUKS), da remoção do disco defeituoso e reversão para modo single temporariamente, até a adição de novos HDDs para restabelecer o array em modo RAID1.

Decidi compartilhar desta vez como automatizar a montagem da partição agora que tirei um tempo para fazer alguns ajustes. O exemplo é para uma partição BTRFS mas com poucos ajustes funciona para qualquer sistema de arquivo que você venha a usar.

pendrive como chave

Qualquer pendrive formatado em fat32, vai servir, quanto mais pequeno melhor.:

# criando uma keyfile na partição
$ sudo dd if='/dev/random' bs=2048 count=1 of='/media/pendrive/.key'

# adicionando a keyfile como chave LUKS,
# dependendo de como você criou ou vai ser 
# o disco (/dev/sdx) ou uma partição (/dev/sdxn) ou 
# um volume lógico (/dev/vgn/lvn).
$ sudo cryptsetup -v luksAddKey '/dev/sdx' '/media/pendrive/.key'

caracteristicas deste esquema via systemd

Este método não é uma montagem automática tradicional via x-systemd.automount, pelos seguintes motivos:

  1. A montagem no boot acontece entre “local-fs-pre.target” e “local-fs.target”, antes de default.target afetando o tempo de boot até graphical.target. Prefiro que eu já possa ir abrindo um navegador, terminal, etc enquanto a partição monta.
  2. Segura o boot tentando montar a partição se algo não estiver certo. Prefiro que o boot siga normalmente se não for possível montar a partição.
  3. Toda vez que você tentar acessar o ponto de montagem o programa tentando fazer isso vai congelar enquanto autofs tenta fazer sua mágica. Prefiro links quebrados e pastas vazias em vez de programas travando

É possível resolver alguns destes problemas, mas como qualquer solução parcial, continua sendo uma porcaria… A melhor solução é inverter a cadeia de dependência, utilizando os dispositivos como triggers.

Se o pendrive estiver plugado, a partição vai montar assim que você logar, se não estiver, o nautilus não vai engasgar porque sua pasta Download é um link para um caminho na partição encriptada, quando for plugado a partição vai montar automaticamente, sem precisar reiniciar ou tentar acessar o ponto de montagem.

Enfim, é a montagem automática de dispositivos externos que temos nas DEs por aí, um pouco mais inteligente. Se você ainda quiser atrasar a montagem até que o ponto de montagem seja acessado, pode ser uma boa idéia investigar unidades systemd.path ou algo via inotify + systemd.

systemd.mount do pendrive

Esta unidade vai montar automaticamente o pendrive assim que for plugado, porém apenas após o default.target, você vai precisar saber ou o UUID ou o ID do seu pendrive

$ lsblk -f
NAME   FSTYPE     FSVER LABEL    UUID         FSAVAIL FSUSE% MOUNTPOINT
...      
sdf                                                                                  
└─sdxn vfat       FAT32 PENDRIVE ABCD-1234    7,4G     0%    /media/pen
...

$ systemctl -a | grep ABCD
dev-disk-by\x2duuid-ABCD\x2d1234.device

Para criar a unidade:

$ sudo systemctl edit --full --force 'media-pendrive.mount'

conteúdo:

[Unit]
Description= key pendrive
After=default.target

[Mount]
Where=/media/pendrive
What=/dev/disk/by-uuid/ABCD-1234
Options=ro,umask=0377
DirectoryMode=0400

[Install]
WantedBy=dev-disk-by\x2duuid-ABCD\x2d1234.device

systemd.service para abrir o dispositivo LUKS

Este serviço vai abrir a partição luks para ser montada.

$ sudo systemctl edit --full --force 'unlock.service'

conteúdo:

[Unit]
Description=unlock HDD
After=media-pendrive.mount
Before=mnt-HDD.mount
BindsTo=mnt-HDD.mount

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/unlock.sh
ExecStop=/usr/bin/lock.sh

[Install]
WantedBy=media-pendrive.mount

conteúdo do script /usr/bin/unlock.sh.

#!/bin/bash

sudo cryptsetup --key-file '/media/pendrive/.key' luksOpen '/dev/disk/by-uuid/...' cryptHDD

if [[ -e '/dev/mapper/cryptHDD' ]]; then
        echo 'HDD unlocked successfully.'
else
        >&2 echo 'failed to unlock HDD.'
        exit 1
fi

conteúdo do script /usr/bin/lock.sh.

#!/bin/bash

sudo cryptsetup luksClose cryptHDDA


if [[ -e '/dev/mapper/cryptHDD' ]]; then
        >&2 echo 'failed to lock HDD.'
        exit 1
else
        echo 'HDD locked successfully.'
fi

OBS: De preferência, use /dev/by-uuid/... em vez de /dev/sdx para não ter problema ao mudar porta USB/SATA.

systemd.mount para a partição

Esta unidade vai montar a partição após unlock.service criar o dispositivo /dev/mapper/cryptHDD. Só será ativada após o default.target.

$ sudo systemctl edit --full --force 'mnt-HDD.service'

conteúdo:

[Unit]
Description=Mount unit for encripted device cryptHDD
After=default.target unlock.service dev-mapper-cryptHDD.device
Requires=dev-mapper-cryptHDD.device
DefaultDependencies=no
PartOf=unlock.service

[Mount]
Where=/mnt/HDD
What=/dev/mapper/cryptHDD
Type=btrfs
Options=noatime,autodefrag,compress-force=zstd:2,...

[Install]
WantedBy=dev-mapper-cryptHDD.device

hora de ativar as unidades

Após ativar as unidades podemos plugar o pendrive.

sudo systemctl enable media-pendrive.mount unlock.service mnt-HDD.mount

Agora sempre que você plugar seu pendrive ele irá descriptografar e montar sua unidade. Você também pode desmontar a partição e fechar os dispositivos LUKS com o comando stop, o sistema irá tomar o devido cuidado de primeiro desmontar e depois fechar os dispositivos.

$ sudo  systemctl stop mnt-HDD.mount
#ou
$ sudo systemctl stop unlock.service
5 curtidas