Бабушкины криптопирожки: шифруем диски

Недавно возникла необходимость разобраться в том, как создать безопасное хранилище для своих (и не только) секретиков. Да, можно использовать какие-что зашифрованные zip-архивы. Но по определенным причинам, это был не мой путь.

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

Так вот, когда я начал искать подходящие руководства по полно-дисковым системам шифрования, я не нашел ни одного, которое бы отвечало на все мои вопросы. А именно: как именно мне с нуля создать файловую систему, которую я потом пошифрую, и как мне с ней работать.

PS. Потом я нашел более-менее подходящую (но она была неполной), тут раскрыл подробнее + указал более точную информацию.

Определяемся с тулзой

Мой выбор пал на стандартную линуксовый модуль ядра dm-crypt (LUKS). Он как раз позволяет работать с файловыми системами. И эта штука очень шустрая, потому что используется блочное шифрование на уровне устройства. Помимо этого в ней есть удобная работа с ключами. Полнодисковой утилита называется из-за того, что работает со всей файловой системой, которая есть на устройстве. Точнее, она ее даже не воспринимает как файловую систему — ей без разницы вообще. Она просто на вход берет блочное устройство и полностью шифрует его.

Если бы я работал с FreeBSD, то выбрал бы geom_bde. Но об этом как-нибудь потом.

Сейчас же важно проделать некоторые другие действия, необходимые нам для настройки. Приступим.

Как работает LUKS

Чтобы выполнить шифрование диска linux используется модуль ядра dm-crypt. Он создает в каталоге /dev/mapper виртуальное блочное устройство с прозрачным для файловой системы и пользователя шифрованием. Фактически все данные лежат на зашифрованном разделе. Если пользователь записывает данные на виртуальное устройство, они на лету шифруются и записываются на диск, при чтении с виртуального устройства, выполняется обратная операция — данные расшифровываются с физического диска и передаются в открытом виде через виртуальный диск пользователю. Дефолтный шифр — AES. Под него оптимизированы большинство современных процессоров. Важно заметить, что вы можете шифровать не только разделы и диски, но и обычные файлы, создав в них файловую систему и подключив как loop устройство (чем мы и займемся дальше).

Алгоритм LUKS определяют какие действия и в каком порядке будут выполняться во время работы с шифрованными носителями. Для работы с LUKS и модулем dm-crypt используется утилита Cryptsetup.

Заводим себе файловую систему

Точнее, файловую систему мы определим уже в самом криптоконтейнере. Тут же мы создадим некую основу для всего этого.

Для начала проинициализируем файл, в который мы потом поместим все свое добро:

root@kali:~#dd if=/dev/zero of=./fs.img bs=1M count=10

Вывод будет такой:

10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0,0141486 s, 741 MB/s

Тут мы берем 10 блоков по 1 мегабайту из /dev/zero и записываем их в файл fs.img

Теперь привяжем наш файл к блочному устройству:

root@kali:~#losetup --find --show ./fs.img

С помощью ключа —find находим первое свободное блочное устройство и ссылаем его на файл ./fs.img. А —show выведет нам имя этого блочного устройства. В моем случае это:

/dev/loop0

Проверим, что все на месте командой:

root@kali:~#losetup --list

Она покажет, какие блочные устройства у нас заняты, и на что они ссылаются:

NAME       SIZELIMIT OFFSET AUTOCLEAR RO BACK-FILE
/dev/loop0         0      0         0  0 /home/user1/fs.img

Создавать файловую систему сразу не имеет смысла, поскольку не сознан еще сам криптоконтейнер — при его создании мы просто перепишем все, что у нас внутри есть. Поэтому приступим к криптоконтейнеру.

Лепим криптопирожки

Конечно же, нам нужно сначала установить нашу тулзу:

 root@kali:~#apt-get install cryptsetup

Как я сказал, нам теперь нужно определить криптоконтейнер. И в этом нам поможет команда cryptsetup. Создадим платформу защищенного хранилища с помощью команды luksFormat:

 root@kali:~#cryptsetup -s 512 luksFormat /dev/loop0

Ты же помнишь, что у нас /dev/loop0 ссылается на наш файл? Тогда отлично. А -s это длина ключа, на котором шифруем. Вывод от этой команды будет такой:

