Domain Name Systemの導入と設定(BIND 8編)

電子メールアドレスの @ の右側にくる名前(ドメイン名)や www.example.com などのような URL の一部を構成する名前は、すべて Domain Name System (DNS) と呼ばれるシステムにより検索されます。基本的に DNS は、あるコンピュータの名前からそのコンピュータの IP アドレスを得たり、IP アドレスからコンピュータ名を得るための仕組みです。

ここでは、DNS を実装するためのシステムの一つである BIND (Berkeley Internet Name Domain) の設定について記述してあります。BINDは、サーバ(named)、 リゾルバ(libresolv.a)、管理用プログラム(nslookup, dig) などから構成される一連のプログラム群です。 現在は、Internet Software Consortium によってサポートされています。

* インストール

BIND のパッケージは、ISC から最新のものを入手する。ここでは、現時点で最新の BIND 8 というバージョンのパッケージをもとに説明しています。src、contrib、doc といったパッケージが用意されているので必要と思われるものを入手して下さい。ソースさえあれば取りあえず DNS は実装できます。BIND のパッケージは、カレントディレクトリーに多くのファイルやディレクトリーが展開されるので、あらかじめ適当なディレクトリーを作ってからパッケージを展開した方がよい。
展開後は、INSTALL ファイルを参考に必要なモジュールをコンパイルして下さい。作業は、ソースツリーのリンクを作成し make (make clean; make depend;make) するだけなので詳細は記述しません。

* ドメインに関する Tips

各種設定ファイルを記述する前に、ちょっと DNSに関する Tips を記述しておきます。


* 各種設定ファイル

インストールが完了したら、運用に必要な各種設定ファイルを記述します。

named.conf

このファイルは、メインのサーバーである named が最初に読み込む初期設定ファイルです。いままで BIND 4 を運用していた場合、BIND 8 のパッケージに付属の named-bootconf.pl という perl スクリプトを利用して BIND 4 の設定ファイルである named.boot を named.conf に変換することが出来ます。named.conf を記述する際には、C++ 言語のように、最後のセミコロンが必要なことに注意して下さい。また、コメント行についても C++言語とおなじです。C言語やシェルで使われるコメントの記述も可能です。

options ステートメント named 全体の動作に関連した option の設定です。
options {
    // ゾーンファイル等を格納するディレクトリを指定します。
    // デフォルトは、カレントディレクトリである"."です。
    directory "/etc/nsdb";
 
    // ゾーン転送の許可/不許可の指定。namedがゾーン転送に応じる相手を限定します。
    // デフォルトは、すべてのゾーン転送の要求に応じる "{ any; };" です。
    allow-transfer {
        192.168.0.1;        // 特定のアドレス形式による指定方法(許可)
        192.168.1.0/24;     // ネットワーク形式による指定方法(許可)
        !192.168.2.123;     // 特定のアドレス形式による指定方法(拒否)
    };
 
    // 問い合わせの許可/不許可の指定。namedが問い合わせに対して答える相手を限定します。
    // デフォルトは、すべての問い合わせに応じる "{ any; };" です。
    //   不正アクセスの拒否等に利用します。
    allow-query {
        192.168.0.200;      // 特定のアドレス(許可)
        192.168.1.0/24;     // ネットワーク(許可)
        !192.168.2.1;       // 特定のアドレス(拒否)
    };
 
    // 動的ネームサーバを用いる場合以外は "{none;};" にしておくのが良いでしょう。
    // デフォルト値は "{none;};" です。
    allow-update { none; };
};
 
zone ステートメント
hint (root cache)
ルートサーバを見付けるための hint となるデータベースファイル(ヒントファイル)を指定します。 ネームサーバは、問い合わせのあったドメインについての情報を全く持っていない場合、ルートサーバを参照します。そのときに、ルートサーバのIPアドレスをヒントファイルを用いて調べます。
最新の hint ファイルは、ftp://rs.internic.net/domain/named.rootにあります。以降、最新版の root.cache ファイルを入手するには dig コマンドを 使用することができます。
         # dig @ns.internic.net . ns > named.root
