Инструкция по отрицаемому хранению данных на носителе с Tails
Цель
Иметь на одном и том же носителе как загрузочный Tails, так и хранилище для дополнительных данных, которое не будет вычищаться перезагрузкой, причём это хранилище должно быть отрицаемым.
Общая идея
На носитель устанавливается Tails, а на оставшемся свободном месте диска (в хвосте) делается бессигнатурный шифрованный раздел для хранения данных.
Легенда
Затёрли флэшку/диск/SD-карточку рандомом, потом записали стандартный Tails по инструкции с сайта, и всё на том. Больше ничего не делали, никаких скрытых данных нет.
Подводные камни
- В ядре Linux решили не заморачиваться консистентностью разных компонент ядра, просто запретив их взаимодействие. Итог: всё dm-based (dmsetup, cryptsetup, LVM) совместимо между собой, но несовместимо с монтированием файловой системы. В частности, если на диске /dev/sda есть файловая система на /dev/sda<N>, и она подмонтирована, нельзя адресовать свободное (неразбитое) дисковое пространство на /dev/sda с помощью dmsetup или cryptsetup (ядро ставит bd_claim на блочное устройство /dev/sda, запрещая его использование dm'у; задаваемые оффсеты и размеры при этом совершенно неважны). Однако, если файловая система находится на ином блочном устройстве (важен логический, а не физический уровень) — к примеру, на /dev/mapper/name, который зацеплен на /dev/sda<N>, монтирование этой ФС не будет препятствовать использованию dm/cryptsetup на /dev/sda.1
- По умолчанию Tails не грузит все файлы в память, а каждый раз запрашивает их с диска/флешки, т.е. файловая система с диска будет всегда подмонтирована. Из-за предыдущего пункта это блокирует возможность использовать неразбитое дисковое пространство для хранения данных. Можно, конечно, загрузить Tails, потом на лету менять MBR, добавляя и убирая нужные разделы, но это геморройно, грязно и может испортить легенду.
Недокументированные возможности
С помощью реверс-инжиниринга можно выяснить, что в Tails есть тайная недокументированная опция загрузки, которая держится в строжайшем секрете — toram («to RAM»). Она позволяет вэйпонизировать Tails в нужном направлении: в самом начале загрузки, когда выводится меню isolinux с двумя вариантами (обычный и fail-safe), выбираем нам нужный, нажимаем tab, дописываем toram к опциям загрузки и грузим. После этого Tails будет загружен в память, а файловые системы на носителе, с которого он был загружен, не будут подмонтированы — носитель можно будет даже отключить, и Tails продолжит работать из RAM.
Семь шагов на пути к успеху
- Следуя инструкциям на сайте Tails, с помощью isohybrid преобразовываем iso в образ, нужный для записи на флешку/диск.2 (Примечание: возможно, в этом уже нет необходимости).
- Записываем получившийся образ с помощью команды(предполагаем, что запись идёт на /dev/sdb). Это создаёт на устройстве MBR и таблицу разделов, в первом разделе (/dev/sdb1) будет находиться Tails.
# dd if=/path/to/file.iso of=/dev/sdb
- Создаём бессигнатурный шифрованный раздел на неразбитом пространстве диска:3Оффсет (задается в секторах) можно не запоминать, потому что его легко посмотреть fdisk-ом — это последний сектор первого раздела + 1. В данном случае мы используем вариант «выделяем всё пространство до конца диска». Однако, лучше сделать иначе: если размер носителя позволяет, взять какой-то фиксированный offset побольше, чтобы при последующем обновлении Tails и его записи на этот же носитель через dd (размер может увеличиться) наш бессигнатурный раздел не был затёрт.
# cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -o оффсет create NAME /dev/sdb
Вышеприведённая команда cryptsetup создаёт устройство /dev/mapper/NAME с несменяемым паролем на шифрование. Внутри него лучше создать LVM с LUKS-шифрованными логическими томами или просто один LUKS-раздел на всё устройство, чтобы не терять возможность менять пароль, убивать слоты и т.д. Как это сделать технически — уже обсуждалось [3], [4].
- Если работаем c SD-карточки, имеющей физический переключатель для блокировки записи, включаем его: на этапе загрузки запись на носитель нам не понадобится.
- Грузимся, включая опцию загрузчика toram (см. выше).
- При поставленном локе на адаптере (см. п.5, этот комментарий только на случай, если он используется) и dmsetup и cryptsetup позволяют создавать только read only mappings, причем cryptsetup умный и сам догадывается включить режимр r/o, а вот dmsetup'у надо указывать опцию -r явно. В предположении, что нужный раздел с данными уже заранее создан на свободном дисковом пространстве, монтируется он так же:(остальные опции подключения LUKS/LVM добавляем по вкусу, если нужны). Если же нужно сделать r/w-доступ к скрытому разделу на SD-карте, надо:
# cryptsetup -c aes-xts-plain64 -s 512 -h sha512 -o оффсет create NAME DEVICE
- Достать SD-карту (предполагаем, что она не подмонтирована).
- Объяснить ядру, что мы её достали (бывают «умные» адаптеры, которые usb disconnect не ловят, пока к SD-карте не обратишься).
- Cнять лок и перевставить SD-карточку.
- Подключить скрытый раздел и смонтировать его в режиме r/w.
1Уже давно пора разделы диска делать принудительно через dm, тогда бы такой проблемы не возникло вообще. Некоторые пояснения:
2) Дело не в том, что раздел открыт на запись; дело в том, что при монтировании ФС ядро делает bd_claim. Таким образом, никакая другая компонента ядра не может сделать bd_claim на подраздел и блочное устройство (диск) в целом (т.е. дело не в том, где физически находится монтируемый подраздел, а в том, логической частью какого блочного устройства он является — bd_claim делается именно на блочное устройство; из-за этого можно без проблем подмонтировать mapping и это ни на что не повлияет — каждый mapping сам по себе блочное устройство).
3) Это проблемы Linux, а точнее — интерференция системы подразделов и системы dm. Во имя консистентности был забит костыль, дабы эти подсистемы не мешали друг другу. В общем, как всегда, проблема legacy и эволюционного проектирования.
Монтирование ФС — это частный случай bd_claim. Важно то, что
b) Одна и та же компонента ядра может это делать без ограничений. Например, всё, что делается через dm (это и dmsetup linear, и dm-crypt, и LVM) совместимо друг с другом.
Т.е. dm внутри себя поддерживает консистентность маппингов, а костыль с bd_claim сделан, чтобы не заморачиваться консистентностью разных подсистем ядра для доступа к одним и тем же блочным устройствам.
2Обычные iso'шки не поддерживают загрузки с флэшек хотя бы потому, что там нет MBR нет и т.п. Гибридные iso когда делаются, а когда нет — это от авторов зависит. Не исключаю, что в Debian iso гибридные по умолчанию.
3Поскольку по умолчанию TRIM отключен, микроконтроллер не знает, какие сектора диска ОС считает свободными. Для нашего случая это хорошо, т.к. неиспользуемое место не будет обнуляться в случае флэшек и SD-карточек.
Спасибо за развернутый ответ.
А где хранится ключ в plain-контейнере? Может быть достаточно просто натравить dd if=/dev/urandom с оффсетом на начало контейнера?
Насколько безопасно использовать для plain-контейнера пароль, который является хешем SHA512 парольной фразы?
Еще есть вопрос по правам доступа. Выполнил:
В результате папка /home/amnesia/AnyDirectory/ вместе со всем содержимым получила права только для административного доступа. Но, не понятно, зачем это там. Как позволить доступ обычному пользователю и не напортачить с безопасностью?
Тема меня сильно заинтересовала, вопросов появляется масса, не обессудьте, что отнимаю драгоценное время.
комментариев: 9796 документов: 488 редакций: 5664
В LUKS генерируется мастер-ключ и слот-ключ(и). Пароль пользователя хэшируется (точнее пропускается через PBKDF — многократное хэширование с некоторыми наворотами) и хэшем от пароля шифруются слот-ключ(и), которым(и) шифруется мастер-ключ. Мастер и слот ключи в шифрованном виде пишутся в заголовок контейнера. Если пароль неизвестен — их не расшифровать. Если они стёрты, то и пароль не поможет.
В Plain-режиме весь контейнер шифруется сразу хэшем от пароля. Никаких других ключей не используется, заголовков для их хранения нет. Если пароль известен, то всегда можно вывести хэш-ключ и расшифровать любую незатёртую часть контейнера, в отличие от LUKS.
Спасибо всем. Является ли безопасным использование хеша от выражения "123" в качестве пароля для plain-контейнера?
Не вижу в этом смысла. Используйте обычный пароль, но достаточно стойкий. Всё равно он будет хэшируется в указанной команде. Если что, есть инфа про пароли и их запоминание. Минимальная рекомендуемая стойкость — 128 бит.
По умолчанию любая подмонтируемая файловая система доступа на запись только руту. Если хотите дать доступ другому, дайте после монтирования:
Вот ещё более развёрнутый на тему одного из аспектов LUKS.
Нет. ☺ Энтпопию нельзя получить изничего. Либо на входе она уже есть, либо никак.
комментариев: 9796 документов: 488 редакций: 5664
Старик Фрейд доволен © ;)
Одна из возможностей перзистентного раздела – сохранение пакетов, ранее установленных пользователем, чтобы они были к диспозиции оффлайн. В разбираемой схеме, перзистенции, пока, несуществует. Проблему решил обойти созданием списка нужных пакетов/зависимостей, их скачиванием по созданному списку и последующей оффлайн-установкой в любое нужное время.
Вот тут-то и пришел облом. На определенном этапе установки комп намертво завис. На борту 2G RAM + 2500MHz CPU. При этом, онлайн-установка проходит без проблем.
Как это вылечить или обойти с сохранением отрицаемости использования пакетов, устанавливаемых сверх стандартной системы.
Штатно в Tails это реализвано. Попробуте разобраться как. Нам тоже интересно будет ).
По вашей ссылке приведённые команды не совпадают с вашми. В частности, «^» отсутствует.
Смысл понятен: скачать пакеты в отрицаемый раздел, потом из него каждый раз после перезагрузки устанавливать пакеты.
Проблем с записью нет? Кто его знает, как оно там реализовано.
Тут есть еще вопрос, а вы загружались в режиме файлсейф?
Может попробовать не sudo, а в root-терминале?
В рассматриваемой конфигурации перзистентного раздела нет по причине отрицаемости.
Извините, проходил много ссылок, мог ошибиться.
Проблем с записью ни разу не наблюдал. Если ставить с онлайна, то все работатет. А если со скрытого раздела, то установка нормально двигается вперед, а потом зависает таким образом, как это бывает при недостатке памяти.
Если считать, что проблема заключается в недостатке памяти, тогда, может быть, ее можно решить с помощью модуля zram (сабж на хабре)? Проверил, такой модуль в Tails есть и грузится.
cat /proc/meminfo и top показывают, сколько занято памяти. Я больше, чем уверен, что она здесь ни при чём. Попробуйте ставить онлайново, но со скрытого раздела — поможет ли это? Вдруг он в процессе установки пытается каждый раз что-то докачать с сети, и это у него не получается? Наверно, вы понимаете, что при оффлайновой инсталляции нужна только последняя команда: dpkg -i *deb.
Думаю, да. Список ссылок на пакеты/зависимоста и их скачивание делаем один раз.
Вы полностью правы. Оказалось, что это процессор грузится под завязку. На примере установки пакета cpulimit, действовал следующим образом (скрытый раздел не подключал, попробую в следующий раз; но, может быть кто-то заметит у меня какую-то ошибку)
Дистрибутив запущем в памяти опцией toram.
Составление списка со ссылкой на пакет и его скачивание
На этом подготовка заканчивается. Если действовать на скрытом разделе, то пакт останется скачанным на будущее.
Теперь устанавливаем пакет, который ранее скачали.
Вот тут-то загрузка процессора и подпрыгивает на 100%. Если устанавливаем только один пакет без зависимостей, то это проходит. А если устанавливаем пакет с десятком зависимостей, то процессор намертво закусывает.
Ограничение использования процессора для dpkg на 20% не помогает
и при наблюдении за показаниями утилиты htop создается впечатление, что все процессы проходят одновременно у двух пользователей
amnesia
root
Кроме того, на разных этапах разные процессы так же сильно загружают процессор. Разобраться во всем этом, пока что, знаний не хватает.
А так хочется просто жить просто. :-)