dm-crypt/加密整个系统
本文介紹了幾種常見的使用「dm-crypt」加密整個系統的方式,以及相比正常安裝過程所需的改動。官方安裝鏡像已經包含了加密所需的工具。
若要加密的是已有的未加密的文件系統,見 dm-crypt/設備加密#加密現有的未加密文件系統。
「dm-crypt」能為為根文件系統提供安全保護,且相比其它方案具更優的性能。相比僅僅加密部分非根文件系統,加密根文件系統可以隱藏許多敏感信息(如已安裝應用列表、用戶名等),並能避免通過locate、/var/log/等常見方式洩露數據。此外,由於除了引導加載程序和內核(通常情況下),所有數據都被加密,更難對系統進行未授權的改動。
除了上面提到的共同優點以外,各種加密方案還有如下特有的優缺點:
| 方案 | 優點 | 缺點 |
|---|---|---|
| #在單一分區上配置LUKS 展示了使用LUKS完全加密的根文件系統的基本方式,最直接。 |
|
|
|
#使用TPM2和安全啟動在單一分區上配置
與上例相似,並通過使用安全啟動、TPM2提高了安全性。 |
相比上例,本方法還有如下優點:
|
|
|
#在LUKS上配置LVM
在LUKS加密的單一分區上配置LVM,實現了分區靈活性。 |
|
|
|
#在LVM上配置LUKS
在LVM上層使用LUKS。 |
|
|
|
#在軟RAID上配置LUKS
在軟RAID上層使用LUKS。 |
|
|
|
#Plain dm-crypt
使用dm-crypt的plain模式(不使用LUKS頭及LUKS的多密鑰選項)。 |
|
|
|
#加密boot分區(GRUB)
展示了如何在使用GRUB時加密boot分區。 |
|
|
| #Root on ZFS |
|
雖然對於外界威脅,相比文件系統層面的加密,上述方案提供了好得多的保護。但也有一個共同的缺點:任何擁有密碼的用戶都能解密整個設備,進而訪問其它用戶的數據。若要防範上述風險,可以結合使用塊設備加密和文件系統加密。可參見靜態數據加密進行提前規劃。
對於本文中所有方案的分區策略的概述,參見dm-crypt/準備磁碟#分區。
此外,還需考慮是否設置加密的swap分區及設置方式。詳見Dm-crypt/交換分區加密。
加密整個系統可在設備失竊時保護數據,但不能抵禦邏輯層面的非法修改(例如,系統上運行的惡意軟體修改未加密的boot分區)。若有相關需求,還應參見dm-crypt/特殊應用#保護未加密的boot分區。
在使用固態硬碟時,可能需要啟用TRIM支持。但這可能影響安全性,詳見dm-crypt/特殊應用#固態硬碟的Discard/TRIM支持。
- 在任何情況下都不要直接在加密卷上運行文件系統修復工具(例如,fsck),否則,加密密鑰將永久丟失,使得所有加密內容無法被解密。只應當在解密後的設備上運行文件系統修復工具。
- Argon2 密鑰派生函數的設計方式使得其在運行時將占用大量內存(在默認設置下,每個加密卷將占用1GiB內存)。在設備內存較少或啟動時並行解密多個LUKS2分區的情況下,可能導致錯誤。可使用
--pbkdf-memory選項控制內存使用。[1] - GRUB對LUKS2的支持並不完善,詳見GRUB#加密的/boot。對於需要由GRUB解密的分區,建議使用PBKDF2密鑰派生函數(
cryptsetup luksFormat --pbkdf pbkdf2)。 - 對於ZFS,即使交換分區並沒有放置在zvol上,從休眠中喚醒時也有可能損壞存儲池。因此在配置休眠時需要額外注意。參考
本例說明了如何通過「dm-crypt」與LUKS,將安裝在單一分區上的系統進行加密。
+-----------------------+------------------------+-----------------------+ | boot分区 | LUKS加密的根分区 | 可选的用于其它分区的 | | | partition | 空闲空间 | | | | | | /boot | / | | | | | | | | /dev/mapper/root | | | |------------------------| | | /dev/sda1 | /dev/sda2 | | +-----------------------+------------------------+-----------------------+
本例的前幾步可在啟動到Arch Linux安裝鏡像後直接進行。
在創建分區前,應先查看dm-crypt/準備磁碟,了解安全地擦除整個磁碟的重要性,並掌握相關方法。
接下來,創建本例中的分區(至少需要/(/dev/sda2)和/boot(/dev/sda1),詳見分區。
在格式化分區時,不要使用安裝指南中的步驟,而是使用本節及下一節的步驟。
使用如下命令創建並掛載加密的根分區,dm-crypt/設備加密#使用 LUKS 模式加密設備中詳細介紹了進行的操作。若要使用非默認的加密選項(例如,修改加密算法,密鑰長度,扇區大小),在執行如下第一條指令前參見相關加密選項。
# cryptsetup -v luksFormat /dev/sda2 # cryptsetup open /dev/sda2 root
在解密的LUKS設備上創建文件系統。例如,要創建Ext4文件系統,執行:
# mkfs.ext4 /dev/mapper/root
將根分區掛載到/mnt:
# mount /dev/mapper/root /mnt
確保設備映射正常:
# umount /mnt # cryptsetup close root # cryptsetup open /dev/sda2 root # mount /dev/mapper/root /mnt
若還創建了其它分區(例如,/home),則對於除了/boot的其它分區,執行類似操作。在啟動時解密其它分區的方法可參見dm-crypt/加密非root文件系統#自動解鎖並掛載。
注意,對於每個要加密並掛載的塊設備,都需要單獨設置密鑰,這將導致在啟動時需要多次輸入密鑰,造成不便。可通過在根分區中存儲密鑰文件,並通過修改crypttab設置,自動使用密鑰文件解鎖其它設備。詳見dm-crypt/設備加密#使用LUKS來格式化帶有密鑰文件的分區。
對於加密根分區的配置,需要設置非加密的/boot分區。
對於UEFI啟動的系統,使用如下命令格式化新創建的EFI 系統分區:
# mkfs.fat -F32 /dev/sda1
對於傳統BIOS啟動的系統:
# mkfs.ext4 /dev/sda1
之後,創建boot分區的掛載點並掛載分區:
# mount --mkdir /dev/sda1 /mnt/boot
在安裝指南#掛載分區步驟時,應當掛載/dev/mapper/*中的相應設備(包含LUKS加密的設備的解密後的版本),而不是LUKS加密的設備自身對應的分區。不過,對於未加密的/boot分區,仍應當直接掛載到/mnt/boot(假設在安裝過程中,根分區被掛載到/mnt)。
在安裝指南#關於_initramfs步驟前,需要在新安裝的系統中完成如下操作:
若使用基於busybox的initramfs,在mkinitcpio.conf中添加keyboard和encrypt鉤子。此外,若要使用非標準鍵盤布局,添加keymap鉤子;若要自定義控制台字體,添加consolefont鉤子。
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt filesystems fsck)
若使用基於systemd的initramfs,在mkinitcpio.conf中添加keyboard和sd-encrypt鉤子。此外,若要使用非標準鍵盤布局,或要自定義控制台字體,添加sd-vconsole鉤子。
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)
保存上述修改後,重新生成initramfs。其它可能需要用到的鉤子以及配置細節參見Dm-crypt/系統配置#mkinitcpio。
要在啟動時解密已加密的根分區,需配置引導加載程序,設置如下內核參數:
cryptdevice=UUID=device-UUID:root root=/dev/mapper/root
若使用的是sd-encrypt,則應該添加如下內核參數:
rd.luks.name=device-UUID=root root=/dev/mapper/root
device-UUID指的是LUKS超級塊的UUID,在本例中為/dev/sda2對應的UUID。詳見塊設備持久化命名。
本例與#在單一分區上配置LUKS相似,但通過使用安全啟動和可信平台模塊,使啟動過程更安全。
在本配置方案中,只有EFI 系統分區是未加密的,存儲經過簽名以用於安全啟動的統一內核映像和systemd-boot。在本配置中,若安全啟動功能被關閉,或者安全啟動的密鑰資料庫被修改,則TPM將不會釋放用於解密分區的密鑰。此時,仍可以使用配置過程中創建的恢復密鑰解密數據。此外,還可要求在解密數據前必須輸入設置的TPM PIN碼。本配置方案類似Windows中的BitLocker和macOS中的FileVault。
在繼續之前,確保已經詳細閱讀了可信平台模塊#LUKS_數據加密,並著重留意其中的警告。
本例中的分區按照符合Systemd#GPT分區自動掛載的方式創建,因此無需fstab、crypttab文件。
+-----------------------+---------------------------------+ | EFI系统分区 | LUKS加密的根分区 | | | | | | | | /boot | / | | | | | | /dev/mapper/root | | |---------------------------------| | /dev/sda1 | /dev/sda2 | +-----------------------+---------------------------------+
按照安裝指南#創建硬碟分區前的步驟進行基本配置。之後,按本文下一節的內容進行磁碟分區。
在創建分區前,應先查看dm-crypt/準備磁碟,了解安全地擦除整個磁碟的重要性,並掌握相關方法。
使用GUID分區表 (GPT),並創建需要的分區。
創建大小合適的EFI 系統分區(在本例中,使用/dev/sda1)。該分區將被掛載到/boot。
在磁碟的剩餘空間上創建根分區(在本例中,使用/dev/sda2)。根分區將被加密,並掛載到/。將根分區的分區類型GUID設置為4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709(在fdisk中,設置為"Linux root (x86-64)"類型;在gdisk中,設置為8304類型)。
使用如下命令創建並掛載加密的根分區,dm-crypt/設備加密#使用 LUKS 模式加密設備中詳細介紹了進行的操作。
若要使用非默認的加密選項(例如,修改加密算法,密鑰長度,扇區大小),或者不想使用TPM解密,在執行如下第一條指令前參見相關加密選項。
創建並掛載LUKS卷(由於在配置完成後將擦除密碼槽位,可以直接使用空密碼):
# cryptsetup luksFormat /dev/sda2 # cryptsetup open /dev/sda2 root
在解密的LUKS設備上創建文件系統。例如,要創建Ext4文件系統,執行:
# mkfs.ext4 /dev/mapper/root
將根分區掛載到 /mnt:
# mount /dev/mapper/root /mnt
格式化新創建的EFI系統分區,並掛載:
# mount --mkdir /dev/sda1 /mnt/boot
繼續執行安裝指南#關於_initramfs前的步驟。注意無需執行安裝指南#生成_fstab_文件步驟。
修改mkinitcpio.conf中的HOOKS=為如下內容,以構建可用的基於systemd的initramfs:
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck)
按照統一內核映像#mkinitcpio中的步驟配置統一內核映像。
由於/boot/EFI/Linux目錄暫未由啟動加載程序創建,暫時不要重新生成initramfs。
可以直接通過UEFI啟動內核,而無需引導加載程序。
若仍需使用引導加載程序,可以安裝systemd-boot:
# bootctl install
systemd-boot可自動識別mkinitcpio生成的統一內核映像,無需在/boot/loader/entries/手動添加條目。
其它配置參見systemd-boot#更新 EFI 啟動管理器 、Systemd-boot#配置。
重新生成initramfs,並確保相關鏡像成功生成。
不要忘記設置 root 密碼,重啟以完成安裝。
為了啟用安全啟動,需要為引導加載程序、EFI鏡像簽名。可使用sbctl簡單、快速地實現。
在簽名引導加載程序並啟用安全啟動後,可以向TPM註冊密鑰用以解鎖LUKS卷。如下命令將移創建LUKS卷時設置的空密碼,創建綁定到TPM PCR 7(安全啟動狀態和已註冊證書)寄存器的密鑰,並創建恢復密鑰,用於在TPM出現問題時解密卷。若安全啟動鏈完好,TPM將自動釋放密鑰。詳見systemd-cryptenroll#Trusted Platform Module、systemd-cryptenroll(1)。
# systemd-cryptenroll /dev/sda2 --recovery-key # systemd-cryptenroll /dev/sda2 --wipe-slot=empty --tpm2-device=auto --tpm2-pcrs=7
--tpm2-with-pin=yes參數。
在加密的單個分區上配置LVM是一種較為直接的方案。該方案將LVM設置在一個大的加密塊設備中,LVM結構只在塊設備解密,掃描並掛載LVM物理卷後才可見。
示例磁碟結構如下:
+-----------------------------------------------------------------------+ +----------------+ | 逻辑卷 1 | 逻辑卷 2 | 逻辑卷 3 | | boot分区 | | | | | | | | [SWAP] | / | /home | | /boot | | | | | | | | /dev/MyVolGroup/swap | /dev/MyVolGroup/root | /dev/MyVolGroup/home | | | |_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _| | (可能在其他 | | | | 设备上) | | 使用LUKS加密的分区 | | | | /dev/sda1 | | /dev/sdb1 | +-----------------------------------------------------------------------+ +----------------+
- dm-crypt/特殊應用#在加密系統時使用分離的LUKS頭介紹了如何將LUKS頭單獨存放於USB設備上,實現兩步驗證。
- dm-crypt/Specialties#Encrypted /boot and a detached LUKS header on USB則將LUKS頭、加密的boot分區、加密的密鑰文件都存放在USB設備上。
在創建分區前,應先查看dm-crypt/準備磁碟,了解安全地擦除整個磁碟的重要性,並掌握相關方法。
創建一個大於1GiB的分區用於/boot。
/boot。創建一個分區,用於存儲整個加密的LVM。
在上述創建的分區上配置LUKS作為LVM的容器(若要修改加密選項,參見dm-crypt/設備加密#LUKS 模式的加密選項):
# cryptsetup luksFormat /dev/sda1
打開創建的容器:
# cryptsetup open /dev/sda1 cryptlvm
現在可通過/dev/mapper/cryptlvm訪問解密的容器。
在解密的LUKS容器上創建物理卷:
# pvcreate /dev/mapper/cryptlvm
創建卷組(本例中使用MyVolGroup,也可使用其它名稱),並加入先前創建的物理卷:
# vgcreate MyVolGroup /dev/mapper/cryptlvm
在卷組中創建邏輯卷:
-l 100%FREE創建占滿所有剩餘空間的最後一個邏輯卷後,使用類似lvreduce -L -256M MyVolGroup/home的命令減少該邏輯卷的大小。# lvcreate -L 4G -n swap MyVolGroup # lvcreate -L 32G -n root MyVolGroup # lvcreate -l 100%FREE -n home MyVolGroup
在每個邏輯卷上創建文件系統。例如,若根分區和home分區使用Ext4文件系統:
# mkfs.ext4 /dev/MyVolGroup/root # mkfs.ext4 /dev/MyVolGroup/home # mkswap /dev/MyVolGroup/swap
掛載文件系統:
# mount /dev/MyVolGroup/root /mnt # mount --mkdir /dev/MyVolGroup/home /mnt/home # swapon /dev/MyVolGroup/swap
引導加載程序從/boot目錄加載內核、initramfs和自身的配置文件。可使用任何引導加載程序支持的文件系統。
為/boot分區創建文件系統。對於UEFI啟動的系統,使用如下命令格式化新創建的EFI 系統分區:
# mkfs.fat -F32 /dev/sdb1
對於傳統BIOS啟動的系統:
# mkfs.ext4 /dev/sdb1
將上述分區掛載到/mnt/boot:
# mount --mkdir /dev/sdb1 /mnt/boot
繼續執行安裝指南#開始安裝系統中的步驟。之後回到本頁,執行修改後的關於 initramfs、安裝引導程序步驟。
若使用基於busybox的initramfs,在mkinitcpio.conf中添加keyboard、encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,添加keymap鉤子;若要自定義控制台字體,添加consolefont鉤子。
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)
若使用基於systemd的initramfs,在mkinitcpio.conf中添加keyboard、sd-encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,或要自定義控制台字體,添加sd-vconsole鉤子。
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
保存上述修改後,重新生成initramfs。其它可能需要用到的鉤子以及配置細節參見Dm-crypt/系統配置#mkinitcpio。
注意:若使用dracut生成mkinitcpio,則其已經包含必要的模塊,無需額外配置。
要在啟動時解密已加密的根分區,需配置引導加載程序設置如下內核參數:
cryptdevice=UUID=device-UUID:cryptlvm root=/dev/MyVolGroup/root
若使用的是sd-encrypt,則應該添加如下內核參數:
rd.luks.name=device-UUID=cryptlvm root=/dev/MyVolGroup/root
device-UUID指的是LUKS超級塊的UUID,在本例中為/dev/sda1對應的UUID。詳見塊設備持久化命名。
若使用dracut,一般可使用如下參數:
rd.luks.uuid=device-UUID root=/dev/MyVolGroup/root
有時,需要設置更多參數:
rd.luks.uuid=luks-deviceUUID rd.lvm.lv=MyVolGroup/root rd.lvm.lv=MyVolGroup/swap root=/dev/mapper/MyVolGroup-root rootfstype=ext4 rootflags=rw,relatime
為了在LVM上層設置加密,首先要設置LVM卷,用作加密分區的基礎。在本方案中,可同時創建加密及未加密的分區。
下例展示了在LVM上配置LUKS加密卷,並使用密鑰文件解鎖home分區。對於swap分區,使用臨時加密卷,以確保在每次重啟後,都重新配置swap分區的加密,防止敏感信息洩露,提升安全性。若熟悉LVM配置,可自行修改LVM分區方案。
若要創建橫跨多個磁碟的邏輯卷,或要將已有邏輯卷擴展到其它已配置好的磁碟上,詳見dm-crypt/特殊應用#將LVM拓展到多個磁碟上。注意調整邏輯卷的大小後,LUKS加密容器的大小也需要調整。
分區方案如下:
+----------------+-------------------------------------------------------------------------------------------------+ | boot分区 | dm-crypt plain加密的分区 | LUKS加密的分区 | LUKS加密的分区 | | | | | | | /boot | [SWAP] | / | /home | | | | | | | | /dev/mapper/swap | /dev/mapper/root | /dev/mapper/home | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| | | 逻辑卷 1 | 逻辑卷 2 | 逻辑卷 3 | | | /dev/MyVolGroup/cryptswap | /dev/MyVolGroup/cryptroot | /dev/MyVolGroup/crypthome | | |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _| | | | | /dev/sda1 | /dev/sda2 | +----------------+-------------------------------------------------------------------------------------------------+
按照dm-crypt/準備磁碟#dm-crypt 擦除空設備或分區隨機擦除/dev/sda2。
# pvcreate /dev/sda2 # vgcreate MyVolGroup /dev/sda2 # lvcreate -L 4G -n cryptswap MyVolGroup # lvcreate -L 32G -n cryptroot MyVolGroup # lvcreate -l 100%FREE -n crypthome MyVolGroup
# cryptsetup luksFormat /dev/MyVolGroup/cryptroot # cryptsetup open /dev/MyVolGroup/cryptroot root
在解密後的設備上創建文件系統,並掛載到對應掛載點。例如,要創建Ext4文件系統:
# mkfs.ext4 /dev/mapper/root # mount /dev/mapper/root /mnt
關於加密選項的更多信息,詳見dm-crypt/設備加密#LUKS 模式的加密選項。
注意/home的加密會在#加密/home邏輯卷步驟中進行。
open操作。為/boot分區創建文件系統。對於UEFI啟動的系統,使用如下命令格式化新創建的EFI 系統分區:
# mkfs.fat -F32 /dev/sda1
對於傳統BIOS啟動的系統:
# mkfs.ext4 /dev/sda1
之後,創建boot分區的掛載點並掛在分區:
# mount --mkdir /dev/sda1 /mnt/boot
若使用基於busybox的initramfs,在mkinitcpio.conf中添加keyboard、encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,添加keymap鉤子;若要自定義控制台字體,添加consolefont鉤子。
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block lvm2 encrypt filesystems fsck)
若使用基於systemd的initramfs,在mkinitcpio.conf中添加keyboard、sd-encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,或要自定義控制台字體,添加sd-vconsole鉤子。
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
保存上述修改後,重新生成initramfs。其它可能需要用到的鉤子以及配置細節參見Dm-crypt/系統配置#mkinitcpio。
要在啟動時解密已加密的根分區,需配置引導加載程序設置如下內核參數:
cryptdevice=UUID=device-UUID:root root=/dev/mapper/root
若使用的是sd-encrypt,則應該添加如下內核參數:
rd.luks.name=device-UUID=root root=/dev/mapper/root
device-UUID指的是LUKS超級塊的UUID,在本例中為/dev/MyVolGroup/cryptroot對應的UUID。詳見塊設備持久化命名。
若使用的是dracut,需要一系列更複雜的參數:
kernel_cmdline="rd.luks.uuid=luks-deviceUUID rd.lvm.lv=MyVolGroup/root rd.lvm.lv=MyVolGroup/swap root=/dev/mapper/MyVolGroup-root rootfstype=ext4 rootflags=rw,relatime"
crypttab用於解密設備,fstab用於掛載文件系統。如下配置將在每次重啟時用不同的密鑰重新加密swap分區:
/etc/crypttab
swap /dev/MyVolGroup/cryptswap /dev/urandom swap,cipher=aes-xts-plain64,size=256,sector-size=4096
/etc/fstab
/dev/mapper/root / ext4 defaults 0 1 UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /boot ext4 defaults 0 2 /dev/mapper/swap none swap defaults 0 0
由於本方案使用LVM作為第一層,dm-crypt作為第二層,每個加密邏輯卷都需要單獨進行加密解密配置。此外,顯然,和臨時文件系統可採用臨時隨機密鑰加密不同,/home對應的邏輯卷應該採用持久不變的密鑰。下列命令假定你已經重啟進入了安裝好的系統。否則,需要調整相應路徑。
為了避免在系統啟動時輸入兩次密碼,創建密鑰文件:
# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/home.key
/home邏輯卷將採用上述密鑰文件加密:
# cryptsetup luksFormat -v /dev/MyVolGroup/crypthome /etc/cryptsetup-keys.d/home.key # cryptsetup -d /etc/cryptsetup-keys.d/home.key open /dev/MyVolGroup/crypthome home
在解密後的設備上創建文件系統,並掛載到對應掛載點。例如,要創建Ext4文件系統:
# mkfs.ext4 /dev/mapper/home # mount /dev/mapper/home /home
/etc/crypttab
home /dev/MyVolGroup/crypthome none
/etc/fstab
/dev/mapper/home /home ext4 defaults 0 2
下例基於真實的工作站筆記本設置,該工作站有兩塊大小相同的SSD及一塊大容量機械硬碟。在本配置中,對所有磁碟採用LUKS加密(包括/boot),並將兩塊SSD組成了RAID0陣列。系統啟動時,在GRUB中輸入正確的密碼後,將用解密出的密鑰文件解密所有分區。
本方案採用的分區配置非常簡單,組成的RAID陣列掛載在/(沒有單獨的/boot 分區),解密後的機械硬碟掛載在/data。
注意對於本方案,定期的備份非常重要。若兩塊SSD中的任何一塊損壞,整個RAID陣列中的數據都將丟失。若要求較高的容錯能力,應選擇其它RAID級別。
本配置中的加密方式不是可抵賴加密。
在之後的命令中,假定採用如下塊設備設置:
/dev/sda = 第一块SSD /dev/sdb = 第二块SSD /dev/sdc = 机械硬盘
+---------------------+---------------------------+---------------------------+ +---------------------+---------------------------+---------------------------+ +---------------------------+ | BIOS boot分区 | EFI系统分区 | LUKS加密的分区 | | BIOS 启动分区 | EFI系统分区 | LUKS加密的分区 | | LUKS加密的分区 | | | | | | | | | | | | | /efi | / | | | /efi | / | | /data | | | | | | | | | | | | | | /dev/mapper/root | | | | /dev/mapper/root | | | | +---------------------------+---------------------------+ | +---------------------------+---------------------------+ | | | | RAID1 array (part 1 of 2) | RAID0 array (part 1 of 2) | | | RAID1 array (part 2 of 2) | RAID0 array (part 2 of 2) | | | | | | | | | | | | | | | /dev/md/ESP | /dev/md/root | | | /dev/md/ESP | /dev/md/root | | /dev/mapper/data | | +---------------------------+---------------------------+ | +---------------------------+---------------------------+ +---------------------------+ | /dev/sda1 | /dev/sda2 | /dev/sda3 | | /dev/sdb1 | /dev/sdb2 | /dev/sdb3 | | /dev/sdc1 | +---------------------+---------------------------+---------------------------+ +---------------------+---------------------------+---------------------------+ +---------------------------+
在之後的操作中,需要根據實際情況替換上述配置。
在創建分區前,應先查看dm-crypt/準備磁碟,了解安全地擦除整個磁碟的重要性,並掌握相關方法。
對於使用GPT分區表的BIOS啟動的系統,需創建一個大小為1MiB的BIOS啟動分區,GRUB將在此存儲第二階段的BIOS引導加載程序。不要掛載該分區。
對於UEFI啟動的系統,需創建大小適當的EFI 系統分區,並掛載到/efi。
對於設備上的剩餘空間,創建一個用於"Linux RAID"的分區(本例中為/dev/sda3)。對於MBR分區表,選擇fd分區類型ID;對於GPT分區表,選擇A19D880F-05FC-4D3B-A006-743F0F84911E分區類型GUID。
一旦在/dev/sda上創建好了分區,可使用下列命令將它們的配置克隆到/dev/sdb上:
# sfdisk -d /dev/sda > sda.dump # sfdisk /dev/sdb < sda.dump
對於機械硬碟,創建單個占據整個磁碟的Linux分區(/dev/sdc1)。
創建用於兩塊SSD的RAID陣列:
- 對於兩塊SSD,EFI系統分區必須能在每塊SSD上單獨訪問,因此只能存放在RAID1上。
- 必須通過
--metadata=1.0選項將RAID superblock放置在EFI系統分區的後部,否則固件將不能訪問EFI系統分區。
# mdadm --create --verbose --level=1 --metadata=1.0 --raid-devices=2 /dev/md/ESP /dev/sda2 /dev/sdb2
對於根分區,本例採用了RAID0。可根據實際偏好與需要選擇其它RAID級別。
# mdadm --create --verbose --level=0 --metadata=1.2 --raid-devices=2 /dev/md/root /dev/sda3 /dev/sdb3
dm-crypt/準備磁碟中介紹了通過使用隨機密鑰創建加密卷,並向加密卷中寫入/dev/zero產生的全零數據來隨機擦除設備的方法。此外,也可使用dd與/dev/random或/dev/urandom來擦除,不過速度較慢。
# cryptsetup open --type plain --sector-size 4096 --key-file /dev/urandom /dev/md/root to_be_wiped # dd if=/dev/zero of=/dev/mapper/to_be_wiped bs=1M status=progress # cryptsetup close to_be_wiped
對本例中的機械硬碟(/dev/sdc1)也需重複上述操作。
為/dev/md/root設置加密:
cryptsetup luksFormat --pbkdf pbkdf2)。# cryptsetup -v luksFormat --pbkdf pbkdf2 /dev/md/root # cryptsetup open /dev/md/root root
在解密後的設備上創建文件系統。例如,要創建Ext4文件系統:
# mkfs.ext4 /dev/mapper/root
將根分區掛載到/mnt:
# mount /dev/mapper/root /mnt
對機械硬碟,類似的:
# cryptsetup -v luksFormat /dev/sdc1 # cryptsetup open /dev/sdc1 data # mkfs.ext4 /dev/mapper/data # mount --mkdir /dev/mapper/data /mnt/data
對於UEFI啟動的系統,還需設置EFI系統分區:
# mkfs.fat -F32 /dev/md/ESP # mount --mkdir /dev/md/ESP /mnt/efi
對於本例中通過LUKS加密的系統,編輯/etc/default/grub以配置GRUB:
GRUB_CMDLINE_LINUX="cryptdevice=/dev/md/root:root" GRUB_ENABLE_CRYPTODISK=y
對於較新的設備,可能需要使用USB鍵盤在GRUB中輸入密碼。這需要啟用固件中的」legacy USB support「,或在/etc/default/grub中添加:
GRUB_TERMINAL_INPUT="usb_keyboard" GRUB_PRELOAD_MODULES="usb usb_keyboard ohci uhci ehci"
否則在提示輸入LUKS密碼時可能無法使用鍵盤。詳見Dm-crypt/系統配置#內核參數、GRUB#加密的/boot。
將GRUB安裝到兩塊SSD上(事實上,僅安裝到/dev/sda也是可行的):
# grub-install --target=i386-pc /dev/sda # grub-install --target=i386-pc /dev/sdb # grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB # grub-mkconfig -o /boot/grub/grub.cfg
進行如下步驟可避免在啟動時需輸入兩次密碼(第一次發生在GRUB解密LUKS設備,第二次發生在initramfs接管系統時)。首先要創建密鑰文件,然後將該密鑰文件加入到initramfs鏡像中以便encrypt鉤子解密根分區。詳見dm-crypt/設備加密#在_initramfs_中嵌入密鑰文件。
- 創建密鑰文件並向其中添加
/dev/md/root的密碼。 - 創建另一個密鑰文件以便於在啟動時解密機械硬碟(
/dev/sdc1)。為了便於以後可能的需要恢復的情況,不要移動/刪除上述密鑰文件。接下來編輯/etc/crypttab以在啟動時解密機械硬碟。詳見Dm-crypt/系統配置#使用密鑰文件解密。
配置fstab以掛載根分區、data分區、EFI系統分區:
/dev/mapper/root / ext4 rw,noatime 0 1 /dev/mapper/data /data ext4 defaults 0 2 /dev/md/ESP /efi vfat rw,relatime,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,tz=UTC,errors=remount-ro 0 2
保存RAID配置:
# mdadm --detail --scan >> /etc/mdadm.conf
編輯mkinitcpio.conf,包含密鑰文件,並添加所需的鉤子:
FILES=(/crypto_keyfile.bin) HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block mdadm_udev encrypt filesystems fsck)
與LUKS不同,dm-crypt的plain模式無需在加密設備前附加LUKS頭,本方案利用該特點在未分區的硬碟上設置加密的系統。對於他人,將無法區分用該方式加密的硬碟與與用隨機數據填充的硬碟,即所謂可抵賴加密。詳見wikipedia:Disk encryption#Full disk encryption。
注意,除非需要將整個硬碟全部加密,否則,無論是加密整個系統還是部分分區,使用之前小節中介紹的基於LUKS的方法都是更好的選擇。因為在plain模式中,無法使用LUKS特有的功能,例如支持多個密碼、密鑰文件的密鑰管理,主密鑰備份,原位重新加密。
由於不依賴主密鑰,可避免主密鑰損壞或被銷毀導致的單點故障,plain模式對數據損壞的承受能力更強。此外,若尤為在意對SSD的TRIM支持,也可以使用plain模式。然而,在plain模式下,要到達與LUKS模式相同的加密強度,需要手動配置加密選項。詳見靜態數據加密#加密的元數據。
- 通過cryptsetup的
--header選項使用分離的LUKS頭。注意若使用該方案則不能使用標準的"encrypt"鉤子,不過可對該鉤子進行修改。 - tcplay 在無LUKS頭加密模式下提供了PBKDF2函數。
本方案使用了兩個U盤:
- 一個用於引導設備,同時存儲用於解密plain加密設備的配置選項;
- 一個用於密鑰文件,將按原始比特位存儲,故不了解加密方案的攻擊者只能看到一串仿佛隨機的數據,而非可見的普通文件。詳見Wikipedia:Security through obscurity。要準備密鑰文件,參見dm-crypt/Device encryption#Keyfiles。
磁碟布局如下:
+----------------------+----------------------+----------------------+ +----------------+ +----------------+ | 逻辑卷 1 | 逻辑卷 2 | 逻辑卷 3 | | 启动设备 | | 密钥 | | | | | | | | 存储设备 | | / | [SWAP] | /home | | /boot | | (在本例中 | | | | | | | | 未分区) | | /dev/MyVolGroup/root | /dev/MyVolGroup/swap | /dev/MyVolGroup/home | | /dev/sdb1 | | /dev/sdc | |----------------------+----------------------+----------------------| |----------------| |----------------| | /dev/sda 使用plain模式加密并配置LVM | | U盘 1 | | U盘 2 | +--------------------------------------------------------------------+ +----------------+ +----------------+
- 也可以只使用一個U盤,如下為兩種方式:
- 在U盤(/dev/sdb)的另一個分區(/dev/sdb2)上存儲密鑰。
- 直接複製密鑰文件到initramfs中。例如,在
/etc/mkinitcpio.conf中設置FILES=(/etc/cryptsetup-keys.d/root.key)將複製/etc/cryptsetup-keys.d/root.key密鑰文件到initramfs鏡像中。要使得encrypt鉤子從initramfs鏡像中讀取密鑰文件,在文件名前添加rootfs:前綴,例如,cryptkey=rootfs:/etc/cryptsetup-keys.d/root.key。
- 此外,也可使用足夠安全的密碼解密。
向解密後的映射設備中填充隨機數據是非常重要的。尤其是在本例中。
詳見dm-crypt/準備磁碟、dm-crypt/準備磁碟#dm-crypt_專用方案
在本例中,使用/dev/sda,並使用aes-xts加密算法,密鑰長度為512位,並使用密鑰文件加密:
# cryptsetup open --type plain --cipher=aes-xts-plain64 --offset=0 --key-file=/dev/sdc --key-size=512 --sector-size 4096 /dev/sda cryptlvm
與使用LUKS不同,每次要解密設備時必須使用上述「完整」的命令,故一定要牢記加密算法、密鑰文件相關信息。
檢查有關/dev/mapper/cryptlvm的映射條目已建立:
# fdisk -l
- 若無需使用LVM提供的功能,cryptsetup FAQ提倡直接在解密後的設備上創建文件系統,而不創建LVM。
- 若LVM卷組中包含ext4文件系統的邏輯卷,為了便於使用e2scrub(8)工具,至少在卷組中保留256MiB的空閒空間。若使用
-l 100%FREE參數創建了最後一個邏輯卷,可以使用lvreduce -L -256M MyVolGroup/home留出256MiB的空閒空間。
接下來,在解密後產生的映射設備上設置LVM邏輯卷,詳見Install Arch Linux on LVM:
# pvcreate /dev/mapper/cryptlvm # vgcreate MyVolGroup /dev/mapper/cryptlvm # lvcreate -L 32G MyVolGroup -n root # lvcreate -L 4G MyVolGroup -n swap # lvcreate -l 100%FREE MyVolGroup -n home
格式化並掛載上述分區並激活swap,詳見文件系統#創建文件系統。
# mkfs.ext4 /dev/MyVolGroup/root # mkfs.ext4 /dev/MyVolGroup/home # mount /dev/MyVolGroup/root /mnt # mount --mkdir /dev/MyVolGroup/home /mnt/home # mkswap /dev/MyVolGroup/swap # swapon /dev/MyVolGroup/swap
可直接將單獨的U盤(通常使用FAT32文件系統)作為/boot分區。或者,若要手動分區,使用分區工具創建大小為1GiB的小分區,並建立文件系統。
# mkfs.fat -F32 /dev/sdb1 # mount --mkdir /dev/sdb1 /mnt/boot
若使用基於busybox的initramfs,在mkinitcpio.conf中添加keyboard、encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,添加keymap鉤子;若要自定義控制台字體,添加consolefont鉤子。
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)
保存上述修改後,重新生成initramfs。其它可能需要用到的鉤子以及配置細節參見Dm-crypt/系統配置#mkinitcpio。
要從加密的根分區啟動,需通過引導加載程序設置如下內核參數(注意512位對應64位元組):
cryptdevice=/dev/disk/by-id/disk-ID-of-sda:cryptlvm:sector-size=4096 cryptkey=/dev/disk/by-id/disk-ID-of-sdc:0:64 crypto=:aes-xts-plain64:512:0:
disk-ID-of-disk表示相應磁碟的id,詳見塊設備持久化命名。
對於其它可能需要的內核參數,詳見Dm-crypt/系統配置#內核參數。
/boot分區所在的U盤上。
對於BIOS啟動的系統:
# grub-install --target=i386-pc --recheck /dev/sdb
對於UEFI啟動的系統:
# grub-install --target=x86_64-efi --efi-directory=/boot --removable
或許希望在系統啟動後移除啟動用的U盤。由於/boot分區並不常用,可在/etc/fstab的相應行中添加noauto選項:
/etc/fstab
# /dev/sdb1 UUID=XXXX-XXXX /boot vfat noauto,rw,noatime 0 2
然而,若需要更新initramfs、內核、引導加載程序使用的相關文件時,則必須掛載/boot分區。由於fstab中存在相關條目,只需執行如下命令即可掛載:
# mount /boot
本配置使用與#在LUKS上配置LVM相同的分區結構和配置。但使用了GRUB引導加載程序,其能從LVM邏輯卷和LUKS加密的/boot上啟動系統。詳見GRUB#加密的/boot
本例中的磁碟結構如下:
+---------------------+----------------------+----------------------+----------------------+----------------------+ | BIOS boot分区 | EFI系统分区 | 逻辑卷 1 | 逻辑卷 2 | 逻辑卷 3 | | | | | | | | | /efi | / | [SWAP] | /home | | | | | | | | | | /dev/MyVolGroup/root | /dev/MyVolGroup/swap | /dev/MyVolGroup/home | | /dev/sda1 | /dev/sda2 |----------------------+----------------------+----------------------+ | 未加密 | 未加密 | /dev/sda3 使用LUKS加密并配置LVM | +---------------------+----------------------+--------------------------------------------------------------------+
- 所有提供的案例僅用作示例。可按需與其它方案結合使用。此外,可參見#在LUKS上配置LVM中介紹的兩種變形。
- 可以使用cryptbootAUR中的
cryptboot腳本簡化加密boot分區的管理(包括掛載、卸載、軟體包更新)。此外,該腳本與UEFI安全啟動配合還可抵禦邪惡女傭攻擊。更多信息及存在的問題見cryptboot project。
在創建分區前,應先查看dm-crypt/準備磁碟,了解安全地擦除整個磁碟的重要性,並掌握相關方法。
對於UEFI啟動的系統,創建大小合適的EFI 系統分區,將掛載該分區到/efi。
對於BIOS + GPT啟動的系統,創建大小為1MiB的BIOS啟動分區,GRUB將在該分區中存儲第二階段引導加載程序,不要手動掛載該分區。
對於BIOS + MBR啟動的系統,無需創建BIOS啟動分區。
創建一個類型為8309的分區用於加密的LVM。
創建LUKS加密容器:
cryptsetup luksFormat --pbkdf pbkdf2)。# cryptsetup luksFormat --pbkdf pbkdf2 /dev/sda3
關於加密選項的更多信息,在執行上述命令前參見dm-crypt/設備加密#LUKS 模式的加密選項。
分區結構應與下述相似:
# gdisk -l /dev/sda
... Number Start (sector) End (sector) Size Code Name 1 2048 4095 1024.0 KiB EF02 BIOS boot partition 2 4096 2101247 1024.0 MiB EF00 EFI system partition 3 2101248 69210111 32.0 GiB 8309 Linux LUKS
打開LUKS加密容器:
# cryptsetup open /dev/sda3 cryptlvm
解密後的容器將在/dev/mapper/cryptlvm。
本例中邏輯卷的結構與#在LUKS上配置LVM中的相同。因此,只需遵循#準備邏輯卷中的步驟並按需調整。
對於UEFI啟動的系統,將EFI 系統分區掛載到/efi,以與接下來的grub-install指令相匹配。
# mount --mkdir /dev/sda2 /mnt/efi
現在,在/mnt下應掛載有如下分區與邏輯卷:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 200G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 550M 0 part /mnt/efi
└─sda3 8:3 0 100G 0 part
└─cryptlvm 254:0 0 100G 0 crypt
├─MyVolGroup-swap 254:1 0 4G 0 lvm [SWAP]
├─MyVolGroup-root 254:2 0 32G 0 lvm /mnt
└─MyVolGroup-home 254:3 0 60G 0 lvm /mnt/home
繼續執行安裝指南#開始安裝系統及之後的步驟。請使用本文中的對應內容替換安裝指南的Initramfs、安裝引導加載程序步驟。
若使用基於busybox的initramfs,在mkinitcpio.conf中添加keyboard、encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,添加keymap鉤子;若要自定義控制台字體,添加consolefont鉤子。
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block encrypt lvm2 filesystems fsck)
若使用基於systemd的initramfs,在mkinitcpio.conf中添加keyboard、sd-encrypt、lvm2鉤子。此外,若要使用非標準鍵盤布局,或要自定義控制台字體,添加sd-vconsole鉤子。
HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt lvm2 filesystems fsck)
保存上述修改後,重新生成initramfs。其它可能需要用到的鉤子以及配置細節參見Dm-crypt/系統配置#mkinitcpio。
配置GRUB以從LUKS加密的/boot啟動:
/etc/default/grub
GRUB_ENABLE_CRYPTODISK=y
設置內核參數以便initramfs解密加密的根分區。
若使用encrypt鉤子:
/etc/default/grub
GRUB_CMDLINE_LINUX="... cryptdevice=UUID=device-UUID:cryptlvm ..."
若使用sd-encrypt鉤子:
/etc/default/grub
GRUB_CMDLINE_LINUX="... rd.luks.name=device-UUID=cryptlvm ..."
詳見Dm-crypt/系統配置#內核參數、GRUB#加密的/boot。device-UUID應為LUKS superblock的UUID(在本例中為/dev/sda3,該分區包含了含有根分區的LVM)。詳見塊設備持久化命名。
對於UEFI啟動的系統,安裝GRUB到掛載的EFI系統分區:
# grub-install --target=x86_64-efi --efi-directory=/efi --bootloader-id=GRUB --recheck
對於BIOS啟動的系統,安裝GRUB:
# grub-install --target=i386-pc --recheck /dev/sda
生成GRUB配置文件:
# grub-mkconfig -o /boot/grub/grub.cfg
若上述所有命令都成功執行,在下次重啟後GRUB應提示輸入密碼解鎖/dev/sda3。
儘管在上述操作後,GRUB會要求輸入密碼解密LUKS加密的分區,但密碼並不會傳遞到initramfs中。因此,需要在啟動時輸入兩次密碼:一次用於GRUB,一次用於initramfs。
可通過在initramfs中嵌入密鑰文件避免輸入兩次密碼。
首先,創建一個密鑰文件,將其添加到LUKS key中:
# dd bs=512 count=4 if=/dev/random iflag=fullblock | install -m 0600 /dev/stdin /etc/cryptsetup-keys.d/cryptlvm.key # cryptsetup -v luksAddKey /dev/sda3 /etc/cryptsetup-keys.d/cryptlvm.key
將密鑰文件添加到initramfs鏡像:
/etc/mkinitcpio.conf
FILES=(/etc/cryptsetup-keys.d/cryptlvm.key)
重新生成initramfs鏡像。
設置如下內核參數以通過密鑰文件解密LUKS分區。
若使用encrypt鉤子:
GRUB_CMDLINE_LINUX="... cryptkey=rootfs:/etc/cryptsetup-keys.d/cryptlvm.key"
若使用sd-encrypt鉤子,將默認使用/etc/cryptsetup-keys.d/name.key密鑰文件,因此無需手動設置內核參數。
若由於某些原因密鑰文件解密boot分區失敗,systemd會要求手動輸入密碼。輸入正確的密碼後,系統啟動將正常進行。
使用存儲在單獨USB設備上的密鑰文件可避免使用密碼(若密碼太複雜,則難以記憶;若太簡單,則容易被猜中)。從安全性角度考慮,在未使用時,存儲有密鑰文件的USB設備必須與需解密的設備分開保存。
首先,按照#避免需輸入兩次密碼中的步驟創建新的密鑰文件。不要復用initramfs中使用的密鑰文件,否則,若USB設備丟失或密鑰洩露,需要修改嵌入到initramfs中的密鑰文件。
將創建的密鑰文件複製到USB設備,並創建GRUB配置文件:
/boot/grub/grub-pre.cfg
set crypto_uuid=UUID-of-the-luks-volume set key_disk=UUID-of-the-volume-with-the-key cryptomount -u $crypto_uuid -k ($key_disk)/the-location-of-the-key-on-your-usb set root=UUID-of-the-unlocked-volume-as-in-grub.cfg set prefix=($root)/boot/grub insmod normal normal
創建並安裝GRUB鏡像(依文件系統設置而定,可能不需要在鏡像中包含某些模塊):
# grub-mkimage -p /boot/grub -O x86_64-efi -c /boot/grub/grub-pre.cfg -o /tmp/grubx64.efi part_gpt part_msdos cryptodisk luks gcry_rijndael gcry_sha512 lvm ext2 ntfs fat exfat # install -v /tmp/grubx64.efi /efi/EFI/GRUB/grubx64.efi
要將dm-crypt與ZFS一同使用,參見ZFS#Encryption in ZFS using dm-crypt。
此外,ZFS具有原生加密支持,可用於加密根分區(不包含引導加載程序和文件系統元數據)。詳見:
對於UEFI啟動的系統,在安裝後可通過安全啟動驗證引導加載程序。