// ヒントサーバ
zone "." in {
    // ゾーンタイプ
    type hint;
 
    // ルートサーバを見付けるためのヒントファイル
    file "named.root";
};
 
logging ステートメント ログの記録を、syslogや指定したファイルなど、カテゴリー別にきめ細かく指定できます。 channel (記録ファイル名や記録レベルを指定する)フレーズで定義したオリジナルのログファイルを、 category フレーズに指定することで、syslog とは別の独立したファイルを作成することが出来ます。
logging {
    // オリジナルの channel を定義します。
    channel bind_log {
        // パス名の指定
        file "/var/log/named.log";
 
        // 優先順位
        severity info;
    };
 
    // ゾーン転送が生じたら記録する
    category xfer-out {
        // channel 名
        bind_log;
    };
 
    // デフォルト
    category default {
        // syslogファイル
        default_syslog;
    };
};
 
zone ステートメント
master (primary)
管理するドメインに関するデータベースを指定します。ネームサーバが、自前でデータベースをもつゾーンをプライマリゾーンと呼びます。ゾーンファイルと呼ばれるデータベースファイルを指定します。
// 正引きデータベースの指定
// このブロックは、zone "domainname"というブロックではじまります。
// domainnameには、ゾーンのドメイン名が入ります。
zone "foobar.co.jp." in {
    // ゾーンタイプ
    type master;
 
    // ゾーンファイル名
    file "foobar.zone";
};
 
// 逆引きデータベースの指定
// このブロックは zone の次に、使用する IPアドレスを RFC1101 に従って指定します。
zone "1.168.192.in-addr.arpa." in {
    // ゾーンタイプ
    type master;
 
    // ゾーンファイル名
    file "foobar.rev";
};
 
// ループバックアドレス
zone "localhost." in {
    // ゾーンタイプ
    type master;
 
    // ゾーンファイル名
    file "localhost.zone";
};
 
zone "0.0.127.in-addr.arpa." in {
    // ゾーンタイプ
    type master;
 
    // ゾーンファイル名
    file "localhost.rev";
};
 
zone ステートメント
slave (secondary)
同じゾーンを持つマスターサーバから、ゾーンをコピーしてサービスに備える場合は、slave についてのゾーンの記述が必要です。
zone "baz.ne.jp." in {
    // ゾーンタイプ
    type slave;
 
    // 障害対策のために、ネットワーク経由で入手したゾーン情報をファイルにバックアップします。
    file "baz.cache";
 
    // master サーバの IP アドレス(複数可)
    // ゾーン転送元となるホストを指定する。リストの先頭からデータの転送を試みますが、
    // 失敗した場合は次のサーバーにアクセスします。
    masters {
        192.168.0.1;
        178.23.0.3;
    };
};
 
もっとも単純な named.conf ファイル
options {
    directory "/etc/nsdb";
};

// hint server (root chache)
zone "." in {
    type hint;
    file "named.root";
};

// for 
zone "foobar.co.jp." in {
    type master;
    file "foobar.zone";
};
 
// for reverse
zone "1.168.192.in-addr.arpa." in {
    type master;
    file "foobar.rev";
};
 
// for loopback
zone "localhost." in {
    type master;
    file "localhost.zone";
};
 
zone "0.0.127.in-addr.arpa." in {
    type master;
    file "localhost.rev";
};

最小限必要なものだけを取り上げましたが、この他にも acl などといった便利なステートメントがあります。詳細は、BIND 8のドキュメントを参照して下さい。

ゾーンファイル

ドメイン名が必要となるサービスなどを提供するホストのドメインについてのデータベースファイルを作成する。
ゾーンファイルの記述方法は、BIND 4 から拡張拡張はされているが、そのまま利用しても問題はない。 SOA レコードに記述する時間値に H(hour)、D(day)、W(week)、 M(month)などの略称が利用できます。

