【BIND9講座 第8回】内と外で世界を変えろ!「View」機能で作るスプリットDNS(内外分離)の構築術

「どこにいるか」で答えを変える魔法

こんにちは!「リナックス先生」です。
BIND9講座、第8回へようこそ。

これまでの講座で、あなたのDNSサーバーはかなり立派になりました。
しかし、Web担当者や社員から、こんなワガママな要望が飛んできたことはありませんか?

「社内にいる時は高速なLAN経由でサーバーに繋ぎたいけど、外出中はインターネット経由で同じサーバーに繋ぎたい。でもURLは変えたくない!」

通常、ドメイン名に対するIPアドレスは1つです。
しかし、BINDの「View(ビュー)」機能を使えば、まるでパラレルワールドのように、アクセスしてきた相手に合わせて「全く違うDNS情報」を見せることができるのです。

これを「スプリットDNS(Split-Horizon DNS)」と呼びます。
非常に便利な機能ですが、導入するには named.conf を根底から書き換える必要があります。
今回は、BIND運用における最大の難所とも言えるこの「View化」に挑みましょう!

コウ君

先生、それ欲しかったです!
家のサーバー、外からスマホで見る時はグローバルIPで、家の中でWi-Fi使ってる時はプライベートIPで繋ぎたくて、いちいちWi-Fi切ったりしてました。
でも「大工事」って…また設定ファイル全部消すんですか?(涙)

リナックス先生

消しはしないけど、構造がガラッと変わるわ。
Viewを使うには「全てのゾーン定義をViewの中に入れなければならない」という厳しいルールがあるの。
一つでもはみ出しているとエラーで起動しなくなるわよ。慎重に行きましょう!

1. View機能の仕組みと「絶対ルール」

View機能とは、named.conf の中に仮想的な「仕切り」を作る機能です。

仕組みのイメージ

  • View “internal”(内部用):
    「社内の人(ACL: trusted)」が来たらこっち。
    再帰問い合わせOK、プライベートIPを返す。
  • View “external”(外部用):
    「それ以外の人(世界中)」が来たらこっち。
    再帰問い合わせNG(セキュリティ)、グローバルIPを返す。

BINDは、上から順番にViewの条件(match-clients)をチェックし、最初に合致したViewの設定だけを適用します。

【最重要】View化の絶対ルール

ここテストに出ます。
「Viewを一つでも定義したら、全ての zone 定義は、いずれかの view { ... }; ブロックの中に入っていなければならない」

これまで書いてきた zone "."(ルートヒント)や zone "kou-house.lan" が、Viewの外側にポツンと残っていると、構文エラーになります。
これが初心者がハマる最大の落とし穴です。

2. シナリオと設計

今回は、以下の構成を目指します。

項目 内部向け (Internal) 外部向け (External)
対象者 社内LAN (trusted ACL) それ以外すべて (any)
キャッシュ機能 許可 (recursion yes) 拒否 (recursion no)
返すIP 192.168.1.10 (プライベート) 203.0.113.10 (グローバル)
ゾーンファイル kou-house.lan.db kou-house.lan.external.db

※外部用のグローバルIP(203.0.113.10)は例です。ご自身のVPS等のIPに読み替えてください。

3. named.conf の大改造

それでは、手術を開始します。
バックアップを取ってから挑んでください。

sudo cp /etc/named.conf /etc/named.conf.bak_vol7
sudo vi /etc/named.conf

以下のように書き換えます。
既存の zone 定義を包み込むように書くのがコツです。

▼named.conf(View化後の構成)

# ACL定義(前回と同じ)
acl "trusted" {
    127.0.0.0/8;
    192.168.1.0/24;
};

options {
    listen-on port 53 { any; }; # 外部からも受けるのでany推奨
    directory       "/var/named";
    # allow-query 等は各Viewの中で書くのでここでは削除してもOK
    # ただしグローバルな設定として残す場合もある
};

# ---------------------------------------------------------
# 1. 内部向けビュー (Internal)
# ---------------------------------------------------------
view "internal" {
    # 条件: 信頼できるネットワークからのアクセス
    match-clients { trusted; };
    
    # 内部向けの設定
    recursion yes;            # キャッシュ機能ON
    allow-recursion { trusted; };

    # ルートヒント(キャッシュ機能に必要)
    zone "." IN {
        type hint;
        file "named.ca";
    };

    # 内部向け正引きゾーン
    zone "kou-house.lan" IN {
        type master;
        file "kou-house.lan.db";
    };

    # 内部向け逆引きゾーン
    zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "1.168.192.in-addr.arpa.db";
    };
};

# ---------------------------------------------------------
# 2. 外部向けビュー (External)
# ---------------------------------------------------------
view "external" {
    # 条件: 上記以外すべて(any)
    match-clients { any; };
    
    # 外部向けの設定(超重要:オープンリゾルバ対策)
    recursion no;             # キャッシュ機能OFF!
    allow-query { any; };     # 質問は誰からでも受ける

    # 外部向け正引きゾーン
    # ※ファイル名を「external」に変えている点に注目!
    zone "kou-house.lan" IN {
        type master;
        file "kou-house.lan.external.db";
    };
    
    # ※外部向けに逆引きやルートヒントは通常不要
    # 自分が持っているドメインのことしか答えないため
};

