フレッツADSL導入日誌

ローカルDNSサーバー

導入編
FreeBSDルーター編
>>> ローカルDNSサーバー
フレッツADSLで固定IP
ドメイン取得とDNS運用
メールサーバー
Webサーバー

30 Aug 2011 djbdnsのセキュリティ上の欠陥について記述。
12 Jun 2004 内部専用ゾーンサーバーBINDとdnscache 〜FreeBSDの場合〜を追加。
31 Jan 2004 内部で使うドメイン 〜明るいドメイン計画〜内部専用ゾーンサーバーを追加。
17 Jan 2004 BINDdjbdnsDNSキャッシュを追加。
14 Jun 2003 新規作成。

 このページはDNSに関する話題を集めています。DNSを自分で立てて運用する方法についても言及していますが、Unixの管理者としての基礎的な知識を前提としています。人に聞かないと「ユーザーを追加する」「起動スクリプトを変更する」などの操作ができない人は、まずはその辺りのスキルから磨いてください。

DNSとは?

 ドメインネームシステム(Domain Name System)のこと。

 インターネットでは通信先の指定にIPアドレスを使う。IPアドレスはIPv4の場合で0〜255までの数字を.で区切って4つ並べたもの(例: 192.168.1.1)。電話番号みたいなものと思えばよい。しかし、数字の羅列は覚えにくく、使いにくいので、普通は名前で指定する(例: www.example.jp)。このとき、example.jpの部分をドメイン名と呼ぶ。www.example.jp のような名前はホスト名と呼ばれるが、ドメイン名がホスト名を兼ねている場合もある。

 実際のアクセスはあくまでIPアドレスで行う必要があるため、ホスト名をIPアドレスに変換する必要がある。この変換を司っているのがDNSであり、DNSサーバーである。まあ、電話帳みたいなものである。ドメイン名・ホスト名はアルファベットと数字とハイフン(-)からなる名前を「.」でいくつかつなげたものである。「.」の数はドメインの種類やサイト管理者の思想によって異なる。最近では日本語も使えるようになってきたがまだ実験段階。

 ちなみに、ホスト名をIPアドレスに変換することを「名前をアドレスに解決する」という。こちらの方向を「正引き」という。DNSはこの逆変換もサポートしており、逆変換の方は「逆引き」と呼ばれる。なお、ホスト名とIPアドレスはいろいろな理由で必ずしも1対1ではないので、正引きした結果を逆引きした場合、元の名前に戻るとは限らない。
ドメイン名

 ドメイン名は一番後ろにある名前が一番大きなくくりである。英語圏での住所の書き方と似ている。一番後ろに来る名前はTLD(Top Level Domain)と呼ばれ、大きく分けるとgTLDと呼ばれるもの(.com・.netなど)と、ccTLD(.jp・.krなどの国名のドメイン)に分かれる。gTLDはInterNICの管理下である。アメリカの管理下ではない。アメリカ合衆国にはちゃんと.usというccTLDがある。

 TLDのすぐ前に来る名前は第2レベルドメインと呼ばれる。gTLDについては第2レベルドメインが各組織(企業とか)に割り当てられ、それより前(第3レベルドメイン以降)は割り当てた企業が適当に決めてよい。ccTLDについては第2レベルドメインは各国のNIC(日本ならJPNIC)が管理することになっている。.jp ドメインの場合、第2レベルドメインを「汎用JPドメイン」「属性型ドメイン」「地域型ドメイン」に分けている。

 汎用は example.jp のようなドメインで、第2レベルドメインが各組織に割り当てられ、第3レベルドメイン以降が各組織の管理下になる。属性型は .co.jp や .ne.jp のようなドメインで、第3レベルドメインが各組織に割り当てられ、第4レベルドメイン以降が各組織の管理下になる。地域型は chiyoda.tokyo.jp のようなドメインで、政令指定都市は 区名.市名.jp、その他の地域では 市町村名.都道府県名.jp という形式になり、一般に使用されるドメインについては、第4レベルドメインが各個人・組織に割り当てられ、第5レベルドメイン以降が各個人・組織の管理となる。

 各組織はさらに sales.example.jp / service.example.jp / post.example.jp などとドメインを付け加えることができる。この部分を「サブドメイン」と呼ぶ。
DNSの実際

 ドメイン名はDNSサーバーを使ってIPアドレスに変換する。階層化された分散システムになっていて、とりあえずルートサーバー(世界中に10台ちょっとある)にTLDをたずねる。例えば、www.example.co.jp を問い合わせる場合、「jpは誰が管理してるの?」とルートサーバーのいずれかに問い合わせる。すると、ルートサーバーは .jp を管理しているDNSサーバーを教えてくれる(日本国内に数台ある)ので、そのうちの1台に対して「co.jpは誰が管理してるの?」と問い合わせる。と、.co.jp を管理しているサーバーを教えてくれるので、そのサーバーに対して「example.co.jpは誰が管理してるの?」と問い合わせる。と、example.co.jp を管理しているサーバーを教えてもらえるので、そのサーバーに対して「www.example.co.jpのIPアドレスは?」と問い合わせを出し、めでたく www.example.co.jp のIPアドレスを知ることができる。本当はもうちょっと簡単で、もうちょっと複雑なのだが(意味不明)。

 example.co.jp 以下のドメインは example.co.jp が割り当てられた組織が管理する(とりあえず例題株式会社とでもしておく)。つまり、example.co.jp のDNSサーバーは例題株式会社内にあるのが普通だ(社外に管理を委嘱することもできる)。example.co.jp 以下のサブドメインは例題株式会社のDNSサーバーを設定することで自由に作り出すことができる。このとき、サブドメインを作ったことを上位のサーバーに明示的に伝える必要はない(注: example.co.jp そのものを管理しているサーバーが増えたとかIPアドレスが変わったとかの場合はそれを上位のサーバーに伝える必要がある)。

 ということで、独自ドメインを立ち上げるためには、基本的に以下の手順を踏む。

  1. どのドメインを使うかを決める

  2. そのドメインを管理している組織に自分のドメインを登録

  3. DNSサーバーを立てる(グローバルな固定IPアドレスと常時接続環境が必要)

  4. 上位のサーバーを管理している組織(普通はドメインを割り当ててもらった組織)にDNSサーバーのアドレスを教える
