BIND で内部向け DNS サーバーを構築

  • 投稿日:
  • by
ついに自分で DNS サーバーを立てました。 今まで DNS 機能はルーターに任せていたのですが、ルーターに登録できる数が 32 で、そろそろ限界を感じていたところでした。
登録数が 30 になったのをきっかけに、勉強がてら自分で DNS サーバーを立てることにしました。
まぁ今では使ってないホスト名を削除すれば 32 という登録数で十分運用はできるんですけどねw

まずは、DNS サーバーとして使うソフトを何にしようかと考えました。BIND は言わずもがなデファクトスタンダードですが、小規模な内部ネットワークで使用するなら dnsmasq の方が使い勝手は良さそうだなとか。ただ、dnsmasq は多少扱ったことがあるのに対して、実は BIND はまともに使ったことがなかったので、ここは思い切って BIND にしようと決めたのでした。
なお、DNS サーバーを立てるのに使った OS は CentOS 5 です。

まずは BIND のインストール。
[root@host ~]# yum -y install bind bind-chroot caching-nameserver
BIND 設定ファイルのひな形を、そのまま設定ファイルとしてコピーします。
[root@host ~]# cp /var/named/chroot/etc/named.caching-nameserver.conf /var/named/chroot/etc/named.conf
所有グループを変更します。
[root@host ~]# chgrp named /var/named/chroot/etc/named.conf
設定ファイルを編集します。
[root@host ~]# vi /var/named/chroot/etc/named.conf
編集内容はこちら。コメントアウトや設定の追加を行いました。
options {
        #listen-on port 53 { 127.0.0.1; };
        #listen-on-v6 port 53 { ::1; };
        version         "unknown";
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";

        query-source    port 53;
        query-source-v6 port 53;
        allow-query     { localhost; localnets; };
        recursion       yes;
        forwarders {
                192.168.1.1;
        };
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

view localhost_resolver {
        match-clients      { localhost; };
        match-destinations { localhost; };
        recursion yes;
        include "/etc/named.rfc1912.zones";
        include "/etc/named.localnets.zones";
};

view "internal" {
        match-clients { localnets; };
        match-destinations { localnets; };
        recursion yes;
        include "/etc/named.rfc1912.zones";
        include "/etc/named.localnets.zones";
};
注目すべき点としては、まず forwarders の設定。自分の場合はルーターを経由させているので、ルーターの IP アドレスを設定しましたが、PPPoE 接続環境の場合にはプロバイダから通知された DNS サーバー(プライマリ、セカンダリ含む)の IP アドレスを設定します。

それと localhost_resolver と "internal" にゾーンファイルをインクルードしている点。ネットで検索すると、インクルードするファイルの名前として特定のドメイン名を使っていたりしますが、自分の場合はそうしませんでした。
自分は複数の内部ドメインを扱い、且つ、ゾーンファイルを個別に作ってインクルードするということはしないつもりなので、特定のドメイン名をもとにした名前でのファイルの作成は行いませんでした。

で、インクルードした named.localnets.zones ファイルを作成します。
[root@host ~]# vi /var/named/chroot/etc/named.localnets.zones
ファイルの中身はこんな感じ。自分の環境に合わせて編集してください。
自分の場合は、1.168.192.in-addr.arpa が逆引きゾーン設定、servered.net と local.domain は正引きゾーン設定になります。扱う内部ドメインを増やす場合には、同じ書式でゾーン名とゾーンデータベースファイル名を変更した設定を追加していきます。
zone "1.168.192.in-addr.arpa" {
        type master;
        file "1.168.192.in-addr.arpa.db";
};

zone "servered.net" {
        type master;
        file "servered.net.db";
};

zone "local.domain" {
        type master;
        file "local.domain.db";
};
で、内部向け正引きゾーンデータベースファイルを作成します。この作業は、登録するドメインごとに行います。
[root@host ~]# vi /var/named/chroot/var/named/servered.net.db
以下の内容はサンプルとなり、実際に運用しているものとちょっとだけ違いますがご容赦ください。
$TTL    86400
@       IN      SOA     ns.servered.net.  master.servered.net. (
                                        2009051101 ; Serial
                                        28800      ; Refresh
                                        14400      ; Retry
                                        3600000    ; Expire
                                        86400      ; Minimum
)

        IN NS    ns.servered.net.
@       IN A     192.168.1.100
host    IN A     192.168.1.100
www     IN CNAME host.servered.net.
blog    IN CNAME host.servered.net.
正引きゾーンデータベースファイルをすべて作り終えたら、逆引きゾーンデータベースファイルを作成します。
[root@host ~]# vi /var/named/chroot/var/named/1.168.192.in-addr.arpa.db
内容はこんな感じ。基本的な内容は正引きと同じですね。
$TTL    86400
@       IN      SOA     ns.servered.net.  master.servered.net. (
                                        2009051101 ; Serial
                                        28800      ; Refresh
                                        14400      ; Retry
                                        3600000    ; Expire
                                        86400      ; Minimum
)

        IN NS    ns.servered.net.
100     IN PTR   servered.net.
110     IN PTR   local.domain.
ゾーンデータベースファイルの設定内容は、BIND を扱う場合において一番難解な箇所になると思います。
設定例は上記の通りとして、ここでは、各レコードの意味を書き留めておきます。
主な DNS レコードの種類
レコード種別 意味
SOA Serial(シリアル番号) ゾーン転送時に情報が更新されているかどうかの判断に用いられる。番号は任意だが、「年月日+連番」の書式が多く用いられる。
Refresh(更新間隔) ゾーン情報のゾーン転送間隔時間。秒単位で指定する。
Retry(転送再試行時間) ゾーン転送に失敗した場合の再試行までの猶予時間。秒単位で指定する。
Expire(レコード有効時間) ゾーン情報を最新と確認できない場合の有効時間。秒単位で指定する。
TTL(キャッシュ有効時間) ゾーン情報をキャッシュする場合の有効時間。秒単位で指定する。
NS ドメインの DNS サーバー名。
A ホストの IP アドレス。
PTR IP アドレスに対するホスト名。
CNAME ホスト名のエイリアス(別名)。
MX ドメインのメールサーバー名。
で、BIND を起動させる訳ですが、その前に念のためルートゾーンの情報を更新しておきます。
[root@host ~]# dig . ns @198.41.0.4 > /var/named/chroot/var/named/named.ca
また、おまけとして、ルートゾーンが最新か月に 1 度チェックし、最新でない場合には更新と BIND の再起動を自動的に行うスクリプトを作成しておくと便利です。
[root@host ~]# vi named.root_update
そのスクリプトの内容は以下となります。ちなみに完璧なパクリですw
なお、ルートゾーンが更新されていた場合のみ、新旧のルートゾーン情報に加え差分情報を root 宛にメールする機能も含まれています。
#!/bin/bash

new=`mktemp`
errors=`mktemp`

dig . ns @198.41.0.4 > $new 2> $errors

if [ $? -eq 0 ]; then
    sort_new=`mktemp`
    sort_old=`mktemp`
    diff_out=`mktemp`
    sort $new > $sort_new
    sort /var/named/chroot/var/named/named.ca > $sort_old
    diff --ignore-matching-lines=^\; $sort_new $sort_old > $diff_out
    if [ $? -ne 0 ]; then
        (
         echo '-------------------- old named.root --------------------'
         cat /var/named/chroot/var/named/named.ca
         echo
         echo '-------------------- new named.root --------------------'
         cat $new
         echo '---------------------- difference ----------------------'
         cat $diff_out
        ) | mail -s 'named.root updated' root
        cp -f $new /var/named/chroot/var/named/named.ca
        chown named. /var/named/chroot/var/named/named.ca
        chmod 644 /var/named/chroot/var/named/named.ca
        /etc/rc.d/init.d/named restart > /dev/null
    fi
    rm -f $sort_new $sort_old $diff_out
else
    cat $errors | mail -s 'named.root update check error' root
fi
rm -f $new $errors
で、スクリプトに実行権限を付加し、cron.monthly に移動します。
[root@host ~]# chmod 700 named.root_update
[root@host ~]# mv named.root_update /etc/cron.monthly/
少し横道に逸れましたが、最後の仕上げとして BIND を起動します。
[root@host ~]# service named start
named を起動中:                                            [  OK  ]
サーバーを再起動したときに自動的に BIND が起動するようランレベルを設定します。
[root@host ~]# chkconfig named on
[root@host ~]# chkconfig --list named
named           0:off   1:off   2:on    3:on    4:on    5:on    6:off
以上です。とっても難解でしたが、何とか実稼働することができました。お疲れ様でした!

参考にしたリンク