【解説ポイント】

  • match-clients: ここで振り分けを行います。internaltrusted にマッチしなかった人が、次の external (any) に落ちてくる仕組みです。
  • recursion no: 外部向けViewでは、絶対に再帰問い合わせをOFFにします。これで「外部には権威サーバーとしてのみ振る舞う(=自分のドメインのことしか答えない)」安全な構成になります。
  • zone “.”: ルートヒントは「キャッシュサーバー(調べる人)」として動くInternal ViewにだけあればOKです。

4. 外部用ゾーンファイルの作成

named.conf で指定した外部用ファイル kou-house.lan.external.db を作成します。
既存の内部用ファイルをコピーして修正するのが早いです。

4-1. ファイルのコピー

cd /var/named/
sudo cp -p kou-house.lan.db kou-house.lan.external.db

-p オプションで所有権(root:named)を維持します。

4-2. 内容の修正

外部から見える情報(グローバルIP)に書き換えます。

sudo vi kou-house.lan.external.db

▼修正例

$TTL 86400
@   IN  SOA     ns1.kou-house.lan. root.kou-house.lan. (
            2026011701  ; Serial (Internalとは別に管理!)
            3600
            900
            604800
            86400 )

    IN  NS      ns1.kou-house.lan.

; 外部公開するサーバーだけを書く!
; プライベートIP (192.168...) は絶対に書かない!
ns1     IN  A       203.0.113.10  ; グローバルIP
web     IN  CNAME   ns1
; router や pc など、外部に見せたくないものは削除する

【プロの注意点】
内部用と外部用は「全く別のファイル」です。
シリアル番号も別々に管理されます。
「内部には router があるけど、外部には見せない」といった情報の出し分けができるのがViewの強みです。

5. 構文チェックと反映

構造を大きく変えたので、いつも以上に念入りにチェックします。

5-1. 全体チェック

sudo named-checkconf

エラーが出た場合、一番多いのは「view の外側に zone 定義が残っている」ミスです。
include "/etc/named.rfc1912.zones"; のような行も、どれかのViewの中に入れるか、削除する必要があります。

5-2. 外部ゾーンのチェック

sudo named-checkzone kou-house.lan /var/named/kou-house.lan.external.db

5-3. 再起動

sudo systemctl restart named

構造変更時は reload ではなく restart の方が確実です。

6. 動作テスト:パラレルワールドの確認

さあ、正しく「2つの顔」を使い分けられているか確認しましょう。
dig コマンドはアクセス元IPを変えることはできませんが、サーバー側のACLを一時的にいじることで擬似的にテストできます。

テスト①:内部からのアクセス(通常)

サーバー自身(127.0.0.1)は trusted ACLに含まれているため、Internal View が適用されるはずです。

dig @127.0.0.1 ns1.kou-house.lan

結果: 192.168.1.10 が返ってくれば正解(内部の世界)。

テスト②:外部からのアクセス(疑似)

本当に外部(スマホの4G回線など)から dig できればベストですが、難しい場合は named.conf のACLを一時的に書き換えて確認します。

# 一時的に 127.0.0.1 を trusted から外す
acl "trusted" {
    # 127.0.0.0/8;  ← コメントアウト
    192.168.1.0/24;
};

再起動して、もう一度同じコマンドを打ちます。

dig @127.0.0.1 ns1.kou-house.lan

結果: 今度は 203.0.113.10 が返ってくれば大成功!(外部の世界)

確認後は必ずACLを元に戻してください。

コウ君

すごい…!
同じ名前を聞いてるのに、設定一つで答えが変わるなんて魔法みたいです。
これで「URLは同じまま、家でも外でも繋がる」環境が作れますね!
recursion を外側だけ NO にするのも、理にかなってて感動しました。

まとめ:Viewを制する者はDNSを制す

第8回では、BIND9の最高難易度機能の一つ「View」を構築しました。

  • Viewを使えば、接続元IPに応じて異なるDNS情報を返せる(スプリットDNS)。
  • match-clients で振り分けルールを決める。
  • Viewを使う場合、全てのzone定義をView内に入れなければならない
  • 外部向けViewでは recursion no に設定し、キャッシュサーバー機能を無効化する(セキュリティ)。

これで、あなたのDNSサーバーは「社内インフラ」としても「公開サーバー」としても完璧に振る舞えるようになりました。

次回(第9回)は、運用フェーズに入ります。
DNSサーバーを運用していると必ず直面する「ログの管理」について解説します。
デフォルトのログは非常に見にくいですが、設定をカスタマイズすることで「誰が」「何を」問い合わせてきたかを詳細に記録し、不正アクセスを検知できるようになります。
プロのログ監視術を学びましょう!

▼View機能の検証に最適なVPS

外部からのアクセスを実際にテストするには、グローバルIPを持つVPS環境が不可欠です。View機能を使って安全な公開サーバーを構築できるおすすめVPSはこちら。

【2026年最新】Linuxサーバー構築におすすめのVPS比較3選!現役エンジニアが速度とコスパで厳選
Linuxの勉強、まだ「自分のPC」でやって消耗していませんか?「Linuxを覚えたいけど、環境構築でエラーが出て先に進めない…」「VirtualBoxを入れたらパソコンが重くなった…」これは、Linux学習を始める9割の人がぶつかる壁です...

コメント