ネットワークセキュリティだけでは足りない — 物理アクセスという脅威
以前、SSHへのブルートフォース攻撃を受けて、深夜に急対応したことがある。その後、ファイアウォール、fail2ban、SSHポートの変更など、できる対策はひと通り施した。しかし、あるシナリオだけはずっと見落としていた。誰かがサーバーのハードディスクを物理的に持ち去った場合、何が起きるのかという問題だ。
VPSならこのリスクは遠い話に聞こえるかもしれない。しかし、オフィスやコロケーション施設、自宅に設置したベアメタルサーバーでは、これは現実の脅威だ。rootパスワードをクラックする必要も、ファイアウォールを突破する必要もない。ディスクを取り外して別のマシンに接続し、マウントすれば、すべてのデータが丸見えになる。
これがLUKS(Linux Unified Key Setup)が生まれた理由だ。パーティション上のデータはブロックデバイス層でAES-256暗号化される — つまり、ロック解除されるまでOSでさえ何も知ることができない。パスフレーズかキーファイルがなければ、ハードディスクはランダムなバイト列でしかない — どのマシンに接続しても同じことだ。
cryptsetupのインストール
cryptsetupはLUKSを管理するパッケージだ。Ubuntuには通常プリインストールされている。他のディストリビューションは以下のコマンドで追加できる:
# Ubuntu / Debian
sudo apt update && sudo apt install cryptsetup -y
# CentOS / RHEL / Rocky Linux
sudo dnf install cryptsetup -y
# バージョン確認
cryptsetup --version
# cryptsetup 2.6.1
カーネルモジュールdm-cryptがロードされている必要がある。簡単に確認する方法:
lsmod | grep dm_crypt
# 空の場合は手動でロード:
sudo modprobe dm-crypt
LUKSの設定手順
ステップ1 — パーティションまたはディスクの準備
ここでは、暗号化が必要な追加ディスク/dev/sdbまたはパーティション/dev/sdb1があるとする。lsblkでデバイスを正確に確認しておくこと — cryptsetup luksFormatコマンドは既存データを完全に削除し、取り消しはできない。
lsblk
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 50G 0 disk
# └─sda1 8:1 0 50G 0 part /
# sdb 8:16 0 20G 0 disk ← 暗号化対象のディスク
ステップ2 — LUKSでパーティションをフォーマット
sudo cryptsetup luksFormat /dev/sdb
このコマンドはYES(大文字)での確認とパスフレーズの入力を求める。このパスフレーズは忘れると復元不可能 — 強力なパスフレーズ(20文字以上)を使い、すぐにパスワードマネージャーへ保存すること。
暗号化アルゴリズムを明示的に指定したい場合:
# AES-256とXTSモード — cryptsetup >= 2.x のデフォルト
sudo cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha256 \
/dev/sdb
ステップ3 — 暗号化ボリュームを開く
フォーマット完了後、LUKSはパーティションを暗号化したが、まだ使用できない。まず「ロック解除」が必要 — luksOpenは復号を行い、パーティションを/dev/mapper/<名前>の仮想ブロックデバイスにマッピングする:
# "data_encrypted"は任意の名前 — /dev/mapper/data_encrypted として表示される
sudo cryptsetup luksOpen /dev/sdb data_encrypted
# パスフレーズを入力...
# 確認
ls -la /dev/mapper/data_encrypted
# lrwxrwxrwx 1 root root 7 ... /dev/mapper/data_encrypted -> ../dm-0
ステップ4 — ファイルシステムのフォーマットとマウント
ここから、/dev/mapper/data_encryptedは通常のパーティションと同様に見えて動作する — ファイルシステムをフォーマットし、マウントして、普通に使える:
# ext4でフォーマット
sudo mkfs.ext4 /dev/mapper/data_encrypted
# マウントポイントを作成
sudo mkdir -p /mnt/secure_data
# マウント
sudo mount /dev/mapper/data_encrypted /mnt/secure_data
# 確認
df -h /mnt/secure_data
# /dev/mapper/data_encrypted 20G 45M 19G 1% /mnt/secure_data
ステップ5 — 起動時のauto-mount設定
ここは多くの人が省略するところだ。再起動後にLUKSボリュームを自動マウントするには、/etc/crypttabと/etc/fstabの2つのファイルを設定する必要がある。
まず、元のパーティション(device mapperではない)のUUIDを取得する:
sudo blkid /dev/sdb
# /dev/sdb: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="crypto_LUKS"
/etc/crypttabに追記する:
sudo nano /etc/crypttab
# <マッパー名> <デバイス> <キーファイル> <オプション>
data_encrypted UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 none luks
noneがキーファイルの列にある場合、起動時にコンソールでパスフレーズを求められる。キーファイルを使って自動化(手入力不要)したい場合:
# 4096バイトのランダムキーファイルを作成
sudo dd if=/dev/urandom of=/root/luks_keyfile bs=4096 count=1
sudo chmod 400 /root/luks_keyfile
# LUKSにキーファイルを追加(既存のパスフレーズをバックアップとして保持)
sudo cryptsetup luksAddKey /dev/sdb /root/luks_keyfile
# crypttabを更新
# data_encrypted UUID=... /root/luks_keyfile luks
その後、/etc/fstabに追記する:
sudo nano /etc/fstab
/dev/mapper/data_encrypted /mnt/secure_data ext4 defaults 0 2
確認と監視
LUKSのステータス確認
# ボリュームの詳細情報
sudo cryptsetup luksDump /dev/sdb
# LUKS header information
# Version: 2
# Epoch: 3
# Metadata area: 16384 [bytes]
# Keyslots area: 16744448 [bytes]
# UUID: a1b2c3d4-...
# Label: (no label)
# Subsystem: (no subsystem)
# Flags: (no flags)
# ...
# Keyslots:
# 0: luks2 ← パスフレーズ
# 1: luks2 ← キーファイル(追加した場合)
# デバイスマッパーのステータス
sudo cryptsetup status data_encrypted
# /dev/mapper/data_encrypted is active.
# type: LUKS2
# cipher: aes-xts-plain64
# keysize: 512 bits
# key location: keyring
# device: /dev/sdb
# ...
LUKSヘッダーのバックアップ — 必須の手順
LUKSヘッダーはパーティションの先頭にある — 暗号化メタデータ、キースロット、ソルトが格納されている場所だ。そのエリアのバッドセクターや、誤ってddを違うデバイスに実行してしまうだけで、すべて終わりだ。パスフレーズが正しくてもデータは永遠に失われる。セットアップ直後に必ずバックアップすること — 後回しにしてはいけない:
sudo cryptsetup luksHeaderBackup /dev/sdb \
--header-backup-file /root/luks_header_backup_sdb.img
# このファイルをサーバー外に保存(USB、S3、暗号化クラウドストレージなど)
# バックアップが有効か確認
sudo cryptsetup luksDump /root/luks_header_backup_sdb.img
使用しないときはボリュームを閉じる
# 先にアンマウント
sudo umount /mnt/secure_data
# LUKSを閉じる
sudo cryptsetup luksClose data_encrypted
# /dev/mapper/data_encrypted が消える
# ディスクが完全に暗号化された状態に戻る
パスフレーズの管理 — 追加、削除、変更
LUKSは最大8つのキースロットをサポートしている — つまり、複数のパスフレーズやキーファイルを同時に設定できる:
# 新しいパスフレーズを追加(例:チーム用のリカバリーパスフレーズ)
sudo cryptsetup luksAddKey /dev/sdb
# 古いパスフレーズを削除
sudo cryptsetup luksRemoveKey /dev/sdb
# 使用中のキースロットを確認
sudo cryptsetup luksDump /dev/sdb | grep -E "Keyslots|[0-9]+:"
実践で覚えておきたいポイント
- パフォーマンスオーバーヘッド:AES-NI(ハードウェアアクセラレーション)は2010年以降のほとんどのCPUに搭載されている。
grep aes /proc/cpuinfoで確認できる。搭載されていれば、暗号化のオーバーヘッドはほぼ無視できる — 実際のベンチマークでは、非暗号化と比べてスループットの差は3%未満であることが多い。 - LUKS1 vs LUKS2:LUKS2(cryptsetup 2.x以降のデフォルト)を使うこと — Argon2鍵導出をサポートし、LUKS1よりもブルートフォースへの耐性が高い。
- スワップパーティション:RAMのダンプがスワップにプレーンテキストで書き出される。具体的な例:使用中のSSH秘密鍵がメモリ上にあり、
/dev/sda3にスワップアウトされた場合、ディスクを持っている人は即座に読み取れてしまう。このシナリオを避けるにはzramを使うか、スワップを個別に暗号化すること。 - フルディスク暗号化 vs パーティション暗号化:この記事ではデータパーティション(data partition)の暗号化を解説している。ディスク全体(
/含む)の暗号化はより複雑で、通常はOSの新規インストール時に行う。
あのSSH対応で深夜に走り回った夜から、セキュリティを後回しにすることはなくなった。LUKSは、重要なデータを保存する新しいサーバーをデプロイする際に必ず設定するものの一つになった。15分のセットアップで、ハードディスクが他人の手に渡るシナリオを考えたとき、完全に安心できる。