DNSサーバー

 DNSサーバーにもいくつか種類がある。一つは今までの説明で出てきたタイプのサーバーで、外部の人に組織内のほかのホストを教えるためのサーバーである。この場合のホストにはサブドメインを管理するDNSサーバーも含まれる。この種類のサーバーにはあまり名前がついてないのだが、ゾーンサーバーとかコンテンツサーバーなどと言われる。プライマリサーバーとかマスタサーバーという名称も近い意味で使われることがある(そのものではない)。通常は再帰検索を禁止する設定をするため、非再帰サーバーという言い方もされる。

 このタイプのサーバーには、プライマリマスタとセカンダリマスタ(スレーブ)の2種類がある。プライマリマスタはドメイン構造データの原本をもっているサーバーで、スレーブはデータを他のサーバーからもらうようになっているサーバーである。「ゾーンデータをよこせ」というスレーブからの要求を受け付けるサーバーを単にマスタサーバーと呼ぶ。

 普通、SOAレコードに名前が載っているのはプライマリマスタだが、別にスレーブサーバーをSOAに書いても大丈夫なはずである(やったことはないが)。プライマリマスタがゾーンにつき1台とも限らない。正しく運用されていれば、マスタもスレーブも権威付の同じ回答を返し、DNSを"使う"側から見れば区別は特にない。

 BINDの解説本を見ると分かるが、プライマリマスタ / スレーブはドメインごと(正確にはゾーンごと)に指定できるため、あるDNSサーバーが特定ドメインに対してはマスタで、他のドメインに対してはスレーブになっているかもしれない。また、プライマリマスタからデータを取得したスレーブサーバーが、さらに他のスレーブサーバーからゾーンデータ取得(転送)要求を受けることもある。したがって、スレーブサーバーは同時にマスタサーバーにもなり得る。ややこしい。まあ、ゾーン転送をしなければこの辺はどうでもよい。

 もう一つ、「キャッシュ」と呼ばれるサーバーがある。これは、自分自身はドメインデータを持っていなくて、もっぱら他のサーバーに問い合わせを出し、その回答を溜め込んで、同じ問い合わせを受け取った時に溜め込んでおいたデータを返すサーバーである。キャッシュはネットワーク負荷を軽減し、DNSの応答速度を早くする効果がある。時間課金のダイヤルアップ環境では無駄な発呼を防ぐ効果もある。ISPが契約者に提供するサーバーは普通はこの形である。サーバーが二つある場合は一方をプライマリ、もう一方をセカンダリと呼んだりするが、使う側から見ればやはり区別はなく、どちらにどちらを書いてもちゃんと動くはずである。

 小さなネットワークではスレーブサーバーはあまり用いられない。外部に名前を公開する必要がなく、内部でも名前解決を必要としないネットワークではキャッシュサーバーを入れるとよい(入れておく価値はある)。たいていの家庭内LANではこれで十分である。外部に名前を公開したい場合は外向けにゾーンサーバーを設ける。内部だけで使う名前がある場合は内部専用のゾーンサーバーが必要になる。したがって、小規模で本格的なLANでは、内部専用ゾーンサーバーキャッシュの2種のDNSサーバーを設けることになり、独自ドメインで外部公開サーバーを運用する場合は、外部公開ゾーンサーバーも運用することになる。

 2つのゾーンサーバーはどちらもプライマリマスタになる。よくセカンダリサーバーの必要性が説かれるが、この程度のネットワークでは自サイトが落ちてしまえば全サービス使用不能になるから、他のネットワーク上に置いたサーバーで名前をIPアドレスに解決できてもまったく意味がない。無理してまでセカンダリサーバーを置く必要はない。

 この3種のサーバーはBIND9ならば1プロセスでこなすこともできるし、プロセスを分けることもできる。BIND8やdjbdnsはプロセスを分ける必要があるが、OSに仮想インターフェース機能(一つのネットワークIFに複数のIPアドレスを割り当てる機能)があれば、サーバーの台数は1台で済む。両者を混在させることも可能である。もちろん、全部を別々のサーバーで動かしてもよい。

 DNSは設定を間違えるとローカルIPを外部ホストに教えてしまったり、メールが届かなくなったりといろいろ厄介なことが多いので、自信がない場合は全部を別々のサーバーで運用した方が安全である。私のサイトでは外部向け・内部向けゾーンサーバーをBIND9(1プロセス)で、キャッシュをdjbdnsで運用している。サーバーの台数は1台。

 組織内のホスト数が100台とかになった場合はまた別の戦略が必要になってくるが、家庭内LANの範疇を超えるので割愛。なお、DNSサーバーは単にネームサーバーと呼ばれることもある。
BIND

 Internet Software Consortium(通称ISC)謹製のDNSサーバーソフトウェア。BINDは元々Berkeley Internet Name Domainの略のようなので、カリフォルニア大学バークレー校由来なのだろう。DNSサーバーソフトの事実上の標準と言ってよい。非常に高機能で、内外に向けたゾーンサーバーとしても、内部ルートとしても、キャッシュ・フォワーダとしても用いることができ、ゾーンごとに異なる設定をして1プロセスで同時にこなすことも可能である。問い合わせIPアドレスごとに振る舞いを変えることもでき、特にBIND9では1プロセスで可能である(view機能)。その複雑さゆえ、設定が難しかったり、変な応答を返したり、時々セキュリティホールが見つかったりする。キャッシュを運用していてルートサーバーを尋ねたら、いつの間にか j.root-servers.net しか返って来なくなった(謎)のでキャッシュはdjbdnsに乗り換えてしまった。ISCのページが一次配布元。日本語の解説はインターネットで情報を探すより、オライリーDNS & BIND(通称バッタ本)を買った方が早い。キーワードは「最強・でかい・複雑」。
djbdns

 qmailでおなじみD.J.Bernstein作のDNSサーバーソフトウェア。外部向けサーバーとキャッシュは別々の小さなプログラムで動作することが大きな特長。どのくらい大きさが違うかと言うと、ソースアーカイブの状態でBIND9.2.3が4,553,260バイトなのに対し、djbdnsは85,648バイトしかない。バイナリの状態では、私の環境で調べてみると、namedをstripしたものが1,175,164バイトなのに対し、dnscacheは49,460バイト、tinydnsは23,176バイトしかない。djbdnsはBINDに比べて1/10以下なのである。

 BINDに比べて簡略で安定した回答を返すことが多い。シンプルゆえ欠陥も少なく、BINDに比べて更新の回数は極端に少ない(BINDが多いというのが正しいのかもしれない)。ただ、一般的なUnixのソフトウェアとビルド方法が違っていたり、事実上daemontoolsが必須だったり、設定ファイル群がかなりハナモゲラで場合によってはファイル名=設定だったり、ログが変だったり、ドキュメントが整っていなくてノウハウ本も少ないという欠点がある。cr.yp.to / D.J.Bernstein / djbdns が一次配布元。日本語の情報は前野年紀氏のページが詳しい。説明文書にマニュアル類がまとめてある。キーワードは「シンプル・さくさく・ハナモゲラ」。

 djbdnsには最初にセキュリティ上の欠陥を見つけた者に1,000ドルを支払う、という懸賞が作者によってかけられていた。 長い間そのような不具合は見つかっていなかったが、2009年の2月にコンテンツサーバーであるtinydnsとゾーン転送に使用するaxfrdnsを使用している場合にキャッシュを汚染できる不具合が見つかり、発見者であるMatthew Dempskyに懸賞金が支払われたようである。

 この不具合はかなり限られた条件で成立するものだったが、その後、dnscacheにも比較的短い時間でキャッシュ汚染が可能な脆弱性があることが発表されている。 この脆弱性はdjbdns patches(Kevin Day)に述べられており、パッチも公開されている。 dnscacheの脆弱性は不特定多数にキャッシュサーバーを公開している場合に問題になる不具合だが、構内のPCがウイルスに感染して構内のキャッシュサーバーが汚染され、キャッシュサーバーを参照している正常なPCが汚染されたアドレスをアクセスする(そして、フィッシングやさらなるウイルス感染を招く)というシナリオも考えられるので、パッチは当てておいた方がよいだろう。

 このようにまったく不具合がないわけではないが、djbdns-1.05の公開が2001年2月11日であり、以後8年間でセキュリティに関する欠陥が2つしか見つかっていないというのは、その間にBINDにリリースされたパッチを考えたら、非常に少ないと言えるだろう。