【正引きデータベースファイル: foobar.zone】
; BIND 8.2 以降、デフォルトの TTL 値を記述しておく必要があるみたい
$TTL 86400
@       IN SOA      ns.foobar.co.jp. postmaster.foobar.co.jp. (
        199912131   ; シリアル
        10800       ; リフレッシュ   < 3 時間  3H と記述しても良い >
        3600        ; リトライ       < 1 時間 >
        360000      ; 期限切れ       < 100 時間 >
        86400       ; TTL            < 1日 1D と記述しても良い >
        )
 
        IN NS       ns.foobar.co.jp.
        IN NS       ns.baz.ne.jp.
;
        IN MX 10    mail.foobar.co.jp.
        IN MX 20    mail.baz.ne.jp.
;
; Name Server
ns      IN A        192.168.1.1
        HINFO       "Ultra SPARC" "Solaris 7"
;
; Mail Server
mail    IN A        192.168.1.2
pop     IN CNAME    mail
;
; Network Service Server
www     IN A        192.168.1.5
ftp     IN CNAME    www
 
【逆引きのデータベースファイル: foobar.rev】
; BIND 8.2 以降、デフォルトの TTL 値を記述しておく必要があるみたい
$TTL 86400
@       IN SOA      ns.foobar.co.jp. postmaster.foobar.co.jp. (
        199912131   ; シリアル
        10800       ; リフレッシュ   < 3 時間  3H と記述しても良い >
        3600        ; リトライ       < 1 時間 >
        360000      ; 期限切れ       < 100 時間 >
        86400       ; TTL            < 1日 1D と記述しても良い >
        )
;
        IN NS       ns.foobar.co.jp.
        IN NS       ns.baz.ne.jp.
;
1       IN PTR      ns.foobar.co.jp.
2       IN PTR      mail.foobar.co.jp.
5       IN PTR      www.foobar.co.jp.
 
【ループバック用正引きのデータベースファイル: local.zone】
; BIND 8.2 以降、デフォルトの TTL 値を記述しておく必要があるみたい
$TTL 86400
@       IN SOA      ns.foobar.co.jp. postmaster.foobar.co.jp. (
        199912131   ; シリアル
        10800       ; リフレッシュ   < 3 時間  3H と記述しても良い >
        3600        ; リトライ       < 1 時間 >
        360000      ; 期限切れ       < 100 時間 >
        86400       ; TTL            < 1日 1D と記述しても良い >
        )
        IN NS       ns.foobar.co.jp.
;
localhost. IN A     127.0.0.1
 
【ループバック用逆引きのデータベースファイル: local.rev】
; BIND 8.2 以降、デフォルトの TTL 値を記述しておく必要があるみたい
$TTL 86400
@       IN SOA      ns.foobar.co.jp. postmaster.foobar.co.jp. (
        199912131   ; シリアル
        10800       ; リフレッシュ   < 3 時間  3H と記述しても良い >
        3600        ; リトライ       < 1 時間 >
        360000      ; 期限切れ       < 100 時間 >
        86400       ; TTL            < 1日 1D と記述しても良い >
        )
        IN NS       ns.foobar.co.jp.
;
1       IN PTR      localhost.

上記レコードの型(type)の概略を簡単に記述します。

SOA

SOA (Start of Authority)レコードは、ゾーン管理の開始であることを意味します。
@ の部分は、本来ならドメイン名が入ります。 もし、@ と記述されている場合(ほとんどの場合 @ です)、named.conf に記述されたドメイン名(foobar.co.jp)が記述されているのと同じ意味になります。逆引のゾーンファイルに記述されている @ は、named.conf に記述された「1.168.192.in-addr.arpa」と同じ意味になります。
SOA には続いて、ネームサーバのホスト名、連絡者のメールアドレス(@を . に置き換えたもの)が入ります。

