给vps挂载iso安装系统并加密系统分区
部分VPS提供商的控制面板仅提供简单的重装系统功能,只能从其提供的有限的iso中选择安装,并且无法验证iso的完整性,或者根本不提供iso挂载功能,直接使用模板重置vps。因此我们无法安装自己所需的系统和对vps系统进行全盘加密。这篇文章简单记录一下如何在vps上挂载自定义iso安装系统并进行加密。
目的
- 为vps安装自己所需的发行版或特定的版本,如kali等
- luks全盘加密并提供ssh远程解密,重启后直接ssh远程输入luks密钥解密,无需登录vps控制面板操作控制台会话
适用条件
- 使用kvm/vmware等完全虚拟化技术的vps
- 控制面板不提供iso挂载功能或仅允许挂载其提供的iso
- 控制面板需提供控制台会话访问
安装系统
这里以vmware虚拟机为例子来说明如何安装全盘加密的ubuntu server 16.04。我在ESXi中准备了一台相同版本ubuntu server 16.04虚拟机,没有lvm,没有luks加密:
1 | $ uname -a |
安装过程大致是在grub2中使用memdisk将ubuntu的iso载入内存,然后引导安装。对于ubuntu来说,我们使用memdisk安装的时候用常规iso的话,在安装过程中会报”Your installation CD-ROM couldn’t be mounted. This probably means that the CD-ROM was not in the drive. If so you can insert it and try again.”这个错误,因此我们要使用网络安装版(Network installer)的iso。
下载syslinux,解压,并将memdisk解压到根目录备用:
1 | wget https://www.kernel.org/pub/linux/utils/boot/syslinux/6.xx/syslinux-6.03.tar.xz |
下载ubuntu网络安装iso到根目录备用:
1 | wget http://archive.ubuntu.com/ubuntu/dists/xenial-updates/main/installer-amd64/current/images/netboot/mini.iso -O /mini.iso |
安装过程需要使用网络,且vps所在网络环境可能不提供DHCP服务,因此需要记录网络配置备用,包括IP地址,子网掩码,网关等。
然后为grub2添加新的引导菜单。这里为了方便,我们仅修改grub2相关参数,在启动时手动操作。修改配置文件/etc/default/grub
,注释GRUB_HIDDEN_TIMEOUT
行,修改GRUB_TIMEOUT
数值为30,使grub2引导界面不会一闪已过,方便中断。最后运行命令update-grub
使grub2参数生效。
至此,准备工作完成。重启后从vps控制面板进入控制台会话,可以发现系统停在grub2引导界面等待引导。
按c进入命令行模式,并使用以下命令引导iso:
1 | insmod memdisk |
如果vps存在多个磁盘,可能会存在memdisk
和mini.iso
不在当前磁盘的情况,则需要先使用search -f "--set-root /mini.iso"
来指定root。一切正常的话,我们已经可以看到ubuntu安装界面:
安装过程和正常安装一样跟着向导一步一步操作就行。如果网络中没有DHCP服务的话会跳出手动配置网络的界面,将上面记录的网络信息填入;如果存在DHCP,但是分配的地址不能用于联网的话,在配置Hostname那一步里双击esc,选手动配置网络,然后填入网络信息。
配置过程中用户Home目录加密选No,因为我们采用lvm+luks全盘加密。选择磁盘界面,我们选择use entire disk and setup encrypted lvm
:
选择磁盘之后输入加密密码:
最后根据向导完成安装,记得勾选安装OpenSSH Server。
重启后会看到要求输入luks密码的界面:
输入刚设置的密码即可启动系统。至此,全盘加密的ubuntu server安装完成。
远程解密系统
全盘加密的系统,每次重启后都需要登录vps控制面板,在控制台会话里输入密码才能启动。我们可以将ssh集成到initramfs里,从而实现远程通过ssh输入密码解密系统。
在initramfs里创建root家目录与.ssh目录,并写入公钥:
1 | mkdir -p /etc/initramfs-tools/root/.ssh/ |
安装busybox
与dropbear
:
1 | apt-get install dropbear busybox |
编辑/etc/initramfs-tools/initramfs.conf
,配置网络与dropbear。
配置网络连接
在DEVICE=
下一行加入
1 | IP=IPADDR::GATEWAY:NETMASK::DEV:off |
更改dropbear端口,添加行
1 | DROPBEAR_OPTIONS="-p 2222" |
这里更改dropbear端口是为了避免连接时报错Host key verification failed
,因为vps系统ssh公钥和initramfs下dropbear的公钥是不一样的。
加入unlock脚本
1 | wget https://gist.githubusercontent.com/gusennan/712d6e81f5cf9489bd9f/raw/fda73649d904ee0437fe3842227ad8ac8ca487d1/crypt_unlock.sh -O /etc/initramfs-tools/hooks/crypt_unlock.sh |
最后更新initramfs
1 | update-initramfs -u |
重启后使用root用户通过证书认证从2222端口连接ssh,运行unlock
命令,输入密码即可解密并引导系统。
1 | $ ssh root@ip -p 2222 |
注意事项
- 以上操作均基于ubuntu server 16.04.3,如选择其他发行版或者其他版本,部分配置可能需要根据实际情况进行调整。
- 系统配置完成后修改用户密码和luks密码,防止在控制台会话做了键盘记录这种极端情况下密码被窃取。操作luks密码可以使用
cryptsetup
命令。 - 文中提到的全盘加密并非实际意义上的整个磁盘加密,仅指系统分区的加密,因为在启动时需要boot分区里的initramfs。
- 由于boot分区无法进行加密,第三方可以挂载此分区并对initramfs进行篡改,加入恶意代码截取密码。因此系统配置完成后,最好记录下boot分区里initramfs的hash值,在每次手动重启前确认该文件是否被篡改。或者在意外重启后,连上initramfs的ssh后手动挂载boot分区,检查文件hash,确认无误后才输入密码进行解密。