DNSキャッシュ

 通常はあまりありがたみがないが、内部専用サーバーを設けるとかなり重要な意味を持ってくる。内部専用サーバーは外部からは参照できないように設定する。もし、ISPのDNSサーバーをクライアントに設定すると、ISPのサーバーも外部ホストであるから、内部専用サーバーは参照できない。その結果、クライアントは内部の名前がまったく解決できなくなる。しかし、クライアントには何かサーバーを教えてやらないと、内部はおろか全ての名前が解決できない。一体何を教えればいいのだろうか。

 こういう場合に内部でキャッシュを運用し、キャッシュで内部/外部のゾーンを判定して参照先のDNSサーバーを使い分けるようにすれば、内部キャッシュのアドレスをクライアントに教えてやればよいことになる。内部専用のネームサーバーを設けなければ特に必須ではないが、設定方法が一番簡単なのでとりあえず最初に解説する。外部の名前を解決する場合にルートサーバーからたどるようにすることもできるが、ISPのDNSサーバーに要求を転送することもできる。後者はフォワーダと呼ばれる。

 サーバーソフトウェアはBINDでもdjbdnsでもよい。BIND9ならばゆくゆく立ち上げるであろう外部公開ゾーンサーバー・内部専用ゾーンサーバーも全部同一プロセスで実現できるが、内部専用サーバーはともかくとして、外部公開サーバーとキャッシュは分けた方が望ましい。そういう意味ではBINDにアドバンテージはあまりない。また、以前にBINDでキャッシュを運用していて変な応答が返って来たことがあり、それを機にキャッシュはdjbdnsに乗り換えているので、ここではdjbdnsの場合を説明する。

[djbdnsインストールの前に]

 とりあえずdaemontoolsをインストールしないと後で面倒なので、インストールしておく(ucspi-tcpは必須ではない)。/package というディレクトリを作ることになっているが、ルートファイルシステムに大量にファイルを置くのは望ましくないので、/usr/local あたりに djbpkg とかいうディレクトリを掘って、/package という名前でシンボリックリンクを張る。
mkdir /usr/local/djbpkg
chmod 1755 /usr/local/djbpkg
ln -s /usr/local/djbpkg /package
cd /package
 あとは見た通りだが、アーカイブの展開は tar xpfz で一気にやってもよい。tarのオプションpはパーミッションを保存する、という意味だが、これはDJBのパッケージ方式がパーミッションを変な風に使っているために必要になる。最後の報告は省略してよい(というか、普通は省略する)。

[svscanを動かす]

 daemontoolsをインストールすると、スタートアップスクリプトのそれらしき部分にsvscanbootを起動する部分が書き込まれるので、まずはそれを確認する。FreeBSDだと /etc/rc.local に書き込まれる。svscanboot起動前に立ち上がったデーモンは、svscanboot経由で立ち上がるデーモン群を参照できないのだが、rc.localはスタートアップの最後に近い部分で実行されるため、このままではほとんどのデーモンがsvscanboot経由で立ち上がるデーモンを参照できない。DNSはかなり基本的なネットワークデーモンになるため、他のデーモンから参照されるケースが多く、このまま放っておくといろいろ面倒なことが起こる。

 ということで、rc.localの行はコメントアウトしてしまい、各種デーモン立ち上げのなるべく最初の方で立ち上がるように仕向ける。ブート時に「Additional daemons」と表示されるあたりが適当だろう。FreeBSDではここでユーザーが指定したデーモンを起動する機能がないため、直接 /etc/rc を書き換える。ついでに、元はcshで書かれているが、他のスクリプト実行にならってshを使って書き換えてみた。例えばこんな感じである。太字の部分を書き加える。
echo -n 'Additional daemons:'

if [ -x /command/svscanboot ] ; then
        echo -n ' djb-supervisors'
        sh -c '/command/svscanboot &'
fi

# Start system logging and name service.  Named needs to start before syslogd
# if you don't have a /etc/resolv.conf.
#
case ${syslogd_enable} in
[Yy][Ee][Ss])
 許されるならば実際にリブートして確認してみるといいだろう。手動で立ち上げる場合は、見れば分かるように /command/svscanboot & と打てばよい。最後の & を忘れないように。ps で確認してみると、svscan と、readproctitle という変なコマンドラインが付いたプログラムが立ち上がっていることが分かるだろう。

 なお、やっぱり /etc/rc は書き換えたくない、という方には、後で少し違う方法を説明する予定である。ヒントは「named_programシェル変数」である。

[djbdnsのインストール]

 次にdjbdnsをインストールする。ドキュメントをインストールするように書かれているが、Webで参照すればいいし、このドキュメントより前述の日本語ページの方が使いやすいだろうからインストールする必要はない。本体インストールの際の展開ディレクトリは特に指定されていないのでどこでビルドしても大丈夫なはずだが、/package でやるのもよかろう。 2つほどセキュリティに関する欠陥が報告されているので、パッチを当てた方がよい。 例によって報告は省略する。