シリアル ゾーンファイルのシリアル番号です。いつ修正したかわかるように、西暦日付+修正回数のような意味で YYYYMMDDR のように記述していますが、1 から始まっても構いません。ただし、忘れてはならないのが、このゾーンファイル(逆引きファイルも含む)を修正した場合、このシリアル番号に +1 以上加算する必要があります。slave サーバーは、master のシリアル番号を見てキャッシュの内容を更新します。そのため、ゾーンファイルを書き換えても、このシリアル番号をあげ忘れると slave サーバのデータは更新されません。シリアル番号の上げ忘れには、十分に注意してください。また、ネームサーバーに HUP シグナルを送ることも忘れてはいけません。ここで、ちょっと気になるのがシリアル番号は無限ではないということです。そのため、RFC 1982 にシリアル番号の計算方法の記述があります。要約すると、シリアルが限界に達した場合、最初に戻る(1の方が大きくなる)ということです。

リフレッシュ

どのくらいの頻度(時間の間隔)でデータの正確さを master に確認しにいくかを、slave に対して指定する。

リトライ slave サーバが master サーバにアクセスしても応答がない場合に、slave サーバが master サーバへのアクセス をリトライする時間の間隔です。
期限切れ ここで指定された期間以内に slave サーバが master サーバにアクセスできなかった場合、slave サーバはそのゾーンについてのデータを全て破棄します。破棄された後に、slaveサーバに対してゾーンについて問い合わせがあっても slaveサーバは回答しません。期限切れの時間は、リトライ時間やリフレッシュ時間よりも長く設定しなければなりません。
TTL

TTL(Time To Live:生存時間) :リソースレコードをキャッシュに保持できる最小時間を設定します。 ホストごとに明示的に TTL を設定したい場合;

www    90000 IN A    192.168.1.5

のように IN の前に指定します。

NS

NS (Name Server)レコードは、ドメインに対して認証されたネームサーバを指定します。本来 IN の前には、ネームサーバによって保持されているドメイン名(foobar.co.jp)のゾーンデータを記述します。しかし、省略するができます。省略した場合、直前のレコードと同じものを指定していることになります。(ここでは、直前の SOA レコードの @ つまり foobar.co.jp が入ります)。 省略せずに記述した場合、以下のようになります。

foobar.co.jp.  IN NS       ns.foobar.co.jp.

注意しなければならないことに、最後が . (ピリオド) で終わっている必要があるということです。もし foobar.co.jp のようにピリオドがない場合、named は、foobar.co.jp.foobar.co.jp と補完してしまいます。

MX

MX (Mail Exchange)レコードは、ドメイン名に対するメール交換を行うホストを指定します。MXレコードは、ドメイン名に対して優先値とメールサーバのホスト名を持っています。この優先値が小さいメールサーバから、メールの送信を試みます。

A

A (Address)レコードは、ホスト名に対応する IP アドレスを記述します。DNS を利用する目的である、IP アドレスと名前の関連づけるために必要なレコードが A レコードです。
上記の例では ns というマシン名ですが、ピリオドが省略されているので 192.168.1.1 という IP アドレスは ns.foobar.co.jp という名前が関連づけられます。

HINFO

HINFO (Host Information)レコードは、利用している CPU や OS などの情報を記述します。といっても、あまり詳しくこの情報を記述すると、「こんなマシンを使っているのか...」とわかってしまいハッキングの対象にされやすくなることがあります。社内専用のネームサーバの場合、有効的なレコードとなるでしょう。

CNAME

CNAME (Canonical Name)レコードは、別名を指定する際に利用します。
A レコードに記述されるホスト名が正式名となるが、そのホストに別名を付けたい場合に CNAME レコードを使用します。メールサーバーは、何かと情報がメールのヘッダに付くので CNAME で与えた名前を設定せずに A レコードで記述したほうが良い。

PTR

