ローカル(LAN内)に内部用DNSがあり、それとは別にグローバルに自ドメインの権威サーバがある場合、ローカルDNSとグローバルDNSで同じドメイン名のゾーンが存在する場合のちょっとしたTipsです。

 想定している環境

LAN内に内部用DNS、設定は自ドメインのゾーン(ローカル用)を持っているが、基本的にはキャッシュサーバとして運用しています。また、外部ドメインの名前解決はISPから提供されているDNSへ forward するという設定です。

options {
        directory "/var/cache/bind";
        forwarders {
                202.xxx.2.3;                  // ISPから指定されているDNS
                202.xxx.2.2;
        };
        forward only;
        auth-nxdomain           no;           // conform to RFC1035
        listen-on-v6            { any; };
        ixfr-from-differences   yes;
        max-ncache-ttl          3600;         // 3600sec=1h
};

グローバル側にはWebサーバやMXとなるSMTPサーバのIPアドレス等、外部からのアクセスに必要なDNSサーバを置いています。これは基本的には権威サーバですので、自ドメインに関する問い合せだけに返答します。つまり、recursion no; に設定されています。

 Tipsの内容

1の環境において、LAN環境からグローバル用DNSに書いてあるホスト名を参照するにはどうしたらよいでしょう?
例えば、www.example.com のIPアドレスが10.0.0.1(グローバルIPアドレスとします)とグローバルDNSに書いてある場合、LAN環境からアクセスすると内部DNSを参照しますので、グローバルとローカルで同じドメイン名を使っていれば、当然内部DNSにも example.com のゾーン情報があるので、そこに www があれば内部DNSから返事がありますし、無ければ Host www not found という返事となります。

最も簡単な対応は、内部DNSに www のIPアドレス(10.0.0.1)を書いておくことです。 ローカルDNSとグローバルDNS、共に同じ管理者が担当していれば、これが一般的でしょう。 しかし、レンタルサーバ等を使っていて、グローバルDNSは別の会社(担当者)が管理している状況だと、同じような方法では問題が出ることがあります。

管理者が違うという事は、いつゾーン情報が変更されるか、わからないと言うことです。 内部DNSではAレコードで直接グローバルIPアドレスを設定しているので、グローバルDNS内のゾーン情報が変更になったら手動でAレコードの書き換えが必要になります。

手動の設定作業を無くすには、内部DNSに対してグローバルDNSに書かれているホスト名を尋ねられたら、内部DNSのゾーン情報から返事をするのではなく、グローバルDNSへクエリを転送し、その結果をクライアントへ返答すればうまくいくでしょう。

このような動作をさせるのは、下記の様にNSレコードを内部DNSのゾーンファイルに記載します。

例: example.com のグローバルDNSに、www は10.0.0.1と書いてあったとします。また、example.com のグローバル側の権威DNSはns1.example-isp.com, ns2.example-isp.com とします。

www        IN NS    ns1.example-isp.com.
           IN NS    ns2.example-isp.com.

このようにグローバル側のDNSを参照させたいホスト名は、グローバルDNSが動いている権威サーバー名をNSレコードとして内部DNSのexample.com のゾーンファイルに設定します。 つまり、ローカルのDNSのゾーン情報にはNSレコードだけを記載し、Aレコードは書かないという事です。
※自ドメイン以外のホスト名をNSレコードに設定する時は、ホスト名の最後にドットを付けることを忘れないでください。

 Attention

この設定方法はちょっとトリッキーなやり方なので、自環境で正常に動作するかどうか良く検証することをお勧めします。 内部DNSのゾーンファイルにはNS レコードしか存在しないホスト名ですが、nslookup, dig, ping 等で使っても正常にグローバルIPアドレスが使われます。

ただし、hostコマンドを使うと…

# host www
www.example.com has address 10.0.0.1
Host www.example.com not found: 2(SERVFAIL)
Host www.example.com not found: 2(SERVFAIL)

このような返事が来ますので、注意してお使いください。

 検証環境

ローカルDNS
Linux kernel 3.2.0-4-686-pae wheezy
bind9 1:9.8.4.dfsg.P1-6+nmu2+deb7u7

グローバルDNS
Linux kernel 2.6.35.4 squeeze
bind9 1:9.7.3.dfsg-1~squeeze17

Have a nice day !!

 追記 2015/10/26

上記の方法はbindでダイナミックDNSを動かしているときでも有効です。 しかし、MicrosoftのDNSで同じような事が出来るかどうかは未検証ですのでご注意ください。