如何在Ubuntu上启用全盘加密,并在休眠/挂起到RAM之前调用LUKSsupend?

这个问题与@Stefan的另一个问题有关,但它并不是重复的。问题略有不同:作者只是想知道是否已经实现了这个功能,而我则是在寻求如何以特定的方式实现这个功能的帮助。此外,其他问题没有给实施者提供有用的答案,除了最近的一个回答,仅仅链接到了我尝试的解决方案。
解释了“重复”问题之后...
我使用Ubuntu 14.04,并且使用全盘加密(LVM在LUKS之上),我想将luksSuspend整合到挂起过程中(然后使用luksResume),这样我就可以将系统挂起到RAM而不会在内存中留下密钥信息和解锁根目录。
我尝试移植一个适用于Arch Linux的脚本,但迄今为止没有成功:老实说,我不知道自己在做什么...
有人能帮我移植这个(或者从头开始创建类似的东西)吗?或者至少,有人能指点我如何将一些东西挂接到挂起过程中,并且在所有对根目录的IO被阻止之后,保持必要的二进制文件和脚本(比如cryptsetup)可用(通过luksSuspend)?
关于如何保持必要的二进制文件和脚本在恢复时可用,这个其他博客文章(也适用于Arch)将它们复制到了/boot;然而,我更倾向于使用Vianney在我之前提到的脚本中使用的方法,因为这种方式在这方面看起来更加优雅。
我还没有取得太多进展,但我的开发可以在GitHub上找到。

你试过在休眠/恢复操作中添加手动锁定命令吗?例如,在/etc/pm/sleep.d/目录下的脚本中添加udisksctl lock -b /dev/sda - AliReza Mosajjal
谢谢,我会调查一下……从我已经了解的情况来看,这比我一直在使用的仅限于LUKS的cryptsetup luksSuspend更为通用,但另一方面需要卸载文件系统。此外,它可能无法在监狱中工作(因为它与udisksd守护程序通信),也不能用于重新挂载/恢复文件系统。 - Jonas Malaco
即使移除了密钥材料,在挂起到RAM期间,内存中可能仍存在其他机密信息。那么,仅仅摆脱luks密钥有何意义呢? - pefu
@pefu 嗯,首先,磁盘上的机密信息量可以比留在RAM中的多得多。此外,与能够访问解密文件系统相比,攻击者在RAM上识别和/或更改信息的能力相对有限。 - Jonas Malaco
@jonasmalacofilho:嗯,我将我的私钥视为笔记本电脑上最机密的资料。当然,这些私钥也受到密码短语的保护。在启动时,我通常会加载这些密钥,并运行一个代理程序,这个代理程序当然在RAM中存储了这些密钥的解密副本。因此,如果我的计算机落入一位熟练的攻击者手中,该攻击者能够绕过任何屏幕保护安全措施并从RAM中恢复数据,即使我在进入挂起之前销毁了RAM中的LUKS密钥,我也会陷入麻烦,对吗? - pefu
@pefu,是的,你会(特别是因为加密材料在RAM中很容易被发现)。然而,一个人可以拥有多个密钥(并且一次只加载其中几个到RAM中),使用非常短暂的缓存时间,甚至在暂停之前设置他的代理卸载所有密钥... - Jonas Malaco
2个回答

抱歉明说一下,你试过在/usr/lib/pm-utils/sleep.d中添加一个包含cryptsetup luksSuspend/luksResume命令的脚本吗?如果是这样,发生了什么?
对我来说,调用在休眠/恢复时停止/启动cryptdisks和cryptdisks_early服务似乎是合乎逻辑的。在pm-utils/sleep.d中的脚本中调用cryptdisks_stop和cryptdisks_start是否能解决问题?我假设这将产生与直接调用cryptsetup luksSuspend相同的结果。

到目前为止,我的方法是修改pm-suspend。然而,在尝试挂起时(使用 echo mem > /sys/power/state),仍然有一些内核模块被加载,它们需要访问根文件系统。请参考链接的存储库了解更多详细信息。 - Jonas Malaco

最接近的解决方案是我找到的这个由Mikko Rauhala于2013年开发的概念验证脚本suspend.sh。
#!/bin/sh

# A proof of concept script for forgetting LUKS passwords on suspend
# and reasking them on resume.