This will overwrite data on /dev/loop0 irrevocably.
  
Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase: ...
Verify passphrase: ...

Мы еще вернёмся к passphrase потом. Кстати, это не единственный способ. Можно еще сгенерировать свой ключ и позировать на нем. Это я тоже покажу, но потом…:)

Давайте же вскроем наш пирожок командой luksOpen:

root@kali:~# cryptsetup luksOpen /dev/loop0 my_crypto
Enter passphrase for /dev/vdb2: ...

Первым параметром передаем блочное устройство, которое хотим посмотреть, второй — файл, на который мы отображаем наше новосозданное блочное устройство (точнее, это ссылка, которая ссылается на другое блочное устройство)

Короче, после этой команды в папке /dev/mapper можно будет найти ссылку (на блочное устройство) my_crypto

root@kali:~# ls -lh /dev/mapper
total 0
crw------- 1 root root 10, 236 May 2 16:22 control
lrwxrwxrwx 1 root root 7 May 2 16:54 my_crypto -> ../dm-0

А вот теперь уже в нашем криптоконтейнере заводим файловую систему:

root@kali:~# mkfs.ext4 /dev/mapper/my_crypto
mke2fs 1.45.5 (07-Jan-2020)
Creating filesystem with 86016 1k blocks and 21560 inodes
Filesystem UUID: a73c8f72-d9c4-4251-a363-280910f93760
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Вы можете создать любую файловую систему, но мне было удобнее ext4. Иначе можно команду поменять на mkfs.ext2, mkfs.ext3… Ну, вы поняли.

Работаем с горячими пирожками

После того, как система создана, ты смело можешь ее монтировать. Делается это так:

root@kali:~# mount /dev/mapper/my_crypto /mnt

Теперь в твоей папке /mnt находится по сути новая файловая система, куда ты можешь класть свою информацию и безопасно хранить. Круто, не правда ли?

Давай попробуем создать там парочку файлов:

root@kali:/mnt# echo 'my secret info' > secret.txt
root@kali:/mnt# mkdir crypto_test && touch crypto_test/1.{1..3}txt
root@kali:/mnt# tree
.
├── crypto_test
│   ├── 1.1txt
│   ├── 1.2txt
│   └── 1.3txt
├── lost+found
└── secret.txt
2 directories, 4 files

Директория lost+found создается по умолчанию. Еще для примера я создал файл с текстовым содержанием и парочку файлов в другой папке (просто для какой-то структуры)

Теперь закроем наш контейнер. Так мы точно будем уверены, что наши файлы больше не доступны для чтения. Сделаем это:

root@kali:~# umount /mnt
root@kali:~# cryptsetup luksClose fs.img

После этого файл fs.img будет оставаться в защищенном виде. Мы можем его передавать и открывать в любом другом месте.

Проверим, что все на месте

Давай теперь удостоверимся, что наш контейнер защищен, и его так просто не примонтировать. Как помнишь, мы не освобождали блочное устройство /dev/loop0. Оно попрежнему ссылается на fs.img. Давай сразу примонтируем его:

root@kali:~# mount /dev/loop0 /mnt
mount: /mnt: unknown filesystem type ‘crypto_LUKS’.

А не вышло! Дело в том, что в данный момент это не файловая система, а криптоконтейнер (можно убедиться командой file fs.img). И команда mount просто не знает, как с этим работать.

Поэтому надо сначала открыть контейнер, как мы делали раньше:

root@kali:~# cryptsetup luksOpen /dev/loop0 my_crypto
Enter passphrase for /root/otus/fs.img:

Конечно же у нас спросят пароль для расшифровки контейнера. После этого он еще будет некоторое время расшифровываться (время зависит от величины контейнера). А дальше монтируем наше новое устройство и идем во внутрь:

root@kali:~# mount /dev/mapper/my_crypto /mnt
root@kali:~# cd /mnt
root@kali:/mnt# tree
.
├── crypto_test
│   ├── 1.1txt
│   ├── 1.2txt
│   └── 1.3txt
├── lost+found
└── secret.txt
2 directories, 4 files
root@kali:/mnt# cat secret.txt
my secret info

Как видишь, вся наша файловая система в сохранности, а доступ мы к ней получили только после ввода пароля.

