3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

(Linux)LUKSでファイルシステムを暗号化してみた

さくらのVPS 1G(CentOS6.3 x64) でsambaを使ってファイルサーバを立てようと思ったんですが、重要なデータも置くことがあるため、ファイルシステムレベルで暗号化をして見ることにしました。

さくらのVPSは標準OS(プレインストール)ではパーティションが既にきられているので、一旦カスタムOSで再インストールを行い、暗号化用のパーティションを作成しておきます。(今回使うdm-cryptはブロックデバイスに対して暗号化をかける仕組みなので、暗号化をかけるパーティションを用意する必要有り)

今回は以下の様なパーティションでインストールしました。

(fdisk後継の parted で確認した時のパーティション情報です。パーティションテーブルがGPTなもんで...)

# parted /dev/vda

(parted) print

Model: Virtio Block Device (virtblk)

Disk /dev/vda: 107GB

Sector size (logical/physical): 512B/512B

Partition Table: gpt

Number Start End Size File system Name Flags

1 1049kB 263MB 262MB ext4 Linux filesystem boot ←/boot

2 263MB 2411MB 2147MB linux-swap(v1) Linux swap

3 2411MB 45.4GB 42.9GB ext4  ← /

4 45.4GB 88.3GB 42.9GB ext4  ← /var

5 88.3GB 107GB 19.1GB ext4  ← 暗号化対象パーティション

Linuxの暗号化方式もいくつかあるようですが、今回はカーネルの2.6系列で統合されたdm-cryptを使った暗号化ファイルシステムの標準的な仕様であるLUKSを使うことにしました。

他の暗号化方式としてはループバックデバイス(実装:loop-AES),FUSE(実装:CryptoFS,EncFS)、eCryptfs(実装:eCryptfs)などがあるようです。

このあたりの話はファイルシステムごと暗号化する方法 - SourceForge.JP Magazine : オープンソースの話題満載が参考になります。

LUKSの操作をするには、cryptsetup コマンドを使います。

まず、以下の書式でパーティションを luks で暗号化します。

# cryptsetup luksFormat [-c 暗号化方式] [-s 鍵の長さ] 暗号化対象デバイスファイル

-c、-s指定しないと以下の初期値になります。

暗号化方式:aes-cbc-essiv:sha256

鍵の長さ:256

(128にしようとしたら、以下のエラーでて出来ませんでした。)

device-mapper: reload ioctl on failed: No such file or directory

Failed to setup dm-crypt key mapping for device /dev/vda5.

Check that kernel supports aes-cbc-essiv:sha128 cipher (check syslog for more info).

今回は、以下のようにしました。

# cryptsetup luksFormat -c aes-cbc-essiv:sha256 -s 256 /dev/vda5

WARNING!

========

This will overwrite data on /dev/vda5 irrevocably.

Are you sure? (Type uppercase yes): YES ←大文字で入力すること!

Enter LUKS passphrase: ←暗号化のパスワード入力

Verify passphrase: ←暗号化のパスワードを確認入力

暗号化が完了したら接続してみます。

LUKSパーティションへの接続は、以下のようにします。

# cryptsetup luksOpen デバイスバイスファイル名(適当な名前)

バイスファイル名はなんでも構いません。

今回と以下のような感じ。

# cryptsetup luksOpen /dev/vda5 luks

Enter passphrase for /dev/vda5: ←cryptsetup luksFormatに設定したパスワード入力

これで接続完了です。

/dev/mapper/デバイスファイル名 が作成されます。

今回だと、/dev/mapper/luks ですね。

そして、暗号化デバイス上にファイルシステムの作成します。

今回は ext4 にしました。

# mkfs -t ext4 /dev/mapper/luks

mke2fs 1.41.12 (17-May-2010)

Filesystem label=

OS type: Linux

Block size=4096 (log=2)

Fragment size=4096 (log=2)

Stride=0 blocks, Stripe width=0 blocks

1164592 inodes, 4654080 blocks

232704 blocks (5.00%) reserved for the super user

First data block=0

Maximum filesystem blocks=4294967296

143 block groups

32768 blocks per group, 32768 fragments per group

8144 inodes per group

Superblock backups stored on blocks:

32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,

4096000

Writing inode tables: done

Creating journal (32768 blocks): done

Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 34 mounts or

180 days, whichever comes first. Use tune2fs -c or -i to override.

ファイルシステム作成が終われば、マウントを行います。

# mount /dev/mapper/luks /mnt/secure/

これで使用可能になりました。

今回は初回なのでファイルシステムのフォーマットがありましたが、次から使うときは以下の様な流れになります。

# cryptsetup luksOpen /dev/vda5 luks ←接続

# mount /dev/mapper/luks /mnt/secure/ ←マウント

使い終われば以下のようにパーティションをアンマウントし、暗号化デバイスを削除する必要があります。

