Использования LUKS шифрования с хранением ключа на сетевом ресурсе

LUKS (Linux Unified Key Setup) — система шифрования дисков, в основе которой лежит удобное использование равнозначных ключей шифрования с возможность их добавления и отзыва. В этой статье будет описан способ создания шифрованного контейнера на Debian и автоматического его монтирования при доступности ключа находящегося на сетевом ресурсе.

Для поддержки LUKS необходимо установить пакет cryptsetup

apt-get install cryptsetup

Первый этап — создание ключа шифрования и файла контейнера

dd bs=32 count=1 if=/dev/random | base64 > /home/user/keyfile
dd if=/dev/urandom of=/opt/container.crypt bs=1M count=512

Шифруем контейнер

/usr/sbin/cryptsetup luksFormat /opt/container.crypt -d /home/user/keyfile -c aes-xts-plain64 -s 512

Опционально добавляем резервный парольный ключ

cryptsetup luksAddKey /opt/container.crypt -d /home/user/keyfile

Просмотр параметров созданного контейнера

/usr/sbin/cryptsetup luksDump /opt/continer.crypt

Вывод команды

LUKS header information
Version:        2
Epoch:          4
Metadata area:  16384 [bytes]
Keyslots area:  16744448 [bytes]
UUID:           48f8dc05-6451-416e-97cf-dbb6bec4768c
Label:          (no label)
Subsystem:      (no subsystem)
Flags:          (no flags)
 
Data segments:
  0: crypt
        offset: 16777216 [bytes]
        length: (whole device)
        cipher: aes-xts-plain64
        sector: 512 [bytes]
 
Keyslots:
  0: luks2
        Key:        512 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      argon2i
        Time cost:  4
        Memory:     564803
        Threads:    1
        Salt:       75 66 22 73 ed aa 52 b2 c3 25 2c 70 df df df 37
                    5e 2d e9 f1 3c 2c dc f6 4a 50 53 bb 91 2f e3 af
        AF stripes: 4000
        AF hash:    sha256
        Area offset:32768 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
  1: luks2
        Key:        512 bits
        Priority:   normal
        Cipher:     aes-xts-plain64
        Cipher key: 512 bits
        PBKDF:      argon2i
        Time cost:  4
        Memory:     579183
        Threads:    1
        Salt:       fc c3 67 58 52 9c fe b5 fd 21 be a9 87 e8 2b a7
                    e2 c4 92 19 82 fe 34 ec 54 5b 67 29 26 2c 6e 74
        AF stripes: 4000
        AF hash:    sha256
        Area offset:290816 [bytes]
        Area length:258048 [bytes]
        Digest ID:  0
Tokens:
Digests:
  0: pbkdf2
        Hash:       sha256
        Iterations: 121138
        Salt:       62 90 ba b5 4e 9e fb 5f 9e c5 95 74 0a ab 88 26
                    9f 2e 9c 5f 12 4a 0b 97 cf 34 05 2e 18 21 63 c9
        Digest:     ca 38 52 af 30 55 be 03 45 3a 7e c8 9a 3c 8f 19
                    f9 5e b6 17 94 6b dd 22 ba 7f 11 b3 ec 65 dc 8d

Открываем контейнер

/usr/sbin/cryptsetup luksOpen /opt/container.crypt -d /home/user/keyfile container

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

mke2fs -t ext4 -O has_journal -L container -m 0 /dev/mapper/container

Монтируем

mount /dev/mapper/container /mnt/container

Команды для закрытия контейнера

umount /dev/mapper/container
cryptsetup luksClose /dev/mapper/container

Файл ключа /home/user/keyfile необходимо переместить на сетевой сервис (например на веб-сервер или Amazon S3). Обязательно ограничить к нему доступ по ip сервера с контейнером.
В приведенном примере файл находится на S3 и доступен по адресу https://bucket_name.s3.amazonaws.com/keyfile

Политика bucket с ограничением доступа

{
    "Version": "2012-10-17",
    "Id": "Policy16696234326731",
    "Statement": [
        {
            "Sid": "Stmt16tt3991977",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucket_name/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "<IP1>",
                        "<IP2>"
                    ]
                }
            }
        }
    ]
}

Для автоматического монтирования контейнера необходимо создать два сервиса systemd в /etc/systemd/system — unlock-container.service, для расшифровки контейнера и mnt-contrainer.mount для монтирования.

unlock-container.service

[Unit]
Description=Open encrypted data volume
After=network-online.target
Wants=network-online.target
StopWhenUnneeded=true
 
[Service]
Type=oneshot
ExecStart=/usr/bin/sh -c '/usr/bin/curl -s "https://bucket_name.s3.amazonaws.com/keyfile" | /usr/sbin/cryptsetup -d - -v luksOpen /opt/container.crypt container'
RemainAfterExit=true
ExecStop=/usr/sbin/cryptsetup -d - -v luksClose container

mnt-container.mount

[Unit]
Requires=unlock-container.service
After=unlock-container.service
 
[Mount]
What=/dev/mapper/container
Where=/mnt/container
Type=ext4
Options=defaults,noatime,_netdev
 
[Install]
WantedBy=multi-user.target

Включаем и запускаем сервис монтирования

systemctl enable mnt-container.mount
systemctl start mnt-container.mount

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

/usr/sbin/cryptsetup luksOpen /opt/container.crypt container
mount /dev/mapper/container /mnt/container

Комментарии запрещены.