chroot環境への移行

named が乗っ取られた場合の用心に、named を chroot 環境 (chroot jail [牢獄] とも呼ばれる) で動かす。 named から見ると、chroot 先のディレクトリがルートディレクトリ "/" に見え、それより上の階層にアクセスすることはできなくなる。 BIND は chroot の仕組みを自前で備えており、 named の起動時に "-t chroot-dir " を指定すれば、自分で自分を牢屋に入れる。持ち物は、一部を除いてこちらであらかじめ牢屋の中に移し、生活に必要な環境を整えてやらなければならない。とはいえ、 chroot メカニズムを内蔵していないプログラムを jail するよりはずっと単純だ。

※ Fedora Core 3 付属の named の man を読むと 「BIND を安全に動かしたいなら chroot はもう古い。 chroot はやめて SELinux 下で動かせ」 との旨。 BIND を SELinux で保護した場合、標準の規制状態はかなり厳しくなっているらしく、幾つかの制限が発生するとのこと。ただ、本稿のような単独のキャッシュサーバなら通常のように `fixfiles relabel' でファイルのセキュリティコンテキストを更新するだけで一応は行けそうだ。

chroot ディレクトリは /named などを作る手もあるが、ここでは /var/named を chroot ディレクトリとする。 chroot しない通常の設定とは異なり、 /var/named/var/ ディレクトリは named 専用となるので、さらにその下に named ディレクトリを作らなくてもログや PID の書き出しに問題はないのだが、設定ファイルの違いを最小限に抑えるために、元のディレクトリ構造を踏襲することにする。

※ Fedora Core 3 では、BIND の chroot ディレクトリ構造を作成するためだけに bind-chroot というパッケージが存在する。 bind-chroot パッケージをインストールすると chroot ディレクトリは /var/named/chroot となり、基本的な必要ディレクトリがその下に自動的に作られ、各種設定ファイルも勝手にコピーされるようだ。

ファイル構成

/var/named に chroot すると仮定する。

/var/named/                        named.named 700  chroot時のルート
          etc/                     named.named 700 
              named.conf           named.named 600  内容変更無し 
              named.key            named.named 600  内容変更無し 
              localtime            named.named 644  タイムゾーン定義 
          var/                     named.named 700 
              named/               named.named 700 
              named.ca             named.named 600  内容変更無し 
              localhost.zone       named.named 600  内容変更無し  
              localhost.rev        named.named 600  内容変更無し  
              hoge.rev             named.named 600  内容変更無し 
              log/                 named.named 700 
                  named/           named.named 700 
                       named_custom.log  named.named 644  touchするかコピー  
                       named.log   named.named 644  syslog.conf を的確に設定すれば勝手にできる  
              run/                 named.named 700 
                  named/           named.named 700 
                       named.pid   named.named 644  勝手にできる 
          dev/                     named.named 700 
              null                 root.root   666  キャラクタデバイス 
              random               root.root   666  キャラクタデバイス 
              log                  root.root   666  syslogへのソケット 
/etc/
    rndc.conf                      root.root   600  移動せず 
    rndc.key                       root.root   600  移動せず 
    sysconfig/named                root.root   644  小変更 
    sysconfig/syslog               root.root   644  小変更

named を一旦ストップし、必要なディレクトリを整備して、「内容変更無し」のファイルを移動。その他のファイルは以下に説明。

デバイスファイルの作成

null と random

chroot 環境に移行すると、/dev/ にあるデバイスファイルにもアクセスできなくなるので、mknod コマンドで獄中に新たに作ってやる。必要なのは nullrandom
null の作成行程を挙げておく:

root# file /dev/null                          # もともとの null のファイルタイプを調べる
/dev/null: character special (1/3)            # キャラクターのメジャー1/マイナー3 と分かる
root# mknod -m 666 /var/named/dev/null c 1 3  # 上の結果を踏まえてデバイス作成

こうすればメジャーナンバー/マイナーナンバーを暗記しておく必要もなく確実。 random も同様に作る。

localtime

本当のところ、デバイスファイルなんかではないのだが段落構成上ここで...。 localtime はタイムゾーンを記述したバイナリファイルで、named が日付時刻関数を使用した場合に正しい出力を得るのに必要。単純にコピーしてくるだけ:

root# cp /etc/localtime /var/named/etc
root# chown named.named /var/named/etc/localtime

named の起動をchroot化

本来なら起動スクリプトを編集して "-t /var/named" を追記するところだが、 RedHat系では /etc/sysconfig/named を1箇所いじるだけで終わり。下記の部分。

ROOTDIR="/var/named"

-t さえ要らない。 /etc/init.d/named スクリプトは、ここから $ROOTDIR を変数として読み取り、PID ファイルの書き出し場所や named.conf の検索パスも自動的に /var/named を基準とした場所にシフトしてくれる。

syslog のための手当て

chroot すると syslogd との通信路も絶たれてしまうので処置が必要だ。 syslogd には chroot を見越した仕組みが用意されており、 syslogd を "-a sock_path " (Solaris では -p らしい)オプション付きで起動すれば、追加のソケットを開くようになる。 named の起動オプションと同じように、RedHat系では /etc/sysconfig/syslog を編集するだけ。

SYSLOGD_OPTIONS="....

の記述に、

-a /var/named/dev/log

を加える。既に -a が他で使われていたら `-a sock -a sock ...' のように指定。標準的な Linux カーネルでは 19 個まで OK らしい。あとは "service syslog restart" するかマシンを再起動すれば、 /var/named/dev/log ソケットができているはず。

これにてchroot jail 完了。