さくらの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
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 /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フォーマットです。
参考: