CentOS7 : システム全体を暗号化したOSの自動起動(LVM on LUKS)その2
どれほど需要があるか不明ですが、boot パーティション以外のシステム全体を暗号化した CentOS7 をなんとか自動起動できないものかと試してみたので、公開します。
自動起動を有効にするためには、何らかの方法でブートローダーが暗号化を解除する鍵に常時あるいは起動時にアクセスできる必要があります。
通常は、起動の際にパスフレーズを入力して起動するのですが、これを常時アクセス可能な場所に保存するということです。
鍵の保存場所を USB などにしておけば、一応は意味があるかもしれませんね。
Step1: 環境の確認
テスト環境は、CentOS7(CentOS-7-x86_64-Minimal-1708)を 暗号化構成(LVM)でインストールしたものを使用しました。
暗号化構成でインストールする方法は、以下の私の記事を参考にしていただければ幸いです。
3.4.1 パーティションの設定(CentOS 7 と Windows とのデュアルブート環境の構築 )
その他、暗号化構成についてはこちらのページが詳しいです。
dm-crypt/システム全体の暗号化
ざっくりと各コマンドで環境を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
[root@localhost ~]# blkid /dev/sda1: UUID="126d77ef-3c48-47ab-852e-4f4d83779f35" TYPE="xfs" /dev/sda2: UUID="4433fc3d-be8c-486e-ad11-0a2ba5aaad95" TYPE="crypto_LUKS" /dev/mapper/luks-4433fc3d-be8c-486e-ad11-0a2ba5aaad95: UUID="NdMfo2-axLe-mTSB-VGpL-sEa1-e2d0-jwj1fj" TYPE="LVM2_member" /dev/mapper/centos-root: UUID="85956dc0-7fa5-4fc3-aee3-ca681a81948f" TYPE="xfs" /dev/mapper/centos-swap: UUID="2eba352e-11cb-488d-8f59-4bfbdefb5354" TYPE="swap" [root@localhost ~]# fdisk -l Disk /dev/sda: 32.2 GB, 32212254720 bytes, 62914560 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト Disk label type: dos ディスク識別子: 0x000a5d72 デバイス ブート 始点 終点 ブロック Id システム /dev/sda1 * 2048 2099199 1048576 83 Linux /dev/sda2 2099200 62914559 30407680 83 Linux Disk /dev/mapper/luks-4433fc3d-be8c-486e-ad11-0a2ba5aaad95: 31.1 GB, 31135367168 bytes, 60811264 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト Disk /dev/mapper/centos-root: 29.0 GB, 28982640640 bytes, 56606720 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト Disk /dev/mapper/centos-swap: 2147 MB, 2147483648 bytes, 4194304 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 4096 bytes I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト [root@localhost ~]# pvdisplay --- Physical volume --- PV Name /dev/mapper/luks-4433fc3d-be8c-486e-ad11-0a2ba5aaad95 VG Name centos PV Size <29.00 GiB / not usable 0 Allocatable yes PE Size 4.00 MiB Total PE 7423 Free PE 1 Allocated PE 7422 PV UUID NdMfo2-axLe-mTSB-VGpL-sEa1-e2d0-jwj1fj [root@localhost ~]# lvdisplay --- Logical volume --- LV Path /dev/centos/root LV Name root VG Name centos LV UUID FikBeB-VnhO-0EFw-9oNn-4LDF-qFon-tVuG2L LV Write Access read/write LV Creation host, time localhost, 2018-04-03 22:21:11 +0900 LV Status available # open 1 LV Size 26.99 GiB Current LE 6910 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:1 --- Logical volume --- LV Path /dev/centos/swap LV Name swap VG Name centos LV UUID JLmE2E-qhKY-EZb4-HqHq-M11s-rU6s-AfMw2C LV Write Access read/write LV Creation host, time localhost, 2018-04-03 22:21:12 +0900 LV Status available # open 2 LV Size 2.00 GiB Current LE 512 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:2 [root@localhost ~]# cryptsetup luksDump /dev/sda1 Device /dev/sda1 is not a valid LUKS device. [root@localhost ~]# cryptsetup luksDump /dev/sda2 LUKS header information for /dev/sda2 Version: 1 Cipher name: aes Cipher mode: xts-plain64 Hash spec: sha256 Payload offset: 4096 MK bits: 512 MK digest: 5c 15 0b 51 c5 c0 34 7c 46 cd 9c 88 22 e3 55 c7 14 3f 14 0e MK salt: 5f b0 d8 e6 1a 1a 2e b0 82 f9 c9 ee c4 2e 6e a5 c5 d8 f5 2f fd a5 e9 aa 1e 69 66 64 76 c3 cc a6 MK iterations: 15750 UUID: 4433fc3d-be8c-486e-ad11-0a2ba5aaad95 Key Slot 0: ENABLED Iterations: 124755 Salt: 55 b5 53 8d e8 8f b0 ac 5c 15 c0 da 1b 33 bd 0a 80 d5 75 89 6a d5 af 1f f4 df d0 c6 d0 c1 c8 07 Key material offset: 8 AF stripes: 4000 Key Slot 1: DISABLED Key Slot 2: DISABLED Key Slot 3: DISABLED Key Slot 4: DISABLED Key Slot 5: DISABLED Key Slot 6: DISABLED Key Slot 7: DISABLED [root@localhost ~]# cat /etc/default/grub GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.luks.uuid=luks-4433fc3d-be8c-486e-ad11-0a2ba5aaad95 rd.lvm.lv=centos/swap rhgb quiet" GRUB_DISABLE_RECOVERY="true" |
Step2: 鍵の作成とキースロットの追加
さて、cryptsetup luksDump /dev/sda2 で確認したところ、キースロット0だけ使っている状態です。
これは、OS インストール時に作成したパスフレーズで、現在起動するために使った鍵です。
これを使って自動起動の設定もできますが、折角なので鍵の強度を上げたいと思います。4096バイトの鍵を作成します。
鍵の保存場所は、OS 起動時に暗号化されていない状態でアクセス可能な場所です。通常 /boot 以下は暗号化されていませんので、こちらに保存します。USB などを使うのであれば、そちらの方が良いでしょう。
1 2 3 4 5 6 7 |
[root@localhost ~]# touch /boot/keyfile [root@localhost ~]# chmod 400 /boot/keyfile [root@localhost ~]# dd if=/dev/urandom of=/boot/keyfile bs=1 count=4096 4096+0 レコード入力 4096+0 レコード出力 4096 バイト (4.1 kB) コピーされました、 0.014668 秒、 279 kB/秒 [root@localhost ~]# chattr +i /boot/keyfile |
続いて作成した鍵をキースロットに登録します。
1 2 3 4 5 |
[root@localhost ~]# cryptsetup -v luksAddKey /dev/sda2 /boot/keyfile Enter any existing passphrase:起動時に入力したパスワード Key slot 0 unlocked. Key slot 0 unlocked. Command successful. |
正しくキーが追加されたか確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
[root@localhost ~]# cryptsetup luksDump /dev/sda2 LUKS header information for /dev/sda2 Version: 1 Cipher name: aes Cipher mode: xts-plain64 Hash spec: sha256 Payload offset: 4096 MK bits: 512 MK digest: 5c 15 0b 51 c5 c0 34 7c 46 cd 9c 88 22 e3 55 c7 14 3f 14 0e MK salt: 5f b0 d8 e6 1a 1a 2e b0 82 f9 c9 ee c4 2e 6e a5 c5 d8 f5 2f fd a5 e9 aa 1e 69 66 64 76 c3 cc a6 MK iterations: 15750 UUID: 4433fc3d-be8c-486e-ad11-0a2ba5aaad95 Key Slot 0: ENABLED Iterations: 124755 Salt: 55 b5 53 8d e8 8f b0 ac 5c 15 c0 da 1b 33 bd 0a 80 d5 75 89 6a d5 af 1f f4 df d0 c6 d0 c1 c8 07 Key material offset: 8 AF stripes: 4000 Key Slot 1: ENABLED Iterations: 245208 Salt: b7 64 1a 48 94 0f 1a d1 7f ad ee 4d 09 31 74 10 f6 79 83 05 06 58 ff b1 ae 6f e1 d1 95 3f 54 7f Key material offset: 512 AF stripes: 4000 Key Slot 2: DISABLED Key Slot 3: DISABLED Key Slot 4: DISABLED Key Slot 5: DISABLED Key Slot 6: DISABLED Key Slot 7: DISABLED |
キースロット1に鍵が追加されています。
Step3: GRUB2 の設定
追加した鍵をブートローダーが認識できるように、場所を指定します。
指定するときのパラメータの書式は、以下の通りです。
1 |
rd.luks.key=<Keyファイルのパス>:UUID=<Keyファイルの保存されたデバイスのUUID>:UUID=<Keyファイルで暗号化を解除しようとするデバイスのUUID> |
このうち、暗号化解除の対象を示すパラメータは、以下の通り省略しても大丈夫です。
1 |
rd.luks.key=<Keyファイルのパス>:UUID=<Keyファイルの保存されたデバイスのUUID> |
ということで、私が追加すべきパラメータは、以下の通りです。
1 |
rd.luks.key=/keyfile:UUID=126d77ef-3c48-47ab-852e-4f4d83779f35 |
/boot は、OS がマウントするポイントですので取り除きます。
/etc/default/grub の GRUB_CMDLINE_LINUX= のところにパラメータを追加します。
1 |
vi /etc/default/grub |
1 2 3 4 5 6 7 |
GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)" GRUB_DEFAULT=saved GRUB_DISABLE_SUBMENU=true GRUB_TERMINAL_OUTPUT="console" GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.luks.uuid=luks-4433fc3d-be8c-486e-ad11-0a2ba5aaad95 rd.luks.key=/keyfile:UUID=126d77ef-3c48-47ab-852e-4f4d83779f35 rd.lvm.lv=centos/swap rhgb quiet" GRUB_DISABLE_RECOVERY="true" |
ということで、以下のコマンドで設定します。
1 |
[root@localhost ~]# grubby --update-kernel=ALL --args="rd.luks.key=/keyfile:UUID=126d77ef-3c48-47ab-852e-4f4d83779f35" |
ちなみに、これを実行すると、/etc/default/grub の設定も更新されますが、/boot/grub2/grub.cfg は更新されないようなので、次項の grub2-mkconfig も実行します(意味なさげですが)。
GRUB2 設定を再生成します。
1 2 3 4 5 6 7 |
[root@localhost ~]# grub2-mkconfig > /boot/grub2/grub.cfg Generating grub configuration file ... Found linux image: /boot/vmlinuz-3.10.0-693.el7.x86_64 Found initrd image: /boot/initramfs-3.10.0-693.el7.x86_64.img Found linux image: /boot/vmlinuz-0-rescue-deac225c91764c6e8b7f859dee5092d4 Found initrd image: /boot/initramfs-0-rescue-deac225c91764c6e8b7f859dee5092d4.img done |
Step4: initrd の編集と作成
Dracut を使って、initrd を編集します。
追加するパラメータを /etc/dracut.conf.d/luks_key.conf に新規作成します。
1 |
echo 'omit_dracutmodules+=" systemd "' > /etc/dracut.conf.d/luks_key.conf |
ついでに、LVM のスナップショット機能も使うのであれば、以下のパラメータも追加します。
1 |
echo 'add_drivers+=" dm-snapshot "' >> /etc/dracut.conf.d/luks_key.conf |
initrd を 再作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
[root@localhost ~]# dracut -fv Executing: /usr/sbin/dracut -fv dracut module 'modsign' will not be installed, because command 'keyctl' could not be found! dracut module 'busybox' will not be installed, because command 'busybox' could not be found! dracut module 'dmraid' will not be installed, because command 'dmraid' could not be found! dracut module 'mdraid' will not be installed, because command 'mdadm' could not be found! dracut module 'multipath' will not be installed, because command 'multipath' could not be found! dracut module 'cifs' will not be installed, because command 'mount.cifs' could not be found! dracut module 'iscsi' will not be installed, because command 'iscsistart' could not be found! dracut module 'iscsi' will not be installed, because command 'iscsi-iname' could not be found! 95nfs: Could not find any command of 'rpcbind portmap'! dracut module 'systemd' will not be installed, because it's in the list to be omitted! dracut module 'modsign' will not be installed, because command 'keyctl' could not be found! dracut module 'busybox' will not be installed, because command 'busybox' could not be found! dracut module 'dmraid' will not be installed, because command 'dmraid' could not be found! dracut module 'mdraid' will not be installed, because command 'mdadm' could not be found! dracut module 'multipath' will not be installed, because command 'multipath' could not be found! dracut module 'cifs' will not be installed, because command 'mount.cifs' could not be found! dracut module 'iscsi' will not be installed, because command 'iscsistart' could not be found! dracut module 'iscsi' will not be installed, because command 'iscsi-iname' could not be found! 95nfs: Could not find any command of 'rpcbind portmap'! *** Including module: bash *** *** Including module: nss-softokn *** *** Including module: i18n *** *** Including module: network *** *** Including module: ifcfg *** *** Including module: drm *** *** Including module: plymouth *** *** Including module: crypt *** *** Including module: dm *** Skipping udev rule: 64-device-mapper.rules Skipping udev rule: 60-persistent-storage-dm.rules Skipping udev rule: 55-dm.rules *** Including module: kernel-modules *** *** Including module: lvm *** Skipping udev rule: 64-device-mapper.rules Skipping udev rule: 56-lvm.rules Skipping udev rule: 60-persistent-storage-lvm.rules *** Including module: resume *** *** Including module: rootfs-block *** *** Including module: terminfo *** *** Including module: udev-rules *** Skipping udev rule: 40-redhat-cpu-hotplug.rules Skipping udev rule: 91-permissions.rules *** Including module: biosdevname *** *** Including module: usrmount *** *** Including module: base *** *** Including module: fs-lib *** *** Including module: shutdown *** *** Including modules done *** *** Installing kernel module dependencies and firmware *** *** Installing kernel module dependencies and firmware done *** *** Resolving executable dependencies *** *** Resolving executable dependencies done*** *** Hardlinking files *** *** Hardlinking files done *** *** Stripping files *** *** Stripping files done *** *** Generating early-microcode cpio image contents *** *** Constructing GenuineIntel.bin **** *** Store current command line parameters *** *** Creating image file *** *** Creating microcode section *** *** Created microcode section *** *** Creating image file done *** *** Creating initramfs image file '/boot/initramfs-3.10.0-693.el7.x86_64.img' done *** |
Step5: 再起動して確認
1 |
reboot |
無事起動すれば、環境構築完了です。
この状態で /boot/keyfile を削除すると、ちゃんとパスフレーズで起動できるようにフォールバックしてくれます。
でも、initrd をいじっているせいか入力画面が若干違います。
何らかのバージョン依存のバグのような気がしますが、とりあえず、そのようになったときの対処法です。
いずれかの方法で起動できると思います。
(1)起動カーネルの選択画面でレスキューモードを選択できる場合(推奨)
Red Hat Graphical Boot を無効にします。
1 2 |
sed -i 's/ rhgb//g' /etc/default/grub grub2-mkconfig > /boot/grub2/grub.cfg |
(2)とりあえず起動できればよい場合 その1
起動カーネルの選択画面で起動したいカーネルにカーソルを合わせて e を押す。起動オプションが表示されるので “rhgb” を削除して、 Ctrl + x を押す。
(3)とりあえず起動できればよい場合 その2
Red Hat Graphical Boot の画面(画面下の進捗バーが伸びていくヤツ)が表示されたら ESC を押してキャンセルする。
Step6: 環境の復元
とりあえず、自動起動できるようになったのは分かったが、元に戻したいときは、逆に手順を進めれば元に戻せます。
Dracut の設定削除と再作成。
1 2 |
rm -f /etc/dracut.conf.d/luks_key.conf dracut -f |
何気に dracut のオプションを変えてみましたが、特に意味はありません。
/etc/default/grub から 先ほど追加したパラメータを削除。してもしなくても動作は変わらないかもしれないけど。して GRUB2 設定を再生成。
1 2 |
sed -i 's/rd.luks.key=\/keyfile:UUID=126d77ef-3c48-47ab-852e-4f4d83779f35 //g' /etc/default/grub grub2-mkconfig > /boot/grub2/grub.cfg |
事故防止のためエディター開いてやったほうが良いです。
キースロットから鍵を削除します。
1 2 3 4 5 |
[root@localhost ~]# cryptsetup -v luksKillSlot /dev/sda2 1 Key slot 1 selected for deletion. Enter any remaining passphrase: Key slot 0 unlocked. Command successful. |
ちなみに、パスフレーズの方を消そうとすると、ちゃんとエラーがでて暴挙を止めてくれます。
1 2 3 4 5 |
[root@localhost ~]# cryptsetup -v luksKillSlot /dev/sda2 0 Key slot 0 selected for deletion. Enter any remaining passphrase: No key available with this passphrase. Command failed with code 1: 許可されていない操作です |
最後に、作成した鍵を消します。
1 2 |
chattr -i /boot/keyfile shred --remove /boot/keyfile |
再起動すると、見慣れたパスフレーズの入力画面が表示され、OS インストール時に設定したパスフレーズで OS 起動が可能です。