PTR (Pointer)レコードは、IP アドレスに対応するドメイン名を記述します。
上記の例では、クラスC の IP アドレスであるため 192.168.1.1 の最後の 1 だけ記述されています。もし、クラス B の IP アドレスの場合、アドレスが 172.114.10.3 であっらなら RFC 1101 に従い 3.10 となります。このレコードの場合、 右側のホスト名を省略された形で書いてはいけない。これを ns と省略して書いてしまうと、補完して解釈するためホスト名が ns.1.168.192.in-addr.arpa となってしまうからです。さらに最後は .(ピリオド) で終わる必要があります。

resolv.conf

このファイルは、ホストがどのネームサーバを利用するか記述しておくものです。BIND 4 では、ネームサーバとなるホストはこのファイルは必要無かったが BIND 8 ではネームサーバも必要になります。

domain デフォルトドメインを設定することができます。ここで指定するドメイン名は、ピリオドやスペースで終わってはいけません。
search

デフォルトドメインを設定した時にできるデフォルトの検索リストを用いたく無い時に使用する。resolv.confには、domain命令とsearch命令のいずれか一方があれば良いのだが両方記述しても構いません。その場合、後に書かれた方が優先されます。

nameserver master, slave といったネームサーバについて記述しました。しかし、ネームサーバは動かしたくないけど DNSは利用したいようなホストがあると思います。全てのホストでネームサーバを動かすのはナンセンスですね。そんな時に、参照するネームサーバを指定するのが nameserver 命令です。

システムがネームサーバとして動作している場合、自分自信なので以下のように書きます。

    nameserver      127.0.0.1
    search          foobar.co.jp

* named の起動とテスト

各ファイルの設定が完了したら named を起動させ、きちんと名前が引けるかテストをします。通常は named をそのまま起動するだけですが、named.conf ファイルがデフォルトである /etc ディレクトリ以外にある場合 -b オプションで named.conf ファイルを指定して起動します。 起動後は、正常に起動しているかどうか syslog を必ず確認してください。

名前引きのテスト

nslookup を利用して、自分が設定したドメイン名が正しく引けるかどうかをテストします。

Default Server:  localhost
Address:  127.0.0.1
 
>
> www.foobar.co.jp.
Server:  localhost
Address:  127.0.0.1
 
Name:    www.foobar.co.jp
Address:  192.168.1.5
>
> 192.168.1.5
Server:  localhost
Address:  127.0.0.1
 
Name:    www.foobar.co.jp
Address:  192.168.1.5
>
> set type=mx
> foobar.co.jp.
Server:  localhost
Address:  127.0.0.1
 
foobar.co.jp        preference = 10, mail exchanger = mail.foobar.co.jp
mail.foobar.co.jp   internet address = 192.168.1.2
> 
> set type=ns 
> foobar.co.jp.
Server:  localhost
Address:  127.0.0.1
 
foobar.co.jp        nameserver = ns.foobar.co.jp
ns.foobar.co.jp     internet address = 192.168.1.1

* ちょっと IPv6

IPv6 になると、どのように記述するのか?と疑問が湧くかも知れませんが基本的にはかわりません。ただし、128ビットなので以下のようになります。A が従来の IPv4 のアドレスとなり、AAAA が IPv6 でのアドレスになります。

【正引き】
; IPv6 Sample
$TTL 86400
@               IN SOA ns.ipv6.foobar.co.jp. postmaster.ipv6.foobar.co.jp. (
                199912131   ; Serial (yyyymmddr)
                10800       ; Refresh 3 hours
                3600        ; Retry   1 hour
                360000      ; Expire  1000 hours
                86400)      ; Minimum 24 hours
                IN NS       ns.ipv6.foobar.co.jp.
                IN NS       ns.ipv6.baz.ne.jp.
;
localhost       IN A        127.0.0.1
;
newer           IN A        128.173.88.82
newer           IN AAAA     5F05:2000:80AD:5800:0058:0800:2023:1D71
                IN HINFO    UltraSPARC  Solaris7
                IN MX       100         mail.ipv6.foobar.co.jp.