# The basic idea is to copy all of the files necessary for luksResume
# onto a RAM disk so that we can be sure they'll be available without
# touching the disk at all. Then switch to a text VT to run the resume
# (easier to make sure it'll come up than to do the same with X).

# The suspend itself has to be done from the ramdisk too to make sure it
# won't hang. This is also a reason why this couldn't be reliably done as a
# self-contained /etc/pm/sleep.d script, so to make the concept clear
# (and because I'm lazy) I did just a minimal standalone proof of concept
# instead. Integrating the functionality into the usual pm tools would be
# encouraged. (Though suspend_pmu would apparently need perl on the ramdisk...)

# (C) 2013 Mikko Rauhala 2013, modifiable and distributable under
# CC0, GPLv2 or later, MIT X11 license or 2-clause BSD. Regardless
# of what you pick, there is NO WARRANTY of any kind.

RAMDEV=/dev/ram0
ROOT=/run/cryptosuspend

PATH=/sbin:/bin:/usr/sbin:/usr/bin

# Cleanup not strictly necessary every time but good for development.
# Doing it before rather than after a suspend for debugging purposes

for a in "$ROOT"/dev/pts "$ROOT"/proc "$ROOT"/sys "$ROOT" ; do
    umount "$a" > /dev/null 2>&1
done

if mount | grep -q "$ROOT" ; then
    echo "Cleanup unsuccessful, cryptosuspend root premounted." 1>&2
    exit 2
fi

if grep -q mem /sys/power/state; then
    METHOD=mem
elif grep -q standby /sys/power/state; then
    METHOD=standby
else
    echo "No mem or standby states available, aborting" 1>&2
    exit 1
fi

if ! mount | grep -q "$RAMDEV" ; then
    mkfs -t ext2 -q "$RAMDEV" 8192
    mkdir -p "$ROOT"
    mount "$RAMDEV" "$ROOT"
    mkdir "$ROOT"/sbin "$ROOT"/bin "$ROOT"/dev "$ROOT"/tmp "$ROOT"/proc "$ROOT"/sys
    cp "$(which cryptsetup)" "$ROOT"/sbin
    for a in $(ldd "$(which cryptsetup)" | grep "/" | cut -d / -f 2- | cut -d " " -f 1) ; do
        mkdir -p "$ROOT""$(dirname /$a)"
        cp "/$a" "$ROOT"/"$a"
    done
    cp "$(which busybox)" "$ROOT"/bin/
    ln -s busybox "$ROOT"/bin/sh
    ln -s busybox "$ROOT"/bin/sync
    cp -a /dev "$ROOT"
    mount -t proc proc "$ROOT"/proc
    mount -t sysfs sysfs "$ROOT"/sys
    mount -t devpts devpts "$ROOT"/dev/pts
fi

CRYPTDEVS="$(dmsetup --target crypt status | cut -d : -f 1)"

echo '#!/bin/sh' > "$ROOT"/bin/cryptosuspend
echo "sync" >> "$ROOT"/bin/cryptosuspend
echo "for a in $CRYPTDEVS ; do" >> "$ROOT"/bin/cryptosuspend
echo "  cryptsetup luksSuspend \$a" >> "$ROOT"/bin/cryptosuspend
echo "done" >> "$ROOT"/bin/cryptosuspend
echo "echo -n \"$METHOD\" > /sys/power/state" >> "$ROOT"/bin/cryptosuspend
echo "for a in $CRYPTDEVS ; do" >> "$ROOT"/bin/cryptosuspend
echo '  while ! cryptsetup luksResume'" \$a ; do" >> "$ROOT"/bin/cryptosuspend
echo "    true" >> "$ROOT"/bin/cryptosuspend
echo "  done" >> "$ROOT"/bin/cryptosuspend
echo "done" >> "$ROOT"/bin/cryptosuspend
chmod a+rx "$ROOT"/bin/cryptosuspend

sync
exec openvt -s chroot "$ROOT" /bin/cryptosuspend

一些工作已经开始将其移植到Ubuntu 14.04 这里。这绝不是一个完美的解决方案,因为仍然存在一些未解决的问题,而且自2014年6月11日以来似乎没有发布任何工作。然而,它似乎是未来发展的一个良好起点。

Source:https://github.com/jonasmalacofilho/ubuntu-luks-suspend