「はじめに」で述べたように、
BIND を root 権限で実行するのはあまり良い考えではありません。
従って、まず最初に BIND 専用のユーザを作りましょう。
この目的に、nobody
のような既存の一般向けユーザは、
決して使うべきではありません。
しかし、SuSE や Linux Mandrake など、
最初からこのためのユーザ (普通 named
という名前)
を用意しているディストリビューションもあるので、
その場合はお望みならこのユーザを用いても構いません。
さて、ユーザを追加するには、次のような行を
/etc/passwd
に加えます。
named:x:200:200:Nameserver:/chroot/named:/bin/false
そして次の行を /etc/group
に加えます。
named:x:200:
これで BIND 用の named
というユーザとグループができました。
UID と GID (この例では両方とも 200) が、
お使いのシステムで他と重なっていないように注意しましょう。
このユーザはログインする必要がないので、
シェルは /bin/false
にしてあります。
次に、chroot jail に使用するディレクトリ構造を作ってあげる必要があります。
ここが BIND の生活の場となるわけです。
これはファイルシステムのどこでも構いません。
非常に神経質な人は、独立したボリューム
(パーティション) に置きたいとさえ思うかもしれませんね。
ここでは /chroot/named
を使います。
まず以下のようなディレクトリ構造を作ってください。
/chroot
+-- named
+-- dev
+-- etc
| +-- namedb
| +-- slave
+-- var
+-- run
(Linux システムなどで) GNU の mkdir
を使っている人は、
次のようにすればこのディレクトリ構造が作れます。
# mkdir -p /chroot/named
# cd /chroot/named
# mkdir -p dev etc/namedb/slave var/run
既に通常のかたちで BIND がインストールできていて、
これを利用しているなら、
named.conf
ファイルとゾーンファイルがあるはずです。
これらのファイルは chroot jail の中に移動
(あるいは安全にやるならコピー) して、
BIND から見えるようにしてやる必要があります。
named.conf
は /chroot/named/etc
へ、
ゾーンファイルは /chroot/named/etc/namedb
へ移動します。
例えば:
# cp -p /etc/named.conf /chroot/named/etc/
# cp -a /var/named/* /chroot/named/etc/namedb/
BIND は通常 namedb
ディレクトリへの書きこみ権限を必要とします。
しかしセキュリティを厳しくするために、これは許さないことにしましょう。
お使いの DNS があるゾーンをスレーブでサービスする場合は、
BIND はそのゾーンファイルを更新できなければなりません。
すなわちこれらのファイルには別のディレクトリに保存させるようにして、
そこに BIND からの書き込みアクセスを許すかたちにします。
# chown -R named:named /chroot/named/etc/namedb/slave
ここで、スレーブゾーンは全部このディレクトリに移動するのを忘れないこと。
また、それに応じて named.conf
の変更も必要になります。
BIND は /var/run
ディレクトリへも書きこみ権限を必要とします。
pid ファイルと統計情報をここに作るからです。
次のコマンドでこれを可能にしてやりましょう。
# chown named:named /chroot/named/var/run
BIND が chroot jail 内部での実行を始めると、 jail 外部のファイルへは一切アクセスできなくなります。 しかし、いくつかの重要なファイルには実行後もアクセスできなければ なりません。ただし BIND 8 に比べるとだいぶ少ないですが。
BIND が jail の内部に必要とするファイルのひとつに、
いつものあれ、/dev/null
があります。
ここで、このデバイスノードを作るために必要なコマンドは
システムによって異なることがあります。
/dev/MAKEDEV
スクリプトを調べて確認してください。
システムによっては /dev/zero
が必要なこともあります。
BIND 9.2.0 リリース予定版では、
/dev/random
が必要だという報告もあります。
ほとんどの Linux システムでは、以下のコマンドが使えます。
# mknod /chroot/named/dev/null c 1 3
# mknod /chroot/named/dev/random c 1 8
# chmod 666 /chroot/named/dev/{null,random}
FreeBSD 4.3 では次のようになります。
# mknod /chroot/named/dev/null c 2 2
# mknod /chroot/named/dev/random c 2 3
# chmod 666 /chroot/named/dev/{null,random}
他にも jail 内部の /etc
ディレクトリに必要なファイルがあります。
BIND に正しい時刻でログ記録をさせるには、
/etc/localtime
(システムによっては
/usr/lib/zoneinfo/localtime
かもしれません)
をここにコピーする必要があります。
以下のコマンドがこの面倒を見てくれます。
# cp /etc/localtime /chroot/named/etc/
本物の囚人とは異なり、BIND はログ記録を壁に書くことはできません :-)。
通常 BIND はログを、システムのロギングデーモンである
syslogd
経由で記録します。
このタイプのログ記録は、特殊なソケットである /dev/log
を通してログエントリを送信することで行われます。
しかしこれは jail の外部にありますから、BIND からは使えません。
でもありがたいことに、これを解決する方法はいくつか存在します。
このジレンマに対する理想的な解決法には、
OpenBSD で導入された -a
スイッチをサポートする、
比較的新しいバージョンの syslogd
が必要です。
syslogd(8)
の man ページをチェックして、
自分の使っているのがこれかどうか見てください。
サポートしていれば、syslogd
を起動する際のコマンドラインに ``-a /chroot/named/dev/log
''
を追加するだけで OK です。
SysV-init をすべて使っているシステム
(Linux ディストリビューションのほとんどはそう) なら、
起動は通常 /etc/rc.d/init.d/syslog
ファイルでなされます。
例えば、私の Red Hat Linux システムでは、私は
daemon syslogd -m 0
の行を
daemon syslogd -m 0 -a /chroot/named/dev/log
と変更しました。
面白いことに Red Hat 7.2 では、
見たところ Red Hat はこの処理をもっと簡単にしています。
現在は /etc/sysconfig/syslog
というファイルがあり、
ここには syslogd に余分に与えるパラメータを定義できるのです。
Caldera OpenLinux システムでは
ssd
というデーモンランチャを使っており、
これは設定を /etc/sysconfig/daemons/syslog
から読みます。
この中のオプション行を以下のように修正するだけです。
OPTIONS_SYSLOGD="-m 0 -a /chroot/named/dev/log"
同様に SuSE システムでは、
このスイッチは /etc/rc.config
ファイルに追加するのが良いそうです。
SYSLOGD_PARAMS=""
という行を
SYSLOGD_PARAMS="-a /chroot/named/dev/log"
とすれば OK です。
そして最後に (といっても重要性の順ではないですよ) FreeBSD 4.3 では、
rc.conf
ファイルを編集して次の行を追加すればよいそうです。
syslogd_flags="-s -l /chroot/named/dev/log"
-s
はセキュリティ上の問題から与えるもので、
デフォルトの設定の一部です。
-l
は、別のログノードが置かれているローカルなパス名です。
【訳注: Debian なら /etc/init.d/syslogd
の
SYSLOGD=""
という行を
SYSLOGD="-a /chroot/named/dev/log"
とします。】
お使いのシステムでの変更方法がわかったら、
syslogd
を再起動するだけです。kill して再び
(追加パラメータとともに) 起動してもいいですし、
SysV-init スクリプトを使って次のようにするのでも良いでしょう。
# /etc/rc.d/init.d/syslog stop
# /etc/rc.d/init.d/syslog start
再起動できたら、/chroot/named/dev
に
以下のような log
という「ファイル」ができているはずです。
srw-rw-rw- 1 root root 0 Mar 13 20:58 log
古い syslogd
を使っている場合は、
ログを取るには別の方法を見つけなければなりません。
例えば hoellogd
のような、
「プロキシ」として動作するよう設計されているプログラムも存在します。
これは chroot された BIND からログエントリを受け取り、
それを通常の /dev/log
ソケットに渡します。
あるいは、BIND を設定して、ログを syslog に送るのではなく ファイルに書きこむようにもできます。 この方法を選ぶなら、BIND の文書にあたって詳細を調べてください。
まず最初に、/chroot
ディレクトリ全体へのアクセスを、
ばっさり root
ユーザのみに限ってしまいましょう。
もちろん、こうしたい人ばかりではないでしょう。
特に他のソフトウェアをこのツリー以下にインストールしていて、
この変更がそのソフトには適切でないような場合にはそうですね。
# chown root /chroot
# chmod 700 /chroot
同じく /chroot/named
へのアクセスは、
named
ユーザにのみ限ってしまって大丈夫です。
# chown named:named /chroot/named
# chmod 700 /chroot/named
もっと厳しくしたい場合は、
Linux システムなら
ext2 ファイルシステムにあるファイルやディレクトリの属性を、
chattr
というツールで immutable (不変) にすることもできます。
# cd /chroot/named
# chattr +i etc etc/localtime var
同様に FreeBSD 4.3 でこれらを immutable にしたいなら、
chflags
を調べてみましょう。
例えば次のようにすれば、/chroot/named/etc
ディレクトリ以下のすべてを immutable にできます。
# chflags schg /chroot/named/etc/*(*).
これらを dev
ディレクトリにも施せれば良いのでしょうが、
残念ながらこうすると syslogd
がここに
dev/log
ソケットを作れなくなってしまいます。
jail の内部にある他のファイルに immutable ビットを立ててもよいでしょう
(例えばプライマリゾーンファイルを変更されたくない場合など)。