[djbdnsをローカルネットワークキャッシュとして設定]

 次にdnschacheの設定を行う。指定されたとおりにgdnscacheとgdnslogユーザーを作る。ユーザーIDは10000番以降などと決めておいたほうが、OSのバージョンアップなどがあったときに便利である(少なくとも1000番以下や、一般ユーザーの直後はやめたほうがよい)。DNSのポート番号にちなんで10053とかがよいだろう。

 キャッシュサーバーのIPアドレスはもちろん今設定しているマシンのIPアドレスなのだが、dnschacheを使う場合、同じIPアドレスで他のDNSサーバーを立てられないので、後で他のDNSサーバー(おそらくは内部専用ゾーンサーバー)を立てようとしている人は注意しなければならない。だいたいのOSではエイリアスという方法で対応できる。

 続いてdnschache-confを実行するのだが、その前に書き換えなければいけないファイルがある。インストール方法には書かれていないが、djbdnsのパッケージが作られた時点に比べて、ルートサーバーのIPアドレスが一部変わっているためである。

 具体的には、/etc/dnsroots.global ファイルを、最新のルートサーバー情報に応じて書き換える。最新のルートサーバー情報は ftp://ftp.internic.org/domain/named.root から得られる。また、dig などのツールがあれば、dig @ほげ.root-servers.net . ns などのようにしても得られる。ほげ にはaからmまでの文字を適当に入れる。こうして得られた情報を、オリジナルの /etc/dnsroots.global に合わせて書き換える。おそらく、j.root-servers.net のIPアドレスが変わっているはずである。

 ルートサーバーはあまり頻繁には更新されないが、たまに更新されることがあるので、各種情報に注意し、時々はルートサーバー一覧を取り寄せて、sortやdiffで比較してみるとよい。なお、現在FTPから得られるnamed.rootはj.root-servers.netのIPアドレスの後ろにスペースが入っているので注意のこと。

 あとは手順どおり dnscache-conf を実行し、/service/dnscache というシンボリックリンクを作り、ローカルホストの属するネットワークに対応するファイルを作成する。192.0.2.* に対して答えたければ /etc/dnscache/root/ip/192.0.2 というファイル(空でよい。普通touchコマンドを使う)を作る。ネットワーク部が24ビット以上のネットワークに対するアクセスは設定できないので、そのような場合はファイアウォールやinetd/tcpd、tcpserverなどで対応する必要がある。

 内部専用サーバを使う場合はもう少し設定が必要になるが、内部専用ゾーンサーバの項で説明する。

[クライアントの設定]

 これでサーバーの設定はおしまいなので、各クライアントの設定をする。Unixならば/etc/resolv.confを書き換える。その他のGUI OSではネットワークの設定でDNSを指定する場所があるので、そこを書き換えればよい。DHCPがある場合はDHCPサーバーが教えるDNSアドレスを変更し、クライアントでIPアドレスを再取得させる。
内部で使うドメイン 〜明るいドメイン計画〜

 内部でもドメイン構造を使用したいという場合、まずはドメインの構造をどうするかを考えておく必要がある。将来的にドメインを取って運用しようとしている場合は特によく考えなければならない。ドメインを取るつもりがないのならば、適当なTLD(例えばlocal)を決め、その下にサブドメインを適当にぶら下げればよい。

 曲がりなりにもインターネットにつながっているネットワークで勝手にTLDを決めてよいのか? という疑問が出てくるだろう。このサーバーは外からはアクセスできない(ように設定する)ので、このTLDが外に漏れることはない。もちろん、このTLDはLANの外にいる人に伝えても無意味である。ただし、実際にインターネットで使われているTLD(例えばnetとか)を使ってしまうと、LAN内からインターネット空間の名前を解決するときに困ることになるので注意。NTTのフレッツスクウェアがこの方式の大規模版になり、.fletsというTLDを使っている。このTLDはもちろんInterNICには登録されていない。

 将来的にインターネット空間のドメインを取ろうと思っている人は、ドメイン名の変更はDNSだけでなくありとあらゆるサーバーに影響が及んで非常に面倒なのと、ドメインは年間数千円で維持でき、ネームサーバーを登録しなくても特に問題はないので、この際だからドメインを取ってしまった方がよいだろう。なお、自分で各種サーバーを運用しようとしている人はNSレコードを自由に登録できるレジストラでドメインを取ること。こうして取ったドメインの下にサブドメインを作る。

 サブドメインはいろいろな名前の付け方があるが、家庭内LAN規模ならばそんなにたくさん作る必要もないだろう。外から見えるサーバーは自分に割り当てられたドメインそのものを使い、内部のサーバーは一段サブドメインを作る程度でよい。例えば、ドメインとして example.jp を取得したならば、外から見えるサーバーには www.example.jp などのホスト名を使い、内部では ntp.alpha.example.jp などのように、一段サブドメイン(この場合はalpha)を作るとよい。メールアドレスはホスト名を省くのが普通なので、ドメインを代表する擬人アドレスは root@example.jp などのようにし、実際に使うアドレスは someone@alpha.example.jp などのようにするとよい。

 ドメイン名やホスト名は、適当なシリーズで名づけられることが多い。これが攻撃のヒントを与えることになる場合もあるが、かといってランダムに付けたら覚えにくいことこの上ない。自分はいいかもしれないが、それこそ家庭内乱の火種になるだろう。よく使われるのは、星座・干支・花の名前・動物の名前・・・などである。例えば、example.jp ドメインに alpha.example.jp の他にもう一つサブドメインを設けるとすれば、普通は beta.example.jp になるだろう(もしかすると ppc.example.jp だという人もいるかもしれないが・・・)。

 以後の例では、とりあえず以下のようにホストが割り当てられているものとして話を進める。なお、192.0.2.* というアドレスは例示用で実際の使用は推奨されていない。実際に使用する際には 172.16.*.* や 192.168.*.* などを使う。
rat.alpha.example.jp192.0.2.1ゲートウェイ gw.alpha.example.jp
ox.alpha.example.jp192.0.2.2DNS ns.alpha.example.jp
tiger.alpha.example.jp192.0.2.3
hare.alpha.example.jp192.0.2.4
dns.alpha.example.jp192.0.2.53DNSキャッシュ
内部専用ゾーンサーバー

 ゾーンサーバーは再帰検索を禁止して運用するのが普通であり、他のサーバーからのデータを内部に溜め込んだりはしない。このため、ゾーンデータさえ正しければDNSソフトウェアによる回答の差異は比較的少ないので、BINDとdjbdns(tinydns)のどちらを使ってもよいだろう。ここでは、設定ファイルが比較的読みやすいBIND9を使うことにする。先ほども説明したとおりBINDは非常に多機能で、ゾーンサーバーとしてだけ使うのには、宝の持ち腐れという意味でも、サーバーのリソースという意味でも少々(かなり?)もったいない。しかし、ゾーンサーバー専用として設定した方が設定が簡単になり、間違いや問題も少なくなるので、特に最初は無理にキャッシュなどを設定しない方がよい。

[BINDのインストール]

 BINDには現在使われているものでもいくつかバージョンがある。大きくBIND4・BIND8・BIND9の三つである。BIND4は他と設定ファイルの形式が違う。BIND8とBIND9はほぼ同じであるが、BIND9はビューという機能があるのと、ゾーンファイル中のTTL(Time To Live、残存時間)の扱いが以前と多少異なっている。BIND9を避ける理由は特にないので、BIND9でよいだろう。

 インストール自体は比較的簡単で、ISCのページから最新のソースを落としたら、お好みでPGP署名を確認し、tar xfvz bind-9.2.*.tar.gz で展開、bind-9.2.* ディレクトリに入って、あとは ./configure ; make し、スーパーユーザーで make install でおしまいである。デフォルトではデーモンが /usr/local/sbin/named としてインストールされ、立ち上げ時に読み込まれる設定ファイルは /etc/named.conf である。

 インストールが済んだら、ブート時に立ち上がるようにしなければならない。FreeBSDでは rc.conf で指定できるのだが、FreeBSDには /usr/sbin に named が入っている(FreeBSD 4.9の場合 BIND 8.3.6。ちなみにこのnamedが使う設定ファイルは /etc/namedb/named.conf である)ため、単に named_enable を YES に設定しただけでは今インストールした named は使われない。named_program で立ち上げたい named のフルパスを指定してやる必要がある。
