title: つよいパソコンを作る
author: Amane Katagiri
summary: everything on (LVM on LUKS)
date: 2016-02-24T20:54:00+09:00
modified: 2017-03-29T18:10:00+09:00
category: tech
license: CC BY 4.0
rating: sfw
ai_summary: ThinkPad X250のDebian再インストールに伴い、LVM on LUKSによるディスク暗号化を設定した記録です。外部デバイス内のキーファイルを用いた自動暗号化解除と、キー紛失時のパスフレーズ入力によるフォールバックを両立させる構成を解説。crypttabの編集や、passdevを確実に動作させるためのinitramfsの更新手順など、具体的なスクリプト設定を交えて紹介しています。
ai_keywords: Debian, LUKS, LVM, ディスク暗号化, キーファイル, ThinkPad X250, initramfs, cryptsetup, 自動起動, パスフレーズ

年度末なのでローカル機(ThinkPad X250)のDebianを入れ直すついでに、ディスクを暗号化することにしました。

[TOC]

# 今回やったこと

* `/boot`を除くDebian領域をLVM on LUKSで管理するようにしました。
* 起動時に、キーファイルを用いて自動で暗号化を解除できるようにしました。
* 起動時にキーファイルが見つからない場合は、パスフレーズで暗号化を解除できるようにしました。

# 前提

LUKSディスクは構成済みであるとします。この記事の作業に関しては、LVM領域は必ずしも必要ではありません。

なお、既存のディスクは暗号化の際に内容が消失しますので、システム全体を暗号化するにあたってはいったん再インストールすることをおすすめします。

以下は今回事前に行った作業です。

1. `/home`を退避します。
2. aptitudeのログなど、再構成に必要な情報などを退避します。
3. Debianインストーラを用いてDebian8を再インストールします。
    1. パーティショニング機能を用いて`/boot`およびLUKSパーティションを作成します。この時、パスフレーズを設定しますが、毎日入力することは考えずに強力なパスフレーズにしましょう。
    2. LUKSパーティション上にLVM領域を作成し、必要な論理ボリュームを作成します。今回は`/`、`/var`、`/tmp`、`/home`とswapに分けました。
4. 退避したデータを用いてあの頃のDebianを取り戻します。

# 作業

このままでは起動時に毎回長々としたパスフレーズを入力しなければなりません。そこで、USBメモリやSDカードにキーファイルを作成して、起動時に自動で暗号化を解除できるようにします。

## キーファイルの作成

まず、

```bash
dd if=/dev/random of=/media/hoge/keyfile bs=1 count=1024
chmod 400 /media/hoge/keyfile
```

とか

```bash
cat /dev/random | head -c 1024 > /media/hoge/keyfile
chmod 400 /media/hoge/keyfile
```

でキーファイルを作ります。別にランダムデータである必要はありませんが、[Standard-lock-key.jpg](https://upload.wikimedia.org/wikipedia/commons/a/a2/Standard-lock-key.jpg)とか、誰にでも手に入れられるようなファイルはやめておきましょうね。

## キーファイルの登録

cryptsetupを用いて作成したキーファイルをキースロットに登録します。登録には今までに設定したキーの1つが必要です。

```bash
cryptsetup luksAddKey /dev/sdX /media/hoge/keyfile
```

## 起動スクリプトの作成

`/lib/cryptsetup/scripts/startup`に以下のようなスクリプトを作成します。既存の`askpass`や`passdev`のみを用いても良いですが、どうもフォールバックが効かないのでそれぞれを呼び出すスクリプトを書きました。

```bash
#!/bin/sh
/lib/cryptsetup/scripts/passdev $1
if [ $? = 1 ]; then
    /lib/cryptsetup/askpass "? "
fi
```

なお、実行権限を与えるのを忘れないでください。

## 起動時設定

`/etc/crypttab`を以下のように変更し、作成した起動スクリプトとデバイスを結びつけます。

```text
sdX_crypt UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /dev/sdY:/keyfile:3 luks,keyscript=/lib/cryptsetup/scripts/startup,discard,timeout=3
```

キーファイルを入れるデバイスがFATだと、マウント時に問題が起きることがあります。例えば、`/etc/initramfs-tools/modules`に以下の追記が必要かもしれません。

```bash
vfat
nls_cp437
nls_ascii
```

## initramfsの更新

ここまでの設定やスクリプトファイルは、暗号化されていない`/boot`上にあるinitramfsというディスクイメージに保持されます。このディスクイメージの更新は以下のコマンドで行うことができます。

```bash
update-initramfs -u
```

しかし、今のままではまだ意図した起動フローになりません。というのも、`/etc/crypttab`に指定されたスクリプトは自動的にinitramfsにコピーされますが、その中で呼び出される`passdev`はコピーされないのです。そこで、`/usr/share/initramfs-tools/hooks/cryptroot`に以下のコピーコマンドを追加します。

```text
copy_exec /lib/cryptsetup/scripts/passdev
```

ちょうど`copy_exec /lib/cryptsetup/askpass`の下あたりに追加すればいいです。

++(2016-05-19) さらに現在の設定では、LVMが暗号化が解除されていない状態でディスクを読もうとするため、エラーが出てしまいます。++

++そのため、以下のページを参考に起動スクリプトを書き変えました。++

++[UNABLE TO FIND LVM VOLUME... WITH LVM ON TOP OF LUKS](http://ixday.github.io/unable-to-find-lvm-volume-with-lvm-on-top-of-luks.html)++

++具体的には`/usr/share/initramfs-tools/scripts/local-top/cryptroot`の`prereqs`の内容を`echo "$PREREQ"`のみにします。++

++(2016-11-05) 最近、カーネルのアップデートの度に変更した各種スクリプトがリセットされているため、対策を考えています。++

# 使い方

initramfsを更新して再起動すれば、キーファイルを用いて自動で暗号化が解除されます。キーファイルが見つからない場合は、`?`が表示されパスフレーズの入力を促されます。

# 故障かな？と思ったら

設定を間違うと、パスフレーズの入力すらできないまま永遠に起動スクリプトを繰り返したりします。そんな時は、焦らずに適当なレスキューモードに入って`/etc/crypttab`を元に戻しましょう。

```text
sdX_crypt UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx none luks
```

レスキューモードの起動には再インストール時に用いたディスクをそのまま使えばいいです。作業後には、以下のコマンドでinitramfsを更新するのを忘れないでください。

```bash
update-initramfs -ut
```

これで、パスフレーズでのみ暗号化を解除できるようになるので、起動後に正しい設定に書き換えましょう。

# 終わりに

まぁ、外出時にキーデバイスをマシンと別々にして持ち歩けば、そこそこ安全なんじゃないでしょうかね。
