Tang-Clevis 自習
このスクラップの内容は整理して『Linuxの暗号化解除をコンソール以外で行うためにClevis-TangとDropbaerを使うGitHubで開く』に公開しました。
スクラップは閉じます。
Tangサーバーによって認証されたClientにより、Ubuntu Serverのrootディスクの暗号を解除する勉強。
Clevisとはボルトやピンを使うU字型の連結器のこと。Tangはそのボルトが貫通される被連結器の部分。
ソフトウェアとしてのClevisは、Tangサーバーにより認証を受けて自サーバーの暗号化を解除する。これによってサーバー起動時の暗号化解除をTangサーバーに一元化できる。また、Clevis側、Tang側だけを盗んでも意味のある情報を取得できない。さらに、Tangサーバーの起動パスワードを人間が投入することで、盗んでもサーバー群を起動できないように設定できる。
Ubuntu Serverはインストール時にディスクを暗号化するよう指定できる。この暗号化解除はオペレータが都度行うが、これをClevisで自動化する実験である。
実験にあたってはネットワーク・バインド・ディスク暗号化の有効化を参照した。
実験には2台のVMを使った
- tang-server : Ubuntu 24.04 Server
- clevis-client : Ubuntu 24.04 Server
いずれもディスク暗号化してある。また、avahi-daemonによりmDNSを有効化してある。
インストール
Tangサーバーをインストールし、サービスを有効化する。
sudo apt install -y tang
sudo systemctl enable tangd.socket
ファイアーウォール
ファイアーウォールを有効化し、許可されているポートを見る。
sudo ufw enable
sudo ufw status verbose
初期状態は以下の通り
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
80番のポートを開き、結果を見る。
sudo ufw allow 80
結果は以下の通り
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
80 ALLOW IN Anywhere
80 (v6) ALLOW IN Anywhere (v6)
同じく22番のポートも開く。
Tangサーバーの状態確認
sudo systemctl status tangd.socket
結果
● tangd.socket - Tang Server socket
Loaded: loaded (/usr/lib/systemd/system/tangd.socket; enabled; preset: enabled)
Active: active (listening) since Mon 2025-01-20 00:19:41 UTC; 3min 9s ago
Docs: man:tang(8)
Listen: [::]:80 (Stream)
Accepted: 0; Connected: 0;
Tasks: 0 (limit: 2218)
Memory: 8.0K (peak: 1.5M)
CPU: 9ms
CGroup: /system.slice/tangd.socket
Jan 20 00:19:41 tang-server systemd[1]: Starting tangd.socket - Tang Server socket...
Jan 20 00:19:41 tang-server systemd[1]: Listening on tangd.socket - Tang Server socket.
## Tangキーの確認
```sh
sudo tang-show-keys [ポート番号]
例えば
sudo tang-show-keys 80
これに対して以下の様な認証キーが与えられる。
TAftHUwZfIYokobfiZU7KN4BxGWEvyGOIwOBbOB2WIg
Clevisのインストール
クライアント側のサーバーにClevisをインストールする。
sudo apt install -y clevis clevis-luks clevis-dracut
- clevis-luks はLUKS暗号化パーティションを操作するために必要。
- clevis-dracutはinitramfsにClevisを組み込むために必要。
Clevis-Tangのテスト
ClevisがTangサーバーを使って暗号化・復号可能であることを確認しておく。まず、平文のテストファイルを作る。
echo "The quick brown fox" > unencrypted.txt
このファイルをTangサーバーによる認証キーを使って暗号化する。
clevis encrypt tang '{"url":"http://tang-server.local"}' < unencrypted.txt > secret.txt
すると、サーバーから取得したキーを使っても良いかという問い合わせがある。このキーは、先ほどtang-show-keyで見たキーである。yと答える。
The advertisement contains the following signing keys:
TAftHUwZfIYokobfiZU7KN4BxGWEvyGOIwOBbOB2WIg
Do you wish to trust these keys? [ynYN] y
暗号化されたsecret.txtが生成される。
最後に、Clevisがこれを解読できることを確認する。
clevis decrypt < secret.txt
secret.txtにはTangサーバーの情報がメタデータとして書き込まれている。その情報をもとにclevisはTangサーバーによる認証を行う。認証が通れば暗号を解除する。
initramfsのアップデート
Clevis-dructパッケージをインストールしたので、これをinitramfsに組み込む。ClevisがTangサーバーを見つけられるなら、initramfsはオペレータによる暗号解除と並行してClevisによる暗号解除を試みる。
sudo dracut -f
ClevisとLUKSのバインディング
ClevisとLUKSをバインドすることで、ネットワークによってLUKS暗号化ボリュームを復号できるようになる。これを行うためにClevisが作成した暗号キーをLUKSボリュームのキースロットに収める必要がある。
さらに、そのためにはLUKSボリュームがどこにあるかを突き止める必要がある。
LUKSボリュームの特定
lsblkコマンドを使う
lsblk
以下の場合、/dev/sda3がLUKSボリュームを格納している物理パーティションであり、これを復号する。
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 953M 0 part /boot/efi
├─sda2 8:2 0 1.8G 0 part /boot
└─sda3 8:3 0 17.3G 0 part
└─dm_crypt-0 252:0 0 17.3G 0 crypt
└─ubuntu--vg-ubuntu--lv 252:1 0 10G 0 lvm /
sr0 11:0 1 2.6G 0 rom
ボリュームを特定したら使用しているキースロットを見る。
sudo cryptsetup luksDump /dev/sda3
以下は、インストール直後のUbuntu Serverのキースロットである。キースロットは1つだけが登録されており、これはユーザーがタイプするLUKSボリューム復号化パスワード(Ubuntu Serverインストール時に登録したもの)である。また、トークンは無い。
LUKS header information
Version: 2
...
Keyslots:
0: luks2
Key: 512 bits
...
Tokens:
Digests:
...
バインディング
特定した暗号化ボリュームを含む物理パーティションとTangサーバー情報を使って、ClevisとLUKSをバインドする。
sudo clevis luks bind -d /dev/sda3 tang '{"url": "http://tang-server.local"}'
最初にLUKSボリューム復号化パスワード(Ubuntu Serverインストール時に指定したもの)を聞かれる。これはClevisが復号キーを登録するために必要である。次に、Tangサーバーの認証キーを確認して信頼して良いか聞かれる。
Enter existing LUKS password:
The advertisement contains the following signing keys:
TAftHUwZfIYokobfiZU7KN4BxGWEvyGOIwOBbOB2WIg
Do you wish to trust these keys? [ynYN] y
cryptsetupによるバインディング結果の確認
再度キースロットをダンプする。
sudo cryptsetup luksDump /dev/sda3
スロット数が1つ増え、Clevisのトークンが追加されていることがわかる。
LUKS header information
Version: 2
...
Keyslots:
0: luks2
Key: 512 bits
...
1: luks2
Key: 512 bits
...
Tokens:
0: clevis
Keyslot: 1
Digests:
...
Clavisによるバインディング結果の確認
sudo clevis luks list -d /dev/sda3
キースロット1にtang-server.localによる認証が必要なキーを収めていることがわかる。cryptsetupのダンプ結果と整合する。
1: tang '{"url":"http://tang-server.local"}'
と、これでリブートすれば動くはずだが動かない。dracutがタイムアウトし、メンテナンスモードに入る。ユーザーに暗号解除を求めることもしない。
次の2点が怪しい。
- dracut -f を実行した際にエラーがあった。
- mDNSを使ってよいのか不明
進展があった。以下の3点の変更でUbuntu ServerがClevisを使って暗号化解除する。
- clevis-dracutではなくclevs-initramfsを使う。
- mDNSを使わずIPアドレスを直打ちする。
- インストール作業の最後に
updateinitramfs -u -k 'all'
を実行する
mDNSを使えないか、使えないならどうするか考えてみる。
Clevsの公式リポジトリのREADME.mdには.localを使っている例がある。つまり、mDNSは使えるはずである。
network-based-unlockingのrd.neednet
が怪しい。
ここまでのまとめ
バインディングにホストアドレスを指定するかIPアドレスを指定するかで結果が変わる。
sudo clevis luks bind -d /dev/sda3 tang '{"url": "http://tang-server.local"}' # ブートしない
sudo clevis luks bind -d /dev/sda3 tang '{"url": "http://192.168.nnn.nnn"}' # ブートする
- ClevisリポジトリのREADME.mdには.localを使った例がある。
- mDNSではないが、Ubuntu 20.04で同様の問題がありパッチで解決したという報告がある。
- ただしこのパッチはv20で取り入れられている。そして、v20はUbuntu 24.04に取り入れられている。
結論。
いろいろ調べたが、「initramfsの中ではmDNSを解決できない」という結論に至った。日本語でも英語でも、これに関して「できる」とも「できない」とも言われていない。たぶん誰もやっていないのだろう。
「サーバー構築にmDNSなど使わない」と言われればそうかもしれない。
ClevisがIPアドレス直打ちでTangサーバーにアクセスするので、TangサーバーのIPアドレスを固定にしなければならない。
Ubuntu 24.04 Serverの場合はnetplanで指定する。50-cloud-init.yamlの内容を書き換えないこと。netplanはファイル名を若い順に読み込み、後のファイルが同じ項目を設定している場合、その値で若いファイル名による設定を上書きする。
いいかえると、99-*.yamlは50-cloud-init.yamlの設定に優先する。
以下はTangサーバーの/etc/netplan/99-fixed-ip-address.yamlの例。
network:
ethernets:
ens33: # NIC device name.
addresses:
- 192.168.222.100/24 # Tang Server IP Address
dhcp4: false # Disable DHCP
routes: # Gateway configuration
- to: default # Any address should go to this gateway.
via: 192.168.222.2 # Gateway server address
nameservers:
addresses: [xxx.xxx.xxx.xxx,8.8.8.8,8.8.4.4] # List of nameservers.
version: 2
ファイルを保存したらnetplanをアップデートする。
sudo netplan apply
Clevis-Tangを使う上でdracutは使わない。
また、update-initramfsも要らない。