本 HOWTO 文档专门介绍如何在树莓派(或其他类似架构,例如 ODROID-C2)上运行 Kali,并使用 LUKS 进行全盘加密。本文基于这篇略显过时的文档。
在局域网环境中,将 Kali 部署在树莓派(或其他类似的、小型低功耗硬件)上作为“一次性黑客盒子(throw-away-hackbox)”显然很实用。然而,将收集到的数据保密是一项基本要求。因此,全盘加密成为强制性的安全概念。
首先,我们应该在 SD 卡上安装一个官方的、适用于树莓派的最新 Kali 镜像(未加密)。
(目前)推荐的做法是使用带有 nexmon 补丁的树莓派 3 定制构建版(以使用板载 WiFi 监控和注入功能)。官方 kali-arm-build-scripts 仓库中有一个自动化构建脚本,可以从零开始生成镜像(在 Kali 发行版上)。这里还有一个修补版本,它也适用于 Kali 之外的其他发行版(已在 Gentoo 上测试)。目前(2017-08)可用于 ODROID-C2 的构建脚本也在这个复刻仓库中。
获取构建工具并以 root 身份从头构建镜像(可能需要几个小时):
$ git clone https://github.com/tothi/kali-arm-build-scripts
$ cd kali-arm-build-scripts
$ sudo ./rpi3-nexmon.sh 2.0
生成的镜像为 rpi3-nexmon-2.0/kali-2.0-rpi3-nexmon.img.xz。将其复制到 SD 卡上(使用 pv 显示进度):
# pixz -d rpi3-nexmon-2.0/kali-2.0-rpi3-nexmon.img.xz - | pv -treb | dd of=/dev/mmcblk0 bs=512k
(镜像应该可以正常工作,现在可以测试。)
我们将 SD 卡中的镜像挂载,并在 chroot 环境中准备一个支持 LUKS 功能的 initramfs。为了使其正常工作,需要在 SD 卡文件系统上放置一个 x86(主机)qemu-arm-static 二进制文件。上述打过补丁的 rpi3-nexmon.sh 构建脚本会将其安装并保留在镜像中,因此一切应能正常工作。(否则,需要将相应的 qemu 静态二进制文件复制到镜像中。)
初始化 chroot 环境(在主机系统上以 root 身份执行):
# mkdir -p /mnt/chroot/boot
# mount /dev/mmcblk0p2 /mnt/chroot/
# mount /dev/mmcblk0p1 /mnt/chroot/boot/
# mount -t proc none /mnt/chroot/proc
# mount -t sysfs none /mnt/chroot/sys
# mount -o bind /dev /mnt/chroot/dev
# mount -o bind /dev/pts /mnt/chroot/dev/pts
# LANG=C chroot /mnt/chroot/
首先我们修改 root 的默认密码:
passwd
安装所需软件包(在 chroot 环境中):
# apt-get update
# apt-get install busybox cryptsetup dropbear
请注意,每次启动时我们都必须输入解密密钥。我们更希望通过 SSH 远程输入,因此需要 dropbear(在 initramfs 中)。
现在编辑 /boot/cmdline.txt,将根设备改为映射后的加密设备(/dev/mapper/crypt_sdcard),并添加相应的 cryptdevice 参数。
以下是原始的 /boot/cmdline.txt:
dwc_otg.fiq_fix_enable=2 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait rootflags=noload net.ifnames=0
以下是更新后的版本(root 和 cryptdevice 参数有所不同):
dwc_otg.fiq_fix_enable=2 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mapper/crypt_sdcard cryptdevice=/dev/mmcblk0p2:crypt_sdcard rootfstype=ext4 rootwait rootflags=noload net.ifnames=0
现在创建包含以下内容的 /boot/config.txt:
initramfs initramfs.gz followkernel
请注意,在其他硬件上也需要类似步骤(ODROID-C2 上包含启动参数的文件是 /boot/boot.ini)。
下面我们来设置 Dropbear SSH 密钥认证。在主机上(chroot 之外!)创建(无密码的)密钥对,并读取公钥:
$ ssh-keygen -N "" -f kali-dropbear
$ cat ./kali-dropbear.pub
将公钥添加到 /etc/dropbear-initramfs/authorized_keys。通过在密钥前添加以下内容,将 Dropbear SSH 访问限制为仅用于设置 cryptroot:
command="/scripts/local-top/cryptroot && kill -9 `ps | grep -m 1 'cryptroot' | cut -d ' ' -f 3`"
修复权限:
chmod 600 /etc/dropbear-initramfs/authorized_keys
编辑 /etc/fstab。原始内容:
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mmcblk0p2 / ext4 defaults,noatime 0 1
更新后的 / 设备改为 /dev/mapper/crypt_sdcard:
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
/dev/mmcblk0p1 /boot vfat defaults 0 2
/dev/mapper/crypt_sdcard / ext4 defaults,noatime 0 1
将这一行添加到 /etc/crypttab:
crypt_sdcard /dev/mmcblk0p2 none luks
修改 /etc/cryptsetup-initramfs/conf-hook,设置
CRYPTSETUP=y
以在 initramfs 镜像中纳入 cryptsetup 文件。
最后,为当前内核版本生成 initramfs 并退出 chroot(不必理会 mkinitramfs 期间的错误/警告):
# ls -l /lib/modules/ |awk -F" " '{print $9}'
4.4.50-v7+
# mkinitramfs -o /boot/initramfs.gz 4.4.50-v7+
请注意,在生成镜像时(尤其是在其他硬件上)必须小心,因为 uname -r 返回的是主机内核版本,而不是 chroot 中的版本。因此,例如在 ODROID-C2 上,/boot/mkuinitrd 无法开箱即用地工作,我们应该手动执行脚本中的命令(请针对其他硬件调整内核版本!):
# rm /boot/initrd.img-3.14.79
# update-initramfs -c -k 3.14.79
# mkimage -A arm64 -O linux -T ramdisk -C none -a 0 -e 0 -n "uInitrd" -d /boot/initrd.img-3.14.79 /boot/uInitrd
#
退出 chroot 环境:
exit
在 SD 卡上创建加密卷(并删除所有内容)之前,卸载文件系统并备份 rootfs:
# umount /mnt/chroot/boot
# umount /mnt/chroot/sys
# umount /mnt/chroot/proc
# mkdir -p /mnt/backup
# rsync -avh /mnt/chroot/* /mnt/backup/
卸载完整的 chroot:
# umount /mnt/chroot/dev/pts
# umount /mnt/chroot/dev
# umount /mnt/chroot
删除未加密的根分区(编号 2),并创建一个空分区(占满整个 SD 卡):
# echo -e "d\n2\nw" | fdisk /dev/mmcblk0
# echo -e "n\np\n2\n\n\nw" | fdisk /dev/mmcblk0
现在(可能)需要拔出并重新插入 SD 卡,以便注册新的分区。
使用强密码创建加密卷(此步骤会销毁原始 rootfs!):
# cryptsetup -v -y --cipher aes-cbc-essiv:sha256 --key-size 256 luksFormat /dev/mmcblk0p2
# cryptsetup -v luksOpen /dev/mmcblk0p2 crypt_sdcard
# mkfs.ext4 /dev/mapper/crypt_sdcard
将 rootfs 恢复到加密卷并关闭磁盘:
# mkdir -p /mnt/encrypted
# mount /dev/mapper/crypt_sdcard /mnt/encrypted/
# rsync -avh /mnt/backup/* /mnt/encrypted/
# umount /mnt/encrypted/
# cryptsetup luksClose /dev/mapper/crypt_sdcard
# sync
弹出 SD 卡,并在树莓派上进行测试。
首次启动过程会失败,并回退到 busybox。输入以下命令:
# cryptsetup luksOpen /dev/mmcblk0p2 crypt_sdcard
## provide password
# exit
你的设备现在应该可以启动了。使用之前选择的密码登录,然后运行:
mkinitramfs -o /boot/initramfs.gz
reboot
现在系统会以更友好的提示符要求你输入密码短语,而且你应该能够通过 SSH 连接到 busybox 并输入密码短语(如果你愿意,可以使用自定义的 known_hosts 文件):
$ ssh -o "UserKnownHostsFile=~/.ssh/known_hosts.initramfs" -i ~/.ssh/kali-dropbear [email protected]
一旦一切正常,不要忘记清理主机上的备份文件:
# rm -fr /mnt/backup
# rm -fr /mnt/chroot
如果要在启动期间获得完整的调试输出,可以在 cmdline.txt 中添加 debug=1。