This site is an archive of ama.ne.jp.

つよいパソコンを作る

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

今回やったこと

  • /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カードにキーファイルを作成して、起動時に自動で暗号化を解除できるようにします。

キーファイルの作成

まず、

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

とか

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

でキーファイルを作ります。別にランダムデータである必要はありませんが、Standard-lock-key.jpgとか、誰にでも手に入れられるようなファイルはやめておきましょうね。

キーファイルの登録

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

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

起動スクリプトの作成

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

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

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

起動時設定

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

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に以下の追記が必要かもしれません。

vfat
nls_cp437
nls_ascii

initramfsの更新

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

update-initramfs -u

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

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

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

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

使い方

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

故障かな?と思ったら

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

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

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

update-initramfs -ut

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

終わりに

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