named_enable="YES"
named_program="/usr/local/sbin/named"
 dnscacheと同じホストでnamedを動かす場合、プライマリインターフェースのポート53が空いておらず、このままではBINDがLANからの要求を受けることができない。インターフェースは一つしかないが、エイリアスという機能を使うと、一つのインターフェースに複数のIPアドレスを割り振ることができる。FreeBSDの場合、ハンドブックの「バーチャルホスト」の部分に詳しく載っている。Linuxにも同様の機能があるはずである。例えば、FreeBSDが動いているホストox.alpha.example.jp(192.0.2.2)にエイリアス192.0.2.53を割り当てたければ、/etc/rc.conf に
ifconfig_ed1="inet 192.0.2.2 netmask 255.255.255.0"
ifconfig_ed1_alias0="inet 192.0.2.53 netmask 255.255.255.255"
と書いてリブートすればよい。もちろん、ed1 の部分は実際に使っているインターフェースデバイス名に置き換える必要がある。エイリアスは二つ以上定義することもできて、その場合はalias0の部分をalias1 alias2・・・と増やしていけばよい。エイリアスのIPアドレスのネットマスクはオール1に設定する。

 どちらのIPアドレスをどちらのDNSに振るかは自由である。dnschacheのIPアドレス設定は /etc/dnscahce/env/IP というファイルにサーバーが動作するIPアドレスが書いてあるので、このファイルを変更すればよい。BIND9の場合は後述する。

 インストール時にもう一つやらなければならないことがある。rndcのセットアップである。rndcはRemote Name Daemon Controlの略で、これを使うとゾーンファイル・設定ファイルの読み込み直しなどが簡単にできるようになる。Remoteが付いていることから分かるように、このプログラムはネットワーク経由でネームサーバーを制御することができるが、今回はそこまでしなくてもよいだろう。そうすると設定は簡単で /usr/local/sbin/rndc-confgen -a を実行すればよい。

 ・・・はずなのだが、FreeBSD 4.7・FreeBSD 4.9ともこれではだめで、-r オプションでランダムデバイスを指定する必要があった。たいてい /dev/random で済むのだが、今回はそれでもだめで、/dev/urandom を使った。ランダムデバイスがどうにも調達できない場合は普通のファイルを指定できる。与えるファイルは圧縮されている方が乱数度は高くなる。
/usr/local/sbin/rndc-confgen -a -r /dev/urandom
 もう一つ、できればファイアウォールによってアクセスを制限しておく。内部専用のサーバーは外から見えるべきではないからである。外からの攻撃も防ぐことができ、また、たとえ設定を間違えたとしても影響を最小限にとどめることができる。FreeBSDのipfwならば、ipfw add 番号 deny ip from any to any 53 in recv tun0 などと設定すればよい。「番号」は適切なルール番号を指定する。tun0は外部接続に使っているインターフェースを指定する。

[BINDの設定]

 BINDの設定には/etc/named.confを使用する。プライマリマスタサーバーの設定は概ね以下の通りになる。
options {
        directory "/var/named";
        pid-file "/var/named/named.pid";
        listen-on { 192.0.2.2; };
        allow-transfer { none; };
        notify no;
        recursion no;
};

zone "alpha.example.jp" {
        type master;
        file "db/alpha.zone";
};

zone "2.0.192.in-addr.arpa" {
        type master;
        file "db/192.0.2.zone";
};
 よく、BINDの設定は複雑だと言われるが、見た感じどうだろうか? 他のBINDの設定ファイルに比べてすっきりした印象を受けるはずである。キャッシュとゾーンサーバーを分けるとこれだけ簡単になるのである。

 directoryはnamedの動作の基準になるディレクトリを指定する。ゾーンデータベースファイルの指定はこのディレクトリからの相対パスになり、統計情報などもこのディレクトリに出力される。ただし、PIDファイルだけは /var/run/named.pid となるので、/var/named の下に出力したければ例のように書いておかなければならない。

 listen-on は問い合わせを受け付けるアドレスである。listen-on を書かなければ全インターフェースが使用される。dnscacheと同じホストでBINDを動かす場合、listen-on オプションが必要になる。正確に言うと起動順序にもよるのだが、明示的に書いておいた方がよいだろう。

 次の3行はアクセス制限に関するものである。allow-transfer と notify は、ゾーン転送を許可するスレーブサーバーと、ゾーンファイルが更新されたときにスレーブサーバーに伝えるか、を示している。今回の場合、スレーブはないので明示的に止めておく。

 recursion no は再帰検索の禁止である。再帰検索とは、クライアントから問い合わせを受けたときに、その問い合わせの答えを見つけるまで複数のサーバーに問い合わせを送る動作のことを指す。キャッシュサーバーは当然再帰検索しなければならないが、ゾーンサーバーは自分のゾーンにのみ責任を持てばよいので、知らないゾーンに対しては他のサーバーに問い合わせずに「知らん!」と返してよい。また、再帰検索は繰り返し多数のホストに問い合わせを送るためサーバーに負荷がかかり、不要な再帰検索要求を大量に送りつけられるとサーバーダウンの原因になるため、ゾーンサーバーでは禁止しておくのが普通である。

 これで基本的なオプション設定はおしまい。あとは問い合わせを返すゾーンと、ゾーン情報の入ったゾーンファイルの名前をずらずらと指定すればよい。alpha.example.jp ゾーンはいいだろう。aplha.example.jp ドメインの問い合わせがあった場合は、alpha.zone ファイルを参照して回答を行う。

 もう一つ、2.0.192.in-addr.arpa という見慣れないゾーンがある。これは、IPアドレスから名前へ逆変換するためのゾーンファイルである。DNSは名前をIPアドレスに変換するときに使われるが、IPアドレスを名前にするときにも使われる。そして、変換手順はどちらも同じものが使われる。IPアドレスの場合は in-addr.arpa ドメインから始めて、このドメインに、IPアドレスの数字を、上(左)の方から、サブドメインの名前として付加しながら検索していく。

 例えば、192.0.2.3 ならば、まずルートサーバーに arpa ドメインのサーバーをたずね、arpa ドメインのサーバーに in-addr.arpa ドメインのサーバーをたずね、192.in-addr.arpa ドメインのサーバーをたずね・・・というように検索していく。したがって、192.0.2.0/24 ネットワークの名前は 2.0.192.in-addr.arpa ゾーンのサーバーに問い合わせればよいのだが、このアドレスはローカルアドレスであり、このゾーンについて権威を持ったサーバーはインターネット上にない(当たり前だ。逆にいえばだからこそ自由に名前が付けられる)。したがって、DNSを用いてLAN内のIPアドレスを名前に変換したければ、2.0.192.in-addr.arpa についての情報も持たせておかなければならない。

 この他に、"." と localhost と 0.0.127.in-addr.arpa ゾーンを持たせることもある。"." はルートサーバーへたどり着くためのヒントとして常に必要なのだが、クラスINの場合はBIND内部にヒント情報を持っているため不要である。ルートサーバーのIPアドレスが変わると、キャッシュの場合は更新されたルートヒントファイルを指定する必要があるが、ゾーンサーバーの場合ヒントが使われることがないのでそのような手間も不要である。残りの二つは常に自分自身を示すアドレス 127.0.0.1 と、それに対応する慣用的な名前 localhost のためのゾーンである。しかし、これらの名前・アドレスはdnschacheが勝手に変換してくれるため、dnschacheを使う場合はこれらのゾーンは必要ない。