;
older           IN A        128.173.88.83
older           IN AAAA     5F05:2000:80AD:5800:0058:0800:2023:2F8E
                IN HINFO    PDP11/80    UNIX
;
soso            IN A        128.173.88.78
soso            IN AAAA     5F05:2000:80AD:5800:0058:00AA:00B7:AF2B
                IN HINFO    P700        WIN2000
【逆引き】
; IPv6 Sample rev
$TTL 86400
;
@               IN SOA ns.ipv6.foobar.co.jp. postmaster.ipv6.foobar.co.jp. (
                199912131   ; Serial (yyyymmddr)
                10800       ; Refresh 3 Hours
                3600        ; Retry   1 hour
                3600000     ; Expire  1000 hours
                86400 )     ; Minimum 24 hours
                IN NS       ns.ipv6.foobar.co.jp.
                IN NS       ns.ipv6.baz.ne.jp.
;
1.7.d.1.3.2.0.2.0.0.8.0     IN PTR      newwer.ipv6.foobar.co.jp.
e.8.f.2.3.2.0.2.0.0.8.0     IN PTR      older.ipv6.foobar.co.jp.
b.2.f.a.3.2.0.2.0.0.8.0     IN PTR      soso.ipv6.foobar.co.jp.

* 注意点

最もよくありがちな問題について取り上げます。

シリアル番号を増やし忘れる ゾーンファイルを変更したのに、slave がその変更を感知しないことがある。これは、シリアル番号が同じであるため slave がゾーンデータに変更が無いと思ってしまうのです。これをチェックするには、シリアル番号を覚えている以外に、変更したかどうか知る方法はありません。最良の方法は、nslookup を使用して master と slave の返すデータを比較することです。
ネームサーバへ HUP シグナルを送り忘れる ネームサーバは、新しいデータを読み込まなければ変更に気が付きません。更新したゾーンファイルをネームサーバに読み込ませるには、HUPシグナルを送って下さい。
PTRレコードを加え忘れる Aレコードを加えるのは、ホストに追加に /etc/hosts を追加するのに慣れているので忘れることはないが、PTRレコードは忘れる時がある。PTRレコードを加え忘れると、そのホストの認証チェックが必要なrsh, rcpの実行の失敗につながります。 nslookup コマンドで、名前と IPアドレスによるチェックを行って下さい。
設定ファイルやゾーンファイルの文法エラー ネームサーバを起動した時にエラーがでなくても、syslog に出力されている可能性があるので注意して確認して下さい。
名前の最後に "." をつけ忘れる ゾーンファイルを編集している時、最後のピリオド"." をつけ忘れることがあります。正引きのゾーンファイル中のホスト名で、最後のピリオドが無い場合ものにはすべてドメイン名が付加さて解釈されます。ホスト名だけの記述なら構いませんが、ドメイン名まで指定してピリオドが無かった場合、二重にドメインが付いた名前となってしまいます。 
ヒント(キャッシュ)データが無い なんらかの原因でヒントデータが無かった場合、ネームサーバは自分が権威を持っているデータに含まれていない名前を解決することが出来ません。syslog中に "No root nameservers for class 1" といったようなエラーがあった場合、ヒントデータが無いことを意味します。
resolv.conf ファイルの文法エラー リゾルバは、resolv.conf の記述が間違っていてもエラーにならず無視してしまいます。そこで、resolv.conf の設定が正しいか nslookup コマンドを使用して確認して下さい。set all に対する出力が期待通りか調べて下さい。ドメイン名の後ろにスペースがあると、うまく動作しないことがあります。
デフォルトドメインが設定されていない デフォルトドメインが設定されていないと、ホスト名だけでは認識されないが、ドメイン名を含めると認識されるなどといった不具合が生じます。この問題は、nslookupコマンドの set all に対する出力で、ドメイン名やサーチリストが設定されていないことに気付くことで発見できます。