2008-09-11

geliで遊ぶための自分用メモ

FreeBSDでは、ezjail-adminを使えば、-c eli とすることで、簡単にgeliで暗号化したjailを作ることができるが、jailの数が増えるとどうも管理が面倒になった。キーファイルを使えばjailの数だけいちいちパスフレーズを打つこともなさそうだが、マウントポイントが多いし、なにかオーバーヘッドが大きそうな気もする。不意にクラッシュした後にそれぞれfsckするのもめんどくさい。なので、ディスクまるごとgeliで暗号化して、jailはその上に置くことにしたい。

それに、「失われた友人の400GBに捧ぐ - 暗号化GELI(8)メタデータ保存機能追加」(gihyo.jp)とか恐ろしげな記事があるし、もうちょっと geli を自在に扱えるようになっておきたい。

というわけで、geli で遊ぶための知識をいくつか。

geliでは、物理的なデバイスの最後の512バイトにメタデータを置いている。メタデータの中身はおよそ次のとおり。

  • マジックナンバー'GEOM::ELI'
  • 暗号方式
  • パーティションサイズ、セクタサイズ
  • 64バイトのソルト
  • 192バイトのマスターキー×2個(0番と1番)
  • MD5ハッシュ
ちゃんと調べてはいないが、パスフレーズと64バイトの乱数キーファイルとマスターキーの一方とソルトとセクタ番号を組み合わせると、セクタ暗号化の鍵が得られるっぽい。0番でも1番でも同じ鍵が得られるようにマスターキーを生成するのだろう。

geli コマンドはほとんどメタデータにのみ作用する。サブコマンドの主なものは次のとおり。
  • geli init: メタデータの新規作成。ソルトの生成(以降変化しない)。パスフレーズ、キーファイル、ソルトにより0番のマスターキーを生成。
  • geli dump: メタデータの表示。
  • geli backup: メタデータのファイルへの保存。
  • geli restore: 保存したメタデータの復元。
  • geli setkey: 指定した番号のマスターキーの変更。パスフレーズ、キーファイル、ソルトにより生成される。
  • geli delkey: 指定した番号のマスターキーの破壊。
  • geli kill: メタデータの破壊。乱数で上書き。
  • geli clear: メタデータの破壊。ゼロで上書き。
setkey, delkey, kill, clearで破壊しても、backupがとってあれば、restoreすることにより完全に元に戻せる。geli(8) にあるように、管理者用のメタデータを別の場所に保存してから、ユーザのマスターキーで上書きしてしまうという管理シナリオもありうる。

上のgihyo.jpの記事は、init時に自動的にメタデータを保存するようになったというもの。backupを用いて手動で保存すれば同じ(はず)。

オプションで geli init -a aalgo を用いると、データ完全性検証をするので、セクタごとにハッシュ分の領域が食われる。少なくともinitは相当遅そう。attachも?通常使用のパフォーマンスはどうなんだろう。そもそも、誰かがattach前にデータを壊したことを知りたいという用途はかなり少ないかも。

2008-09-04

FreeBSDのjail内でdhcpdを動かす

今のところFreeBSD-7.0のjailではbpfが動かないが、net/isc-dhcp3-serverにはDHCP_SOCKETSオプションがあり、bpfを使わずに動作するバイナリがビルドできる。しかし、これをjail内で動かすだけで、dhcpサーバとして働くかというと、そうもいかなかった。

まず、jail内ではbroadcastパケットを受信できないようで、dhcpリクエストの中継サーバが外に必要らしい。jail(8), jail(2), ハンドブックを探したが、broadcast受信の制約は見かけなかった気がする。jailの制約はときどき変わったりするので、どこかにまとめてあればいいんだけど。

そこで次に、net/isc-dhcp3-relayをホスト側で動かしてみた。そうすると確かに、dhcpdのログにはリクエストの到着とレスポンス内容が記録されるが、そのレスポンスパケットが外に出ていっていない。jail内のdhcpdからlo0経由でホスト側に来たパケットをdhcrelayが見ていない感じである。dhcrelayに -i lo0 を指定するとエラーになるので、無理やりIFF_LOOPBACKをスキップしないようコードを修正してみたが、それもうまくいかなかった。

というわけで、dhcrelayを完全に別のホストに設置してみたところ、あっさりと双方向に中継されて、dhcpクライアントが動くようになった。つまり、同じホスト内でパケットを中継するということをdhcrelayが想定していないせいなので、うまくいじれば直せる問題だと思う。

とすると、他の実装では動く可能性があるということなので、試しに、net/dhcprelay と net/dhcprelya をホスト側で動かしてみたら、どちらも、*_ifaces に lo0 を追加指定するだけで、問題なく中継できてしまった。そこで最終的に、これらのうち、高負荷ルータ用と銘打っている dhcprelya を採用。

ちなみに、dhcpdには、ホスト側で起動してbpfを掴んだのちに、chrootやjailに入るというオプションもあるようだが、美しさというか整合性の都合で採用を見送った。

中継サーバがいらなくなるであろう、vimageの正式採用にとても期待。

追記(9/11)

dhcprelyaを動かしていたら、数秒に1回
wrong ether type -- packet ignore
と出ていた。わずらわしいだけだが、dhcprelayだと出ないようなので、こちらに採用変更。