FreeBSD+GEOM/GELIでJail用パーティションを暗号化する

[FreeBSD Advent Calendar 2020](https://qiita.com/advent-calendar/2020/freebsd) 2日目は、GEOM/GELIによるストレージ暗号化機能を利用し、Jailコンテナ用のパーティションを暗号化する方法を紹介しようと思います。

## 背景

以下の記事でも紹介しているように、私は[さくらのVPS](https://vps.sakura.ad.jp/)にFreeBSD＋Jail環境を構築して利用しています。

 * [さくらVPSでFreeBSD＋Jailを動かして仮想的にVPSが複数使えているような環境を作ってみる](https://qiita.com/furandon_pig/items/b40db38ac2a2d795224d)

Jail使う分には昨日の記事で紹介した手順で充分なのですが、クラウド上に用意した生活環境などはストレージを暗号化しておきたいなという気持ちもあります(気にする人は気にするよね、レベルの話です...)。

 * [ちょっとした実験・作業環境をJailで構築する](https://qiita.com/furandon_pig/items/b40db38ac2a2d795224d)

FreeBSDには[geom(4)](https://www.freebsd.org/cgi/man.cgi?query=geom&sektion=4&apropos=0&manpath=FreeBSD+12.0-RELEA%3Cbr%3ESE+and+Ports)と[geli](https://www.freebsd.org/cgi/man.cgi?query=geli&apropos=0&sektion=0&manpath=FreeBSD+12.0-RELEASE+and+Ports&%3Cbr%3Earch=default&format=html)というディスク暗号化機能があり、これとJailを組み合わせることで、暗号化したストレージの上に生活環境を構築できそうです。

というわけで、今日の記事ではFreeBSD＋Jail＋GEOM/GELIを活用する方法を紹介してみます。

## GEOM/GELIによるストレージの暗号化

GEOM/GELIによるストレージの暗号化を行う場合、FreeBSDインストールの段階でルートパーティションと暗号化ストレージ用のパーティションを分けて作成しておきます。以降の例では `/jail` を暗号化ストレージ用のパーティションとして設定して行きます。

```
$ df -h
Filesystem       Size    Used   Avail Capacity  Mounted on
/dev/vtbd0s1a    2.9G    1.3G    1.4G    48%    /
devfs            1.0K    1.0K      0B   100%    /dev
/dev/vtbd0s1b     15G     32M     14G     0%    /jail
```

`/boot/loader.conf` に以下の設定を追加し、FreeBSD起動時にGEOM/GELI用のカーネルモジュールがロードされるようにしておきます。

```
geom_bde_load=YES
```

上記の設定は再起動しないと参照されないため、暗号化設定の投入作業時においては以下のように手動でカーネルモジュールをロードしておきましょう。

```sh
$ kldload geom_bde
$ kldstat
Id Refs Address                Size Name
 1   14 0xffffffff80200000  243cd00 kernel
 2    1 0xffffffff8263d000    12248 geom_bde.ko
```

FreeBSDインストール直後の `/jail` パーティションはフォーマットされた状態なので、いったん `unmount` します。

```sh
$ sudo umount /jail
```

また、 `/etc/fstab` のエントリもコメントアウトしておきます。

```sh
$ sudo vi /etc/fstab
```

```
# Device        Mountpoint      FStype  Options Dump    Pass#
/dev/vtbd0s1a   /               ufs     rw      1       1
#/dev/vtbd0s1b  /jail           ufs     rw      2       2
/dev/vtbd0s1d   none            swap    sw      0       0
```

### 暗号化パーティションの設定

パーティションを暗号化します。 `/jail` はデバイス `/dev/vtbd0s1b` として見えており、これに対してGEOM操作用コマンドである `gbde init` `gbde attach` を実行します。

`gbde init` を実行すると暗号化パーティションの設定ファイルが開きます。保存・終了時にパスフレーズの入力が求められ、ここで入力したパスフレーズを暗号化パーティションのアタッチ時に入力することになります。

```sh
$ # GBDE関連のファイルを置いておくディレクトリを作成。
$ sudo mkdir /etc/gbde
$
$ # "gbde init"で設定ファイルが開く。
$ # 保存時に新たにパスフレーズを聞かれるので設定する。
$ sudo gbde init /dev/vtbd0s1b -i -L /etc/gbde/vtbd0s1b.lock
```

`gbde attach` でアタッチすることで `/dev/vtbd0s1b.bde` のような形で暗号化パーティションが見えるようになります。

```sh
$ sudo gbde attach /dev/vtbd0s1b -l /etc/gbde/vtbd0s1b.lock
$
$ ls /dev/vtbd0s1*.bde
/dev/vtbd0s1b.bde
```

あとは通常のパーティションと同じく、 `newfs` を実行してフォーマットします。

```sh
$ sudo newfs -U /dev/vtbd0s1b.bde
/dev/vtbd0s1b.bde: 16256.8MB (33293824 sectors) block size 32768, fragment size 4096
        using 26 cylinder groups of 626.09MB, 20035 blks, 80256 inodes.
        with soft updates
super-block backups (for fsck_ffs -b #) at:
 192, 1282432, 2564672, 3846912, 5129152, 6411392, 7693632, 8975872, 10258112,
 11540352, 12822592, 14104832, 15387072, 16669312, 17951552, 19233792,
 20516032, 21798272, 23080512, 24362752, 25644992, 26927232, 28209472,
 29491712, 30773952, 32056192
```

これで暗号化パーティションの設定とフォーマットが完了しました。 `mount` コマンドでパーティションをマウントすればそのまま使用できます。

```sh
$ sudo mount /dev/vtbd0s1b.bde /jail
$ df -h
Filesystem           Size    Used   Avail Capacity  Mounted on
/dev/vtbd0s1a        2.9G    1.3G    1.4G    48%    /
devfs                1.0K    1.0K      0B   100%    /dev
/dev/vtbd0s1b.bde     15G    8.0K     14G     0%    /jail
```

これで必要な準備が完了しました。あとは [昨日の記事](https://qiita.com/furandon_pig/items/b40db38ac2a2d795224d)で紹介したJail環境を暗号化ストレージ上に構築することで安心(？)してFreeBSD環境を利用することができます。

### クラウド上のインスタンスでGEOM/GELIを利用する際のコツ

暗号化したパーティションは、 `/etc/rc.conf` に以下のような記述を追加しておくことで、OS起動時にマウントすることができますが、クラウド上のインスタンスではこの設定はおススメしません。

理由としては、起動時に `gbde attach` を実行した時と同じくパスフレーズの入力が求められるため、コンソールが取れないような環境では入力待ちのまま起動が止まってしまうためです。
(さくらVPSの場合はコンソールが取れるため問題ありませんが、それでも起動時にWebコンソールを開くのは少々手間な感じです...)

```
gbde_autoattach_all="YES"
gbde_devices="vtbd0s1b"
gbde_lockdir="/etc/gbde"
```

そのため、私の環境ではインスタンスが起動したのち、 `ssh` でログインしてから `gbde attach` と `mount` を実行する方法で運用しています。

## まとめ

GEOM/GELIを用いたFreeBSDでの暗号化ストレージ設定方法を紹介しました。今回はストレージ上にJail環境を構築する前提での話でしたが、USBメモリのような暗号化しておくと安心といったデバイスにも応用ができるかと思います。