Ключевые файлы

Ты, конечно, понимаешь, что по некоторым причинам пароли использовать не безопасно (если только вы не используете достаточно большой, соответствующий всем парольным политикам). Поэтому шифровать ваши контейнеры можно так же с помощью ключевых файлов. Не буду подробно расписписывать, потому что процесс отличается не сильно.

Создадим случайный ключ (либо любым другим образом):

root@kali:~# dd if=/dev/urandom of=/etc/keys/enc.key bs=1 count=4096

Создаем наш криптоконтейнер с ключевым файлом:

root@kali:~# cryptsetup -s 512 luksFormat /dev/loop0 /etc/keys/enc.key

Откроем наш контейнер с помощью файла-ключа (не забудь про создание ФС):

root@kali:~# cryptsetup luksOpen -d /etc/keys/enc.key /dev/loop0 my_crypt

И точно также закроем контейнер (после того, как отмонтируем):

root@kali:~# cryptsetup luksClose my_crypt

Теперь ты знаешь, как использовать ключи в файлах. Давай поуправляем этими ключами.

Управление ключами

Ключи LUKS (фраза или тот, который передаем в файле) используются для доступа к настоящим ключам шифрования. Они хранятся в слотах в заголовке (зашифрованного) раздела, диска или файла.

Получим список доступных слотов (один пароль с ключом шифрования хранится в одном слоте) и еще много-много полезной информации:

root@kali:~# cryptsetup luksDump /dev/loop0
LUKS header information
Version: 2
Epoch: 3
Metadata area: 16384 [bytes]
Keyslots area: 16744448 [bytes]
UUID: b915729b-b7d7-4eab-9622-4e85b2d3104c
Label: (no label)
Subsystem: (no subsystem)
Flags: (no flag)

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
...

Добавим новый ключ

Чтобы добавить новый ключ нужно:

root@kali:~# cryptsetup luksAddKey /dev/loop0
Enter any passphrase: (Enter a valid, previously used passphrase to unlock the key)
Enter new passphrase for key slot: ... 
Verify passphrase: ...

Либо через -d передаем passphrase из ключевого файла.

Если же нужно добавить новый ключевой файл, то делаем так:

root@kali:~# cryptsetup luksAddKey /dev/loop backup.key

Аналогично с предыдущим примером, если хотим добавить новый ключевой файл, используя информацию из ключевого файла, который уже был добавлен:

root@kali:~# cryptsetup luksAddKey /dev/loop0 ./enc.key -d enc2.key

Удаление ключей

root@kali:~# cryptsetup luksRemoveKey /dev/loop0
Enter LUKS passphrase to be deleted: ...

либо же с помощью ключевого файла:

root@kali:~# cryptsetup luksRemoveKey -d backup.key /dev/loop0

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

Опустошение слота

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

root@kali:~#cryptsetup luksKillSlot /dev/loop0 2

Эта команда. попросит одну из действительных ключевых фраз. Однако, также можно воспользоваться и ключевой фразой из файла

root@kali:~#cryptsetup luksKillSlot -d /etc/keys/enc.key /dev/loop0 2

Только смотри не удали тот слот, который на самом деле тебе нужен! А то останешься без ключей шифрования.

Это получилось большая статья. Больше она написана, конечно, для себя. Поскольку, вероятно, я буду не раз. возвращаться к ней, чтобы вспомнить те или иные детали. Но, возможно, тебе она тоже будет полезна! В любом случае я рад, что могу принести пользу еще кому-то.

Выводы

Плюсы:

  • LUKS шифрует все блочное устройство, и поэтому очень хорошо подходит для защиты содержимого переносных устройств, таких как мобильные телефоны, съемные носители или жесткие диски ноутбуков.
  • Вы можете использовать на серверах для защиты резервных копий
  • Процессоры Intel и AMD с AES-NI (Advanced Encryption Standard) имеют набор команд, которые могут ускорить процесс шифрования на основе dm-crypt в ядре Linux начиная с 2.6.32.
  • Работает в том числе и с разделом подкачки, так что ваш ноутбук может использовать функцию спящего режима, или гибернации полностью безопасно.

Минусы:

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

Мы на дзене

Наш телеграмм канал

Возможно, Вам понравится:

guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x
()
x