基础知识
-
Initrd(Initial RamDisk)
- Initrd是在Linux内核加载后,系统引导过程中挂载的一个临时根文件系统。
- 使用Initrd的启动过程分两步:
- 挂载Initrd
- 挂载rootfs
- Initrd的组成部分
-
/bin
一些必要的命令:busybox cat echo mount lsmod depmod insmod cryptsetup ...
-
/dev
一些必要的字符设备文件:console null zero tty0 ...
-
/lib
一些必要的动态链接库和内核模块:libc.so libblkid.so libuuid.so libcryptsetup.so e1000.ko xen-blkfront.ko ...
-
init
挂载Initrd后执行的shell脚本:- 从grub的CMDLINE获取rootfs所在分区及其他引导选项
- 加载内核模块
- 挂载rootfs(解密)
switch_root
-
- Initrd 非必须,很多情况下可以只使用内核便进入系统。但对于存在某些重要分区,需要在Initrd中进行操作(例如解密)的情况,Initrd就是必须的
- 文件格式:通常是一个经过gzip压缩的cpio归档格式(早期的Initrd是loop设备,可以挂载之后查看文件内容)
-
对称加密
- 特点:对源文件的加密和对加密文件的解密采用同一份密钥
- 优势:计算量小、算法公开、速度快、效率高
- 劣势:密钥的保存与传输成了安全性的重要考量、密钥数量巨大时难以管理
- 常见的对称加密算法:RC2、RC4、AES等
- RC4
- Ron Rivest在1987年设计,但RSA并未真正发表过RC4
- RC4后来被证明容易被破解,因此慢慢从SSL/TSL等众多舞台中退出
- 原理:主要是利用xor实现加密、解密使用同一份密钥
device mapper
device mapper
是一种linux内核提供的、用于建立物理块设备和虚拟块设备之间映射关系的框架-
基于
device mapper
的应用- 逻辑卷管理(LVM)
- dm-crypt/cryptsetup
- TrueCrypt
- Docker
-
创建或管理mappered device的两种方法(libdevmapper.so)
- 通过设备节点
/dev/mapper/control
- 通过shell的
dmsetup
命令
- 通过设备节点
dm-crypt/cryptsetup
-
dm-crypt
基于Linux内核提供的crypto API
,从2.5.45版本开始引入,是Linux内核提供的磁盘加密功能(内核态)。为了在用户态能够使用dm-crypt提供的功能,编译内核时需要打开以下三个选项:CONFIG_DM_CRYPT
CONFIG_BLK_DEV_DM
CONFIG_CRYPTO_XTS
-
cryptsetup
是提供用户使用的命令行工具(用户态),有些发行版可能需要单独安装gentoo: emerge cryptsetup
debian/ubuntu: apt-get install cryptsetup
centos/fedora: yum install cryptsetup
- ...
-
cryptsetup
的优缺点- 优势:
- 与LVM都基于device mapper机制,无缝衔接
- 众多发行版均已内置,无需额外安装
- 支持多种加密格式,如LUKS、TCRYPT等
- 缺点:
- 不能对系统中已有的数据加密,必须创建加密的分区
- 一旦忘记密码或丢失密钥文件,数据将永远丢失
- 优势:
LUKS on cryptsetup
# First, partition
Device Size Id Type
/dev/xvda1 3M 83 Linux
/dev/xvda2 300M 83 Linux
/dev/xvda3 2G 82 Linux swap / Solaris
/dev/xvda4 37.7G 83 Linux
# Second, encrypt using LUKS format
# Usage: cryptsetup [option] luksFormat <device> [key file]
# Example:
cryptsetup -q luksFormat /dev/xvda4 .key
# Third, open LUKS format disk
# Usage: cryptsetup [option] luksOpen <device> <name>
# Example:
cryptsetup -d .key luksOpen /dev/xvda4 root
# Fourth, make file system
# Now, using /dev/mapper/root instead of /dev/xvda4
mkfs.ext3 /dev/mapper/root
# Fifth, mount file system
mount /dev/mapper/root /mnt/gentoo
$df -h
Filesystem Size Mounted on
/dev/mapper/root 37.7G /mnt/gentoo
$blkid
# different block device, different UUID
/dev/xvda4: UUID="..." TYPE="crypto_LUKS" PARTUUID="..."
/dev/mapper/root: UUID="..." TYPE="ext3"
# Umount LUKS partition
umount /dev/xvda4
# Close LUKS partition
# Uasge: crypt luksClose <name>
cryptsetup luksClose root
-
加密原理
- LUKS格式的加密盘不能直接挂载
- 密码错误或密钥文件不正确时,
luksOpen
会失败
-
密钥文件
- 可以使用一个填充任意字符串的文件作为密钥文件
- 使用
dd
随机生成的密钥文件安全性更高
dd if=/dev/urandom of=.key bs=1 count=32
系统加密的例子
用
cryptsetup
对rootfs分区进行加密-
定制Initrd
- 使用linux内核提供的工具
gen_init_cpio
生成 - 将rootfs的秘钥文件包含在Initrd中
- Initrd中自定义
init
脚本,完成rootfs的解密和挂载操作
- 使用linux内核提供的工具
-
对boot分区中的Initrd文件加密
- 采用分区加密时,boot分区不能加密,因此使系统的Initrd文件暴露给入侵者。一旦Initrd被解包,rootfs的秘钥就被知晓了
- 使用对称加密方法对Initrd进行加密,实现简单,又加大了破解Initrd的难度,使系统文件处于较安全的状态
$./gen_init_cpio
Usage:
./gen_init_cpio <cpio_list>
<cpio_list> is a file containing newline separated entries that
describe the files to be included in the initramfs archive:
# a comment
file <name> <location> <mode> <uid> <gid> [<hard links>]
dir <name> <mode> <uid> <gid>
nod <name> <mode> <uid> <gid> <dev_type> <maj> <min>
slink <name> <target> <mode> <uid> <gid>
pipe <name> <mode> <uid> <gid>
sock <name> <mode> <uid> <gid>
<name> name of the file/dir/nod/etc in the archive
<location> location of the file in the current filesystem
expands shell variables quoted with ${}
<target> link target
<mode> mode/permissions of the file
<uid> user id (0=root)
<gid> group id (0=root)
<dev_type> device type (b=block, c=character)
<maj> major number of nod
<min> minor number of nod
<hard links> space separated list of other links to file
example:
# A simple initramfs
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
dir /sbin 0755 0 0
file /sbin/kinit /usr/src/klibc/kinit/kinit 0755 0 0