メインシステムをEncFS on BtrfsからBtrfs on dm-cryptに変更
zsh
- TOP
- Old Archives
- メインシステムをEncFS on BtrfsからBtrfs on dm-cryptに変更
概要
散々やるよといっていた構成変更だが、ついに実行した。
作業はかなり面倒で、1時間半ほどかかってしまった。
今までは次のようになっていた。
- 4ディスクによるBtrfsを編成
- Btrfsはサブボリュームを持つ
- ひとつのサブボリュームを丸々EncFSとする
- .zshrcで
encfs
コマンドを呼び、マウントする
この方法のメリットは次のようなものだ
- 強力で柔軟な暗号化
- ファイル単位でのバックアップが、暗号化したまま可能
- 手軽
- rootでもユーザーデータにアクセスできないので、かなり安全
一方デメリットは次のようなもの
- rootでユーザーデータにアクセスできないとKVMが暗号化されたディスクにイメージを置けないなど結構不便
- 特にバックアップで困る
- ファイルアクセスは常にEncFSがトップ。どのプロセスがIO負荷になっているのかわからない
下準備
先日のrsoftmirrorとrsyncを使ってデータをすべてスレーブにバックアップ
dm-crypt
4kBのurandomデータをめちゃくちゃに暗号しまくって、その中から512Bを切り出す方法で鍵ファイルを作成。これを使う。
cryptsetup --hash=sha512 --key-size=512 --ciper="twofish-xts-plain" --offset=0 key-file=/etc/worldencmount/keyfile --type=plain open device name
単にopen。LUKSではluksFormat
という専用のアクションがあるが、プレーンだとない。
ちなみに、twofish-xts-plain
は結構遅い。
これをしただけだとBtrfsの存在はblkid
では残っているように見えてしまう。
そこでrebootするのだが、その前に/etc/fstab
を編集してbtrfsをマウントしないようにしておかないと痛い目を見る。
Btrfs
リブートしたら暗号化を行うのと同じ手順でデバイスをオープンする。 Btrfsはそのオープンしたデバイスに対して行う。
# mkfs.btrfs -m raid1 -d raid1 -l WorldBtrfs /dev/mapper/world_enc_*
ちなみに、ストライプで高速化するのではなく、ミラーで分散してもらうことにした。 ミラーするかどうかは悩んだのだが、やはり安全をとってミラー。つまり、2ミラー、1バックアップになる。
サブボリュームを作ることを忘れていて若干ハマった。
# mount /dev/mapper/world_enc_1 /mnt/1
# cd /mnt/1
# btrfs subvolume create shared-world
設定ファイルにblkidでdm-cryptのPARTUUIDを送り込んでおく。 また、btrfsのUUIDを/etc/fstabに送り込んでおく。
# blkid | grep -F /dev/mapper/world_enc_* | tail -n 1 >> /etc/fstab
そしてvim
# vim /etc/fstab
コピペしてUUIDを書き換え、ゴミを消去し、コメントアウトを外し、noauto
オプションを追加する。
修正
そういえばこの方法はdiskのパーティションを暗号化している。 これは推奨される方法だが、やはりできればwhole diskの暗号化をしたい。 LUKSも含め3TB以上のwhole diskの暗号化には対応している。
だが、そうするとかなり重大な問題が生じる。 PARTUUIDやPARTLABELが使えなくなるのだ。
これは結構困ったことで、どうしたものかと思ったが、/dev/disk/by-id
を使うことにした。
これはWWIDと呼ばれる、システムに依存しないデバイスに対して永続的なIDであるという。
若干手間だが、確実だ。
ちなみにこの修正、同期がかなり進んだ段階でリセットする形で行った。 この修正に30分くらいかかってしまった。
セットアップスクリプト
#!/usr/bin/zsh
#read config file.
. /etc/worldencmount/worldrc || exit 1
#decryption
for disk in "${disks[@]}"
do
cryptsetup --hash=sha512 --key-size=512 --cipher="twofish-xts-plain" --offset=0 --key-file=${keyfile:-/etc/worldencmount/seedfile} --type=plain open "$disk" dmcw_${disk:t}
done
.zshrc
#Check shared zshrc file.
if [[ -e $HOME/share/.zshrc ]]
then
# Enable shared zshrc
. $HOME/share/.zshrc
else
# Disabled shared zshrc.
print ~/share/.zshrc "is not exist." >&2
print "Probably encrypted filesystem don't mount yet." >&2
print "Let's mount it!" >&2
print >&2
## Decryption ##
if sudo btrfs filesystem show | grep -F -q HydrangeaMasterBtr
then
print "Btrfs filesystem already active." >&2
else
if sudo /usr/local/sbin/worldencmount
then
print "Okay, succeed to decrypt." >&2
else
print "Oh, failed to decrypt disks." >&2
print "Aborting..." >&2
exit 2
fi
fi
## Mount ##
if sudo mount ~/share
then
print "Okay, succeed to mount the filesystem." >&2
print "You can use the World." >&2
exit 0
else
print "Gosh! failed to mount. I don't know why." >&2
print "Please fix it." >&2
exit 3
fi
fi
いままでよりだいぶ複雑になった。 結局、自動マウントではなく.zshrcで処理するようにした。 このほうが合理的だ。
slave側の自動マウント
逆にslave側は常にマウントされているべきなので、systemdユニットを書く。
[Unit]
Description=Mount World filesystem.
After=network.service
[Service]
ExecStart=/usr/local/sbin/worldmount
[Install]
WantedBy=multi-user.target
そして自動起動
# systemctl enable worldmount
ものすごく手抜きで、実はまだテストしていないが、動くはずだ。 ちなみにCentOS7である。
同期
rsyncで新たに作られた~/share
に同期する。
これは復旧作業なので通常とは逆方向のsyncとなる。
結果的には約14時間かかった。gzipのためか時間はかかったが、容量は2.02TiBと約2/3に抑えられた。
鍵のバックアップ
鍵ファイルがなくなると困るのでバックアップ。 しかしそれだけでは暗号化している意味がないので、鍵ファイルも暗号化した上でCD-Rに焼く。 暗号化はopensslのencを使うのが手っ取り早く、確実。 復号化用のスクリプトも同梱した。
総論
今回の作業はそれなりにしんどかったが、それでも同期を別とすれば1時間半ほどで終了した。 (ただしそれは最初にしたようにパーティションベースで行った場合のみの話)
元々EncFSにしたのは暫定的な措置だったし、スレーブサーバー設置に伴ってこういった作業をすることは想定していた。