# umount /mnt/secure

# cryptsetup luksClose luks

これで、/dev/mapper/luks が削除されます。

OS起動時に自動マウントさせる

いちいち手動で接続、マウントしていると面倒なので、OS起動時に自動マウントさせるようにしました。

そのために、パスワードだけでなくキーファイルで認証できるようにします。(LUKSはキースロットが複数あるので、複数のパスワードやキーファイルが指定できます)

以下のようにキーファイルを作成します。乱数で、1024バイトのファイルを作成してます。

# dd if=/dev/urandom of=/boot/luks_key bs=1 count=1024

(キーファイルは /boot パーティションに配置しておきます。当初別パーティションに分けた /var 配下においてたんですが、自動マウントさせようとするとどうもうまく行かなかったので。。。)

安全のためキーファイルの権限を600か400にします。

# chmod 600 /boot/luks_key

LUKSパーティションにキーファイルの登録します。

# cryptsetup luksAddKey /dev/vda5 /boot/luks_key

Enter any passphrase: ←最初の設定したパスワード入力

以下コマンドでキーファイルが登録されたか確認します。

# cryptsetup luksDump /dev/vda5

LUKS header information for /dev/vda5

Version: 1

Cipher name: aes

Cipher mode: cbc-essiv:sha256

Hash spec: sha1

Payload offset: 4096

MK bits: 256

MK digest: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

MK salt: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

MK iterations: 23875

UUID: 5c7a088a-c452-4229-aeb3-c81d15e0e4b5

Key Slot 0: ENABLED ←ここが最初に指定したパスワード認証の設定

Iterations: 95873

Salt: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

Key material offset: 8

AF stripes: 4000

Key Slot 1: ENABLED ←●ENABLEDになっていればkeyfileが登録されている。

Iterations: 128900

Salt: xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx

Key material offset: 264

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

登録したキーファイルでマウントできることを確認します。

(すでにマウントされているなら、アンマウントし暗号化デバイスを削除しておきます)

# cryptsetup luksOpen /dev/vda5 luks --key-file /boot/luks_key

# mount /dev/mapper/luks /mnt/secure/

これでマウントできればキーファイルでの認証OKということになります。

いよいよ暗号化ボリュームを自動でマウントする方法です。

/etc/crypttab に設定を書くことでOS起動時にLUKSへの接続ができるようです。

書式は、以下のようになります。

[cryptsetupデバイス名] [/dev名] [キーファイルへのパス] [LUKS拡張が必要である旨]

今回は以下のようにしてみました。

# vi /etc/crypttab

luks /dev/vda5 /boot/luks_key luks,timeout=5

さて、次はファイルシステムのマウントです。

最初は/etc/fstabで以下のように書いてみました。

# vi /etc/fstab

/dev/mapper/luks /mnt/secure/ ext4 defaults 2 2

しかし、/etc/fstab使ってリブートすると以下のようにエラーになってしまいました。

Mounting local filesystems: mount: special device /dev/mapper/luks does not exist [FAILED]

Enabling local filesystem quotas: [ OK ]

modprobe: FATAL: Error inserting padlock_sha (/lib/modules/2.6.32-279.9.1.el6.x86_64/kernel/drivers/crypto/padlock-sha.ko): No such device

fstabの末尾の数字の設定によっては、起動時に他のパーティションも読み取り専用になってしまうこともあります。

(末尾の数字の意味については@IT:/etc/fstabに記述されている数字の意味を参照)

もしそうなったら "mount -o remount ,rw /" コマンドで書き込み可能でマウントしなおし、/etc/fstab を元に戻します。)

どうも /etc/fstab ではマウントできないようなので(多分、crypttabのマウントの前にfstabのマウントが走るため)、rc.local(システム起動時の最後に読み込まれる)でマウントするようにしました。

# vi /etc/rc.local

mount /dev/mapper/luks /mnt/secure/

リブートしてマウントできてるか確認してみます。

# mount

/dev/vda3 on / type ext4 (rw)

proc on /proc type proc (rw)

sysfs on /sys type sysfs (rw)

devpts on /dev/pts type devpts (rw,gid=5,mode=620)

tmpfs on /dev/shm type tmpfs (rw)

/dev/vda1 on /boot type ext4 (rw)

/dev/vda4 on /var type ext4 (rw)

none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

/dev/mapper/luks on /mnt/secure type ext4 (rw)

↑最下行見てみるとちゃんとマウントできてますね。

余談ですが、cryptsetup isLuksコマンドを使うと指定したパーティションがLUKSフォーマットかどうか確認できます。

# cryptsetup isLuks /dev/sdc

# echo $?

0 ←0が表示されればLUKSフォーマットです。

参考:

LUKS - GreenLeaf:

crypttab - GreenLeaf:

Markopee::Notebook: Linux で暗号化ファイルシステムを使う