我刚刚读过这次讨论莱纳斯·托瓦兹 (Linus Torvalds) 和(以及其他人)之间米兰·布罗兹,dm-crypt 的维护者之一。
我对讨论的以下部分很感兴趣:
Linus Torvalds:我认为那些使用隐藏(“可否认”)东西的人实际上从未使用过使用完全是外部文件系统,这样他们就可以将真正的加密内容放在那里,而不必担心它。
Milan Broz:嗯,他们实际上应该时不时地“使用”外部,这样数据看起来是“最新的”,对于整个“隐藏操作系统”,他们甚至应该能够根据请求启动到外部诱饵操作系统,只是为了表明某些东西工作就在那里。
理论上我同意米兰的说法,利用诱饵数据是增加可信度的好事情。但在实践中如何实现这一目标呢?例如,如何写入外部卷而不冒覆盖内部卷的风险?
多年来我一直在使用隐藏的 LUKS 卷,结合可拆卸的标头和数据偏移量。通常我首先创建一个小型 LUKS 加密的外部卷(假设为 20 GB),用 EXT4 对其进行格式化,用诱饵数据填充它,然后增加该外部卷的大小(例如 500 GB),然后创建例如,偏移量为 25GB 的内部卷。
之后,我按照 Linus 所说的去做,我虔诚地避免接触外部卷的诱饵数据,因为担心损坏内部卷的数据。
有没有办法刷新外部卷的数据,而不会有损坏内部卷数据的风险?例如,是否有一个工具可以专门在外卷的前 20 场演出上编写,确保不会弄乱后面的 480 场演出?
我同时使用 HDD 和 SSD,因此这个问题适用于两者。
答案1
可能有几种方法可以安全地做到这一点,如果从新的外部体积或现有的外部体积开始,可能会采用不同的方法。
可能最好的方法是debugfs setb
在安装外部文件系统并更新其中的文件之前,在未安装的外部文件系统设备上使用命令来标记属于内部卷的块范围:
debugfs -c -R "setb <inner_start_blk> <inner_count>" /dev/<outer>
setb block [count]
Mark the block number block as allocated. If the optional argument
"count" is present, then "count" blocks starting at block number
"block" will be marked as allocated.
如果文件存在不相交的范围,则可以通过使用块范围管道传输文件来编写多个 setb 命令的脚本,如下所示:
setb <range1> <count1>
setb <range2> <count2>
:
来debugfs
读取文件debugfs -c -f <file> /dev/<outer>
。
如果您想要更聪明一点,而不仅仅是将内部卷打包在外部文件系统的末尾,则最初可以fallocate -s 32M mydir/inner
在外部文件系统中创建内部卷,然后可以从以下位置生成块范围debugfs
:
# debugfs -c -R "stat mydir/inner" /dev/vg_root/lvhome
Inode: 263236 Type: regular Mode: 0664 Flags: 0x80000
Generation: 2399864846 Version: 0x00000000:00000001
User: 1000 Group: 1000 Project: 0 Size: 32499577
File ACL: 0
Links: 1 Blockcount: 63480
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x63c98fc0:62bb0a38 -- Thu Jan 19 11:45:20 2023
atime: 0x63cee835:5e019630 -- Mon Jan 23 13:04:05 2023
mtime: 0x63c98fc0:559e2928 -- Thu Jan 19 11:45:20 2023
crtime: 0x63c98fc0:41974a6c -- Thu Jan 19 11:45:20 2023
Size of extra inode fields: 32
Extended attributes:
security.selinux (37) = "unconfined_u:object_r:user_home_t:s0\000"
EXTENTS:
(0-7934):966656-974590
在本例中,~32MB(7935x4KiB 块)文件位于块 966656-974590 中,因此这将用于setb 966656 7935
标记已使用的那些块。应擦除 inode,以clri <inum>
防止分配的块范围随后可见。
在外部文件系统中分配的块debugfs setb
将保持分配状态,直到下次在外部文件系统上运行 e2fsck。如果有人这样做,这可能会“暴露”正在使用的那些块真的注意,因此可以选择在卸载外部文件系统后再次清除它们,使用 `debugfs -c -R "clrb <inner_start> <inner_count>" /dev/",或者保留分配以避免内部文件系统可能被损坏。
答案2
我自己不使用合理的否认,所以请将此视为评论。
你可以使用设备映射器为了工作 (dmsetup
)。
它允许您设置线性映射(映射到实际数据的扇区范围)、错误映射(不存在且仅产生读/写错误的扇区范围)、零映射(丢弃写入并在读取时返回零的扇区范围) )、快照(写时复制覆盖)、...
因此,您可以设计一个块设备,其中只有外部卷区域可见,内部卷受到保护,并且对内部卷的写入将被有效丢弃或仅暂时存储在快照区域中。并且尝试读取这些区域可能会产生零或读取错误。
您可以在该外部卷上安装甚至启动虚拟机,它根本无法损坏或访问您的内部卷。但是,在没有这层保护的情况下使用它时,就没有这样的承诺。
另一种选择是通过在外部卷中创建文件来分配空间,然后使用 dm-线性 从分配的文件空间中创建可用的块设备(filefrag
将显示为每个文件分配的扇区范围)。这样,外部文件系统的文件将保护内部卷。
这种方法将允许您自由使用外部文件系统,甚至可以在其上运行 TRIM/discard。只要代表内部卷的文件保持不变,一切都可以。这还假设外部卷文件系统不会自行重新定位/重写文件内容(无碎片整理、重新压缩、重复数据删除等)。