BINDの構築とDNS名前空間の概要

CentOS7 への BIND の構築方法をご紹介します。といっても、「yum install bind」を実行してしまえばインストールは完了してしまうので、その先の話として、DNSの仕組みを理解する目的も含めて以下の構成を BIND で構築することを最終目標とします。

192.168.0.200 のサーバを tech.yamashiro.blog. として定義し、クライアントPC から名前解決ができることをゴールとします。

dig

DNS の名前解決をテストするコマンドとして「dig」があります。dig は nslookup や host と違って、入手したレコードをほぼそのまま出力するのでデバッグには最適です。

ただし、dig は少なくとも CentOS7.4 にはデフォルトでインストールされていないので、「yum install bind-utils」でインストールしておくとトラブルシューティングがやり易いので導入することをお勧めします。

Windows にも dig は標準で実装されていません。インストールは可能ですが、Linux のようにコマンド1つで、とはいきません。

BIND はフルサービスリゾルバ(以下フルリゾルバ、もしくはキャッシュサーバ)と権威サーバ両方の機能を持っているため、その両方の機能を1台のDNSサーバが担うことも可能です。

しかし、フルリゾルバと権威サーバの論理的な置き場所が異なる(社内とDMZ等)事に起因するセキュリティ上の問題が発生するため、一般的には1台のサーバでフルリゾルバと権威サーバを同時に稼働させることはありません。

構築に入る前に基本的な要素を1点だけ覚えておいてください。フルリゾルバ役と権威サーバ約の両方の named サービスが起動していないと、この検証は失敗します。当たり前と思うかもしれませんが、named はインストール時点で start していないので、意外とはまりがちです。また、検証においては Firealld と SELINUX は無効にしておくことをお勧めします。

長くなりましたが、まずは BIND をフルリゾルバにする方法からご紹介します。なお、BIND のバージョンは「bind-9.11.4-16.P2.el7_8.6.x86_64」を使用しています。

Linux をルータにする方法

Virtualbox などで別ネットワークの検証をする場合、Windows もしくは Linux をルータとして動作させる必要があります。CentOS をルータにするには「/etc/sysctl.conf」に「net.ipv4.ip_forward=1」を追記します。

「cat /proc/sys/net/ipv4/ip_forward」の結果が “1” だった場合フォワーディングが有効なので簡易的なルータとして扱えます。”0″ だった場合は「service network restart」を実行します。

BIND をキャッシュサーバにする

BIND はデフォルトだとキャッシュサーバとして動作しません。以下は BIND インストール直後の /etc/named.conf の内容です。

options {
        listen-on port 53 { 127.0.0.1; };
        listen-on-v6 port 53 { ::1; };
        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";
        recursing-file  "/var/named/data/named.recursing";
        secroots-file   "/var/named/data/named.secroots";
        allow-query     { localhost; };

        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;

        bindkeys-file "/etc/named.root.key";

        managed-keys-directory "/var/named/dynamic";

        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";
};

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