[ゾーンファイル]

 実際に指定されたゾーンにどんなホストが存在するのかを書き示したのがゾーンファイルで、基本的にホストとアドレスの対応表だと思えばよいだろう。ゾーンファイル名は、named.conf 内の directory オプションで指定したパスを基準にした相対パスを、zone 内の file に記述する。先ほどの例だと directory が /var/named で、alpha.example.jpゾーンの file 指定は db/alpha.zone だから、alpha.example.jp ゾーンのゾーンファイルは /var/named/db/alpha.zone となる。

 ゾーンファイルはリソースレコード(略してRRとも言われる)がずらずら並べられた形になっている。基本的に1行が1レコードに対応するが、SOAのように資源データのフィールド数が多く、1行が長くなる場合は、行末に ( を書くことでレコードを複数行に渡って書くことができる。

 各レコードは 名前 クラス TTL タイプ 資源データ の順にデータが並んでいる。なお、クラスとTTLは省略可能で、両方書く場合はどちらを先に書いてもよい。名前はこのレコードがどの名前についての情報なのかを示す。省略記法があるが後述する。クラスはどういうアドレス空間かを示すものだが、現在のところIN(インターネット)以外に広く使われているものはない。TTLはTime To Liveの略で、残存時間のことである。タイプはこのレコードがどんな情報を示しているかを示す。資源データ(略してRDATAとも言われる)はタイプによって記述が異なる。

 先ほどの例
rat.alpha.example.jp192.0.2.1ゲートウェイ gw.alpha.example.jp
ox.alpha.example.jp192.0.2.2DNS ns.alpha.example.jp
tiger.alpha.example.jp192.0.2.3
hare.alpha.example.jp192.0.2.4
dns.alpha.example.jp192.0.2.53DNSキャッシュ
をゾーンファイルに書いてみると、以下のようになる。
$TTL    432000
@       3600    SOA     ns.alpha.example.jp. dnsadmin.alpha.example.jp. (
                              2004012201      ; serial
                              10800           ; refresh
                              3600            ; retry
                              604800          ; expire
                              600 )           ; negative
                NS      ns
rat             A       192.0.2.1
ox              A       192.0.2.2
tiger           A       192.0.2.3
hare            A       192.0.2.4
gw              A       192.0.2.1
ns              A       192.0.2.2
dns             A       192.0.2.53
 最初の $TTL はリソースレコード中のTTLフィールドを省略した場合に使用されるTTL(デフォルトのTTL)を指定する。次の行のタイプSOAのレコードは「権威開始(Start Of Authority)」の意味である。ゾーンファイルで最初に出てくるリソースレコードは原則としてSOAレコードになる。名前が @ になっているが、名前に @ と書くと、$ORIGIN で指定した名前か、named.conf 中の対応する zone で指定されているゾーン名に置き換えられる。この名前のことを「基点名」と呼ぶ。今ならば alpha.example.jp になる。クラス IN は省略されていて、TTLが3600と指定されている。単位は秒なので、他のDNSキャッシュサーバー・クライアントがこのリソースレコードを問い合わせた場合、その結果を1時間はキャッシュに保存していてくれる。

 SOAの資源データはプライマリマスタネームサーバー名、管理者メールアドレス、シリアル番号、リフレッシュ間隔、リトライ間隔、期限切れとなる時間、ネガティブキャッシュ時間 である。上の例ではシリアル番号からネガティブキャッシュ時間までが ( ) に入れられ、複数行に渡って記述されている。

 プライマリマスタサーバー名は、同じゾーンで権威を持っているどのサーバーに問い合わせても、同じ名前を返すように設定する。今はネームサーバーは ns.alpha.example.jp しかないのでこれを書いておけばよい。管理者メールアドレスは通常のメールアドレスの @ を . に変えたものである。この場合だと dnsadmin@alpha.example.jp を意味することになる。なお、メールアドレスのユーザー名に . が含まれる場合、\ でエスケープしなければならない。

 その後の4つはスレーブサーバーが参照するものなので今のところあまり深く考える必要はない。最後のネガティブキャッシュ時間は、他のDNSキャッシュサーバー・クライアントがこのゾーン内にない名前を検索したときに、その結果を(キャッシュ・クライアントが)何秒間保存すべきかを示している。通常はTTLよりもだいぶ短めに設定する。この例だと10分である。

 なお、RFC1035ではネガティブキャッシュ時間の部分は「最小TTL」として定義されている。BIND8まではゾーンのデフォルトTTLとして扱っていた。RFC2308でネガティブキャッシュキャッシュ時間として新たに定義しなおされ、デフォルトTTLを表現するために $TTL というディレクティブが導入された。これに伴い、BIND9でのデフォルトTTLは$TTLディレクティブで指定するように変更されている。もし指定がなかった場合、BIND9.1とBIND9.2は起動時にエラーとなる。BIND9.3は警告を出した上で、SOAのネガティブキャッシュ時間に書かれている値をデフォルトのTTL時間として扱う。

 もう一つ、RFC2181には「SOAのTTLは0であるべきだ」という意味のことが書かれている。想像だが、SOAにはスレーブサーバーがゾーンデータの更新を知る手がかりとなるシリアル番号が含まれており、キャッシュされてしまうと都合が悪いからだろう。しかし、実際に世の中にあるサーバーでは0になっているものは少ない。例えば、ルートサーバー a.root-servers.net に "." のSOAをたずねると、TTLは86400(1日)が返ってくる。cr.yp.toが収容されているサーバーでは2560(約40分)という値が返ってくる。返ってくる値は0ではないのだが、他のリソースレコードに比べてずいぶん短い値が返ってくる。

 通常の使用ではSOAが必要な場合というのはほとんどないから、SOAに短めのTTLを設定しても、ネットワークトラフィックはほとんど影響を受けない。他のリソースレコードにはSOAに比べ頻繁に参照されるため、TTLはある程度長い値(数日程度)にしておくのが望ましい。ここでは、SOAについてはTTLを3600(1時間)として、他のリソースレコードについてはTTLを432000(5日)としてみた。なお、サーバー移転などの際には前もってこの値を小さくしておく必要がある。

 次のレコードはNSレコードで、このゾーンに権威のあるネームサーバーを指定する。一つのレコードにつき一つのサーバーしか指定できないので、スレーブサーバーがある場合はNSレコードを複数書くことになる。名前が省略されているが、省略された場合は直前のレコードと同じ名前を使う。直前は@、つまり alpha.example.jp だったから、これがそのまま使われる。TTLは省略されているので、$TTLディレクティブの値432000が使用され、5日間キャッシュされる。NSレコードの資源データはネームサーバーの名前を(一つだけ)書く。ns とだけ書いてあるが、最後にピリオドがない名前は基点名が補われる。今の場合だと alpha.example.jp ドメインが補われて ns.alpha.example.jp になる。

 余談だが、SOAのプライマリマスタサーバー名、管理者メールアドレスも同様に省略できるので、実は ns dnsadmin と書いてもよかったのである。が、この部分はあまり省略しないのが普通(後述)で、省略しない場合は最後にピリオド "." を付けなければならない。これを忘れるととてつもなく長い(そして変な)名前ができあがってしまう。これはゾーンファイルの中だけの話なので、named.conf の zone指定では後ろにピリオドを付けないで指定する。

 NSレコードの後にはAレコードが並んでいる。これは、名前とアドレスの対応を示したものである。名前は最後にピリオドがないから基点名が補われ、例えば rat は rat.alpha.example.jp として扱われる。クラスは省略されているのでIN、TTLも省略されていて$TTLディレクティブの値が使われ、5日である。Aレコードの資源データはIPアドレスである。IPアドレスは名前ではないので後ろにピリオドは付けない。

 よく見ると同じIPアドレスを持ったAレコードがあることに気づくだろう。IPアドレスは一つのAレコードにつき一つしか書けないため、一つのホストが(同じIPアドレスで)複数の名前を持つような場合、このようにして複数のホスト名を定義する。逆に、一つのホストが複数のIPアドレスを持っているような場合は、同じ名前に対して複数のAレコードを定義すればよい。続けてAレコードを書けば2行目以降の名前は省略できる。

[逆引き]

 これで名前からIPアドレスへの変換のためのデータは揃った。しかし、DNSはIPアドレスから名前への変換を自動ではやってくれないので、逆引きのためのデータも書く必要がある。先ほどちょっと述べたが、逆引きの場合はIPアドレスを逆に並べて、in-addr.arpaを最後に補った名前を指定してDNSに問い合わせを出す。例えば、192.0.2.3 に対応するホスト名を調べたければ、3.2.0.192.in-addr.arpa を指定してDNSに問い合わせを出す。これはもはやIPアドレスではなく、in-addr.arpa という変なドメインに属しているという点を除けば、ns.alpha.example.jp と同様の名前として扱われる。答として tiger.alpha.example.jp というPTRレコードが返ってくるように 2.0.192.in-addr.arpa ゾーンのゾーンファイルを書く。例えば、以下のようになる。
$TTL    432000
@       3600    SOA     ns.alpha.example.jp. dnsadmin.alpha.example.jp. (
                              2004012201      ; serial
                              10800           ; refresh
                              3600            ; retry
                              604800          ; expire
                              600 )           ; negative
                NS      ns.alpha.example.jp.
1               PTR     rat.alpha.example.jp.
                PTR     gw.alpha.example.jp.
2               PTR     ox.alpha.example.jp.
                PTR     ns.alpha.example.jp.
3               PTR     tiger.alpha.example.jp.
4               PTR     hare.alpha.example.jp.
53              PTR     dns.alpha.example.jp.
 書き方はほとんど同じだが、いろいろ注意する点がある。SOAとNSは先ほどと同じだが、こちらのゾーンファイルは 2.0.192.in-addr.arpa ゾーンのものであるから、基点名が 2.0.192.in-addr.arpa である。したがって、SOAレコードのネームサーバー名、管理者アドレス、NSレコードの資源データに指定する名前はドメインを省略できない。うっかり省略してしまうと ns.alpha.example.jp にならず、ns.2.0.192.in-addr.arpa という変な名前ができあがってしまう。SOAレコードはコピー・ペーストして使うことが多いため、SOAのネームサーバー名・管理者アドレスはドメインを省略しないでFQDN(Fully Qualified Domain Name、完全修飾ドメイン名)を書いた方が後々間違いが少ない。後ろのピリオドを忘れないように。

 以下、PTRレコードが並ぶ。PTRレコードも左側に書くのは名前なので、基点名省略の規則が適用される。したがって、1 と書くと 2.0.192.in-addr.arpa が補われて 1.2.0.192.in-addr.arpa という名前ができがる。これは、キャッシュやクライアントがIPアドレス 192.0.2.1 を問い合わせるときに使う名前になっている。これに対する答えが右側に書いてあるが、右側も名前なので基点名省略の規則が適用されるが、先ほどからしつこく述べているように基点名は 2.0.192.in-addr.arpa だから、FQDNを書かなければならない(後ろのピリオドを忘れないように)

 最初のPTRレコードの次の行(やはりPTRレコード)は名前が省略されている。省略されているのは名前なので、名前を省略した場合の規則が適用される。つまり、直前の名前がそのまま使われる。したがって、1.2.0.192.in-addr.arpa に対する定義、言い換えるとIPアドレス192.0.2.1に対する定義だということになる。よって、IPアドレス192.0.2.1は二つのPTRレコードを持ち、rat.alpha.example.jp と gw.alpha.example.jp という名前に対応する。実際に正引きの方のゾーンファイルと対応していることが分かるだろう。あとで実際にテストしてみると、ちゃんと両方の名前が返ってくることが分かるはずだ。

[起動とテスト]

 これでBINDの設定ファイルは全部そろったので /usr/local/sbin/named を起動する。できればブートして確認するとよい。起動したら /var/log/message あたりを見て、エラーを出力していないかどうか確認する。

 テストには nslookup / dig / host といったツールを使う。djbdns には dnsq / dnsqr などのツールが付いてくるのでこれを利用してもよい。nslookup は将来のBINDリリースからは外される予定のようだ。dig はかなり詳細な情報を、ゾーンファイルとして使える形で出力する。host は dig より簡潔な出力になる。dnsq は host に近い。hostを使う場合は host -t レコードタイプ 名前 サーバー と打つ。dnsqの場合は dnsq レコードタイプ 名前 サーバー である。-tが不要だ。ただし、ptrレコードを検索する場合、hostはIPアドレスを指定すればよいのに対し、dnsqはin-addr.arpaドメインの名前を指定しなければならないので少々面倒である。

 今はDNSの設定をテストしようとしているので、DNSサーバー名は省略できない。省略してしまうとデフォルトのDNSサーバー、通常はキャッシュサーバーを見に行ってしまう。キャッシュサーバーはまだ設定を変更しておらず、今立ち上げたDNSサーバを見るようにはなっていないから、問い合わせは全部失敗するだろう。host を使う場合、hostコマンドを実行するマシン自体が試験運用中ならば、一時的に /etc/resolv.conf を書き換えればサーバー指定を省略できる。

ここではhostを使ってみることにする。これらのツールはバージョンによってかなり表示内容が違う。ソースから何も考えずにインストールすると /usr/local/bin/host になるのだが、標準でBINDが入っている場合、単に host と打つと /usr/bin/host が使われることがある。
$ host -t soa alpha.example.jp 192.0.2.2
Using domain server:
Name: 192.0.2.2
Address: 192.0.2.2#53
Aliases:

alpha.example.jp SOA ns.alpha.example.jp. dnsadmin.alpha.example.jp. 2004012201 10800 3600 604800 600
$ host -t ns ns.alpha.example.jp 192.0.2.2
Using domain server:
Name: 192.0.2.2
Address: 192.0.2.2#53
Aliases:

alpha.example.jp name server ns.alpha.example.jp.
$ host -t a ns.alpha.example.jp 192.0.2.2
Using domain server:
Name: 192.0.2.2
Address: 192.0.2.2#53
Aliases:

ns.alpha.example.jp has address 192.0.2.2
$ host -t ptr 192.0.2.1 192.0.2.2
Using domain server:
Name: 192.0.2.2
Address: 192.0.2.2#53
Aliases:

1.2.0.192.in-addr.arpa domain name pointer gw.alpha.example.jp.
1.2.0.192.in-addr.arpa domain name pointer rat.alpha.example.jp.
$
 ゾーンファイルに書いた順序で確かめていくとよいだろう。つまり、soa ns a ptr と調べていく。TTLまで見たい場合は -v をつけると詳細な情報を表示してくれる。
$ host -v -t soa alpha.example.jp 192.0.2.2
Trying "alpha.example.jp"
Using domain server:
Name: 192.0.2.2
Address: 192.0.2.2#53
Aliases:

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56340
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; QUESTION SECTION:
;alpha.example.jp.              IN      SOA

;; ANSWER SECTION:
alpha.example.jp.       3600    IN      SOA     ns.alpha.example.jp. dnsadmin.alpha.example.jp. 2004012201 10800 3600 604800 600

;; AUTHORITY SECTION:
alpha.example.jp.       432000  IN      NS      ns.alpha.example.jp.

;; ADDITIONAL SECTION:
ns.alpha.example.jp.    432000  IN      A       192.0.2.2

Received 888 bytes from 192.0.2.2#53 in 16 ms
$
間違いが見つかった場合は named.conf ファイルや対応するゾーンファイルを修正し、named に修正されたことを伝える。named を再起動してもよいが、通常は rndc reload とすることで named が各種設定ファイルを読み直してくれる。なお、rndc はデフォルトで /usr/local/sbin にインストールされる。

[キャッシュの設定]

 これでゾーンサーバーの設定は終わったが、このサーバーを参照しているホストはまだ一台もない。キャッシュの設定を変更して、alpha.example.jp ドメインの名前解決の場合に限り ns.alpha.example.jp(192.0.2.2) を参照するように指示する。すると、LAN内のクライアントはキャッシュサーバーを参照しているので、特に設定を変更しなくても、キャッシュを通して間接的にゾーンサーバーを参照することになる。

 djbdns(dnscache)の場合、この設定は /etc/dnscache/root/servers ディレクトリに、中身が参照先のサーバーのIPアドレスであるようなファイルを、ドメイン名と同じ名前で作ることで行う。今回の例だと、
# echo 192.0.2.2 > /etc/dnscache/root/servers/alpha.example.jp
# echo 192.0.2.2 > /etc/dnscache/root/servers/2.0.192.in-addr.arpa
でよい。忘れがちだが逆引きのための設定も必要である(二行目)。サーバーは複数設定できる。その場合はサーバーのIPアドレスを一行にひとつずつ書く。

 あとは dnscache プログラムを再起動する。daemontools(supervise) 下で動いている場合、本来は svc プログラムで -t オプションを指定して dnscache を制御するのだが、実は dnscache プロセスを kill するだけでよい。kill すると supervise が dnscache を勝手に再起動してくれる。もし、テストの時にresolv.confを変更していたら、キャッシュを参照するように戻すのを忘れないこと。終わったら、LAN内のクライアントから alpha.example.jp ドメインの名前が解決できることを確認する。もちろん、外部のドメインの名前も解決できるはずである。

[BINDとdnscache] 〜FreeBSDの場合〜

 上の例ではdnscacheを立ち上げるために /etc/rc を直接編集したが、/etc/rc を編集せずに済む方法もある。FreeBSD4系は /etc/rc.conf で named_enable="YES" とすると、named_program で指定されたプログラムを立ち上げるようになっているが、このシェル変数にはシェルスクリプトを指定することもできる。/etc/rc.named あたりに BIND9とdnscacheを続けて立ち上げるスクリプトを書いて、/etc/rc.conf の named_programに指定してやれば、/etc/rc を書き換えなくとも目的を達成できる。

 例えば、/etc/rc.named として、
#!/bin/sh
if [ -x ${named_exec:='/usr/local/sbin/named'} ] ; then
        ${named_exec}
else
        echo " - WARNING: ${named_exec} is not found."
fi
if [ -x /command/svscanboot ] ; then
        echo -n ' djb-svscan'
        sh -c '/command/svscanboot &'
fi
sleep 1
exit 0
こんなシェルスクリプトを書く。実行パーミッションを立てるのを忘れないように。ちなみに、sleep 1 はnamedが立ち上がってから実際に問い合わせを受け付けるようになるまで若干間があるようなので入れてある。rcスクリプト中でローカルDNSへの問い合わせが起きると、名前の解決に失敗してしまうことがあり、その防止策である。

 あとは rc.conf の中で、
named_enable="YES"
named_program="/etc/rc.named"
としてブートすれば、しかるべき時点でBIND9とdnscache(正確にはsvscanとその仲間たち)が立ち上がる。ただし、svscan管理下のデーモンが他にあると、それらもここでガサガサ立ち上がってしまう欠点がある。

[DHCPとDNS]

$GENERATEディレクティブ。ダイナミックDNS。

Copyright (C) 2006 You SUZUKI

$Id: dns.htm,v 1.11 2011/08/30 13:03:44 you Exp $