Closed13

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を使って暗号化解除する。

  1. clevis-dracutではなくclevs-initramfsを使う。
  2. mDNSを使わずIPアドレスを直打ちする。
  3. インストール作業の最後にupdateinitramfs -u -k 'all'を実行する

mDNSを使えないか、使えないならどうするか考えてみる。

堀江誠一堀江誠一

ここまでのまとめ

バインディングにホストアドレスを指定するか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"}' # ブートする
堀江誠一堀江誠一

結論。

いろいろ調べたが、「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の例。

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も要らない。

このスクラップは3ヶ月前にクローズされました