zone "." IN {
        type hint;
        file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

上記の2行を修正し、1行を追加するだけでフルリゾルバとして機能します。それが以下です。

listen-on port 53 {127.0.0.1; 192.168.0.1};
dnssec-validation no;
allow-recursion { any; };

listen-on に関しては行を削除しても動作しますが、その場合 namedはホストに割り当てられたすべてのアドレスをリッスンします。

フルリゾルバの dnssec-validation は no にしないと ANSER SECTION が返ってきません。DNSSEC 関連の設定なので、セキュリティ的には勿論 yes の方がいいのですが、話を単純化するために今回は no に設定します。

allow-recursion が再帰問い合わせの受付を制限するオプションですが、今回は any としているため所謂オープンリゾルバ状態です。実環境では制限してください。

パブリックDNS

管理者がセキュリティ対策を実施したうえで、意図的にオープンな状態にしているものをパブリックDNSと言います。

代表的なパブリックDNSとして「Google Public DNS(8.8.8.8/8.8.4.4)」「Quad9(9.9.9.9/149.112.112.112)」「1.1.1.1(1.1.1.1/1.0.0.1)」があります。

なお、前述したように named サービスの start と Firealld、SELINUX の無効化は必ず実行してください。named が動いていない場合再帰問い合わせが行われません。Firealld が有効になっている場合、サーバからの dig は成功するけどクライアントから nslookup が失敗する、などということになる可能性が高いです。

named.conf の正常性を確認する

BIND には設定ファイルである named.conf の書式が間違っていないかをチェックするコマンドとして「named-checkconf」があります。

[root@localhost ~]# named-checkconf
/etc/named.conf:21: missing ';' before '}'

上記のように引数無しで実行し、問題が無ければ何も出力されず、問題があればこのように間違いを教えてくれます。named が何故か start できないといった場合に named-checkconf を実行すると、単純に書式が間違っていたなどということもままあります。

ルートヒントの編集

「/var/named/named.ca」がルートヒント(ヒントファイル)です。ここでは検証のために A~M までのルートサーバを削除し、以下のように Y ルートサーバを追加しました。

;; QUESTION SECTION:
;. IN NS
;; ANSWER SECTION:
. 518400 IN NS y.root-servers.net.
;; ADDITIONAL SECTION:
y.root-servers.net. 518400 IN A 10.0.0.1

これで、フルリゾルバは再帰問い合わせのはじまりとして”10.0.0.1″のルートネームサーバ役のサーバに問い合わせを始めるようになります。

BIND を権威サーバにする

今回の検証では権威サーバは3台必要です。「.(ルート)」「blog.」「yamashiro.blog.」というゾーンをそれぞれ管理します。まずはルートネームサーバから設定します。

ルートネームサーバ

ルートネームサーバ役の /etc/named.conf で以下の設定を行います。

listen-on port 53 { 127.0.0.1;10.0.0.1; };
allow-query { any; };
/*
zone "." IN {
        type hint;
        file "named.ca";
};
*/
zone "." IN {
        type master;
        file "root.zone";
};

ルートゾーン用のファイルを /var/named/root.zone として作成します。root で作成すると所有ユーザ/所有グループが root/root となります。そのままでも動きますし、named.ca と同じように root/named としても動きます。

そして以下がゾーンファイルとなります。

$ORIGIN                 .
$TTL                    3600
@                       IN      SOA (
                        ns1.            ; MNAME
                        postmaster.     ; RNAME
                        2019062301      ; SERIAL
                        3600            ; REFRESH
                        900             ; RETRY
                        604800          ; EXPIRE
                        3600            ; MINIMUM
                        )
                        IN       NS      ns1
blog                    IN       NS      ns1.blog
ns1                     IN       A       10.0.0.1
ns1.blog                IN       A       172.16.0.1

ゾーンファイルの書き方は RFC で定義されており、以下のようなルールがあります。

  1. 前行と同じドメイン名は省略可能
  2. 前行と同じクラスは省略可能
  3. $TTL ディレクティブを設定することでゾーン内のデフォルトTTLが設定されるため、各リソースレコードでのTTLを省略可能
  4. $ORIGIN ディレクティブでゾーンファイル中のオリジン(相対ドメイン名を設定した際に補完されるドメイン名)を設定可能
  5. オリジンと同じドメイン名は”@”で省略可能
  6. ドメイン名のフィールド末尾が”.”ではない場合、相対ドメインとなり $ORIGIN で設定されたドメイン名が末尾に補完される

なお、$ORIGIN を省略した場合は、/etc/named.conf の zone ステートメントで指定したドメイン名で補完されます。IN を省略した場合は、同じく /etc/named.conf の zone ステートメントで指定したクラスが適用されます。

全てのゾーンファイルは基本的に SOA レコードと自分自身の NS レコード、そして委任した子ドメインの NS レコード、それらのグルーレコードである A レコードで構成されます。

SOA レコードのそれぞれの値には以下のような意味があります。

MNAMEゾーンを管理するプライマリサーバのホスト名。
RNAME管理者のメールアドレス。@ を . に置き換えて記述する。
SERIALゾーン情報のバージョン(一般的には更新年月日8桁+通番2桁)。ゾーンを更新した場合、前のシリアル値より大きな数になるよう値を更新する。
REFRESHゾーン情報の更新タイミング。セカンダリサーバは前回の更新からこの時間が経過すると自発的に更新を確認する。
RETRYゾーン情報の更新が失敗した際に、再度更新を試みるまでの待ち時間。
EXPIREゾーン情報の更新は成功するまで繰り返すが、この時間内に成功しなかった場合は持っているゾーン情報を期限切れにする。この状態になった場合、一切の応答を返さない。
MINIMUMフルリゾルバがネガティブキャッシュを保持していい時間。

SOA レコードのゾーンのホスト名と管理者のメールアドレスは以下のように定義することもできます。

@ IN SOA ns1. postmaster. (

どちらかと言うとこちらの書き方の方が主流かもしれません。

SOA レコードは本当に必須なのか

ゾーンファイルの構文を確認するコマンドに「named-checkzone」コマンドがあります。ゾーンファイルに SOA レコードが無い状態でこのコマンドを実行すると以下のような結果になります。なお、「named-checkconf」は引数が不要ですが、named-checkzone は引数としてドメインとゾーンファイが必要です。

[root@localhost named]# named-checkzone blog /var/named/blog.zone
zone blog/IN: has 0 SOA records
zone blog/IN: not loaded due to errors.

SOA レコードはゾーン転送しない場合は不要と思われがちですが、必須レコードのひとつです。なお、BIND では SOA レコードは必ずリソースレコードの先頭に書かなくてはならないという決まりがあります。

TLD ネームサーバ

次は blog. のネームサーバです。/etc/named.conf は以下のようになります。

listen-on port 53 { 127.0.0.1;172.16.0.1; };
allow-query { any; };
zone "blog" IN {
        type master;
        file "blog.zone";
};

そしてゾーンファイル /var/named/blog.zone は以下のようになります。

$ORIGIN                 blog.
$TTL                    3600
@                       IN      SOA (
                        ns1.blog.
                        postmaster.blog.
                        2019062301
                        3600
                        900
                        604800
                        3600
                        )
                        IN       NS      ns1
yamashiro               IN       NS      ns1.yamashiro
ns1                     IN       A       172.16.0.1
ns1.yamashiro           IN       A       192.168.0.1

SLD ネームサーバ

最後に yamashiro.blog. のネームサーバです。/etc/named.conf は以下のようになります。

listen-on port 53 { 127.0.0.1;192.168.0.1; };
allow-query { any; };
zone "yamashiro.blog" IN {
        type master;
        file "yamashiro.blog.zone";
};

そしてゾーンファイル /var/named/yamashiro.blog.zone は以下のようになります。

$ORIGIN         yamashiro.blog.
$TTL            3600
@                       IN      SOA (
                        ns1.yamashiro.blog.
                        postmaster.yamashiro.blog.
                        2019062301
                        3600
                        900
                        604800
                        3600
                        )
                        IN       NS      ns1
ns1                     IN       A       192.168.0.1
tech                    IN       A       192.168.0.200

yamashiro.blog. はドメイン名前空間の最下層なので、子ドメインの NS レコードはありません。変わりに tech という A レコードを用意しました。この tech.yamashiro.blog. の名前解決ができるかを最後にテストします。

名前解決テスト

最後にクライアントからの名前解決をテストします。結果は下図のように成功です。

このように、ローカル環境で最も単純なドメイン名前空間を再現することができると DNS の理解がより深まります。最終的には以下のような名前空間となりました。

なお、DNS キャッシュの削除方法は Windows だと「ipconfig /flushdns」、BIND だと「rndc flush」です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)