第12章 DNSサーバーの基本設定とゾーン管理

LPIC-2 207.1〜207.2 相当

ここから202試験パートに入ります。まずは、名前とIPアドレスを結びつけるDNSの仕組みと、代表的なDNSサーバーソフトウェアBINDの基礎を扱います。

DNSの基本用語

用語意味
権威DNSサーバー特定のドメインについて「正式な回答」を持つサーバー
ゾーンあるサーバーが管理を任されているドメインの範囲
キャッシュDNSサーバー(フルリゾルバ)問い合わせを受けて、権威サーバーに再帰的に問い合わせて回答するサーバー
Aレコードホスト名をIPv4アドレスに変換するレコード
MXレコードそのドメイン宛のメールを受け取るサーバーを指定するレコード
NSレコードそのゾーンを管理する権威DNSサーバーを指定するレコード
CNAMEレコードあるホスト名を別のホスト名の別名(エイリアス)として定義するレコード
PTRレコードIPアドレスからホスト名を引く「逆引き」に使うレコード
TXTレコード任意のテキスト情報を格納。SPFやDKIMなど送信ドメイン認証にも利用される
AAAAレコードホスト名をIPv6アドレスに変換するレコード(Aレコードの128ビット版)
SRVレコード特定のサービス(プロトコル)を提供するホストとポート番号を示すレコード
CAAレコードそのドメインに証明書を発行してよい認証局(CA)を制限するレコード

複数のAレコードを同じホスト名に登録すると、クライアント側は問い合わせのたびに異なる順序で結果を受け取ることが多く、簡易的な負荷分散(DNSラウンドロビン)として使われることがあります。ただし障害検知の仕組みは持たないため、あるサーバーが停止していてもそのIPアドレスを返し続けてしまう点には注意が必要です。

BIND(named)の設定ファイル

BINDは最も広く使われているDNSサーバーソフトウェアです。主要な設定ファイルは named.conf で、そこからゾーンファイルを読み込みます。

ディストリビューションによる配置の違い: Debian系(bind9パッケージ)は設定を /etc/bind/named.conf から named.conf.options・named.conf.local に分割し、ゾーンファイルも /etc/bind/ 配下に置く構成が標準です。一方RHEL系(bindパッケージ)は /etc/named.conf 1ファイルに設定をまとめ、ゾーンファイルは /var/named/ 配下に置くのが慣習です。本章のコード例は、設定を分割して見通しをよくできるDebian系の構成で統一しています。RHEL系で作業する場合は、パスの読み替えが必要です。
/etc/bind/named.conf.local(Debian系の例)
zone "example.com" {
    type master;
    file "/etc/bind/db.example.com";
};
/etc/bind/db.example.com(ゾーンファイルの例)
$TTL 86400
@   IN  SOA ns1.example.com. admin.example.com. ( 2024010101 3600 900 604800 86400 )
@   IN  NS  ns1.example.com.
@   IN  A   192.0.2.10
www IN  A   192.0.2.10
mail IN MX 10 mail.example.com.
シリアル番号の書式: SOAレコードのシリアル番号(例の2024010101)は、ゾーンファイルが更新されたことをセカンダリサーバーに伝えるための値です。更新のたびに必ず増加させる必要があり、慣習的に「YYYYMMDDNN」(日付+その日の何回目の更新か)の形式がよく使われます。増加させ忘れると、セカンダリサーバーに変更が反映されません。

SOAレコードのカッコ内には、シリアル番号に続けて4つの時間パラメータが並びます。refresh(セカンダリがプライマリに更新確認を行う間隔)、retry(refreshに失敗した際の再試行間隔)、expire(それでもプライマリに接続できない場合、セカンダリが自身のデータを無効とみなすまでの期間)、minimum(否定応答=該当レコードが存在しないという回答をキャッシュしてよい時間、ネガティブキャッシュTTL)です。これらの値もLPIC-2の記述式設問で狙われやすいポイントです。

よくある間違い: ゾーンファイルでホスト名の末尾にドット(.)を付け忘れるミスは非常によく起こります。ns1.example.com. のように末尾にドットがある場合は「完全修飾ドメイン名(FQDN)」として扱われますが、ドットがないと$ORIGIN(既定ではゾーン名)が自動的に補われてしまい、ns1.example.com.example.com のような意図しないホスト名になってしまいます。named-checkzoneで警告が出ないか必ず確認しましょう。

逆引きゾーンとセカンダリDNS

IPアドレスからホスト名を求める「逆引き」も、通常のゾーンと同様に別ファイルとして定義します。IPv4の場合、オクテットを逆順にした in-addr.arpa というドメインを使います。

/etc/bind/named.conf.local に追記
zone "1.2.0.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192.0.2";
};

/etc/bind/db.192.0.2(逆引きゾーンファイル)
$TTL 86400
@   IN  SOA ns1.example.com. admin.example.com. ( 2024010101 3600 900 604800 86400 )
@   IN  NS  ns1.example.com.
10  IN  PTR www.example.com.

可用性を高めるため、権威DNSサーバーは通常1台のプライマリ(マスター)だけでなく、複数のセカンダリ(スレーブ)サーバーで構成します。セカンダリはゾーン転送(AXFR/IXFR)によってプライマリからデータを取得し、同じ内容を提供します。

セカンダリ側のnamed.conf.local
zone "example.com" {
    type slave;
    file "/var/cache/bind/db.example.com";
    masters { 192.0.2.10; };
};

セカンダリはゾーン転送を受け取る際、SOAレコードのシリアル番号を見て「プライマリの方が新しいかどうか」を判断します。そのため、プライマリ側でゾーンファイルを書き換えたのにシリアル番号を上げ忘れると、セカンダリはいつまでも古い内容のままになってしまいます。運用ミスの中でも特に多い落とし穴です。

再帰的な問い合わせとキャッシュ

クライアント(スタブリゾルバ)は通常、キャッシュDNSサーバーに「再帰的問い合わせ」を行い、答えが見つかるまで全部おまかせします。一方、キャッシュDNSサーバー自身はルートサーバー→TLD(.comなどの)サーバー→権威サーバーへと、階層をたどりながら「反復的問い合わせ」を行い、最終的な回答を得てからクライアントに返します。

一度得られた回答は、レコードごとに設定されたTTL(Time To Live、生存時間)の間だけキャッシュされ、同じ問い合わせが来ても権威サーバーへ再度問い合わせずに済みます。TTLを短くするとレコード変更の反映が速くなる一方、権威サーバーへの問い合わせ頻度が増えて負荷が上がるというトレードオフがあります。サーバー移転など変更を予定している場合は、事前にTTLを短くしておくのが定石です。

スタブリゾルバ キャッシュDNS サーバー ルートサーバー TLDサーバー 権威サーバー ① 再帰的問い合わせ www.example.com? ② 反復問い合わせ ③ .comの権威(TLD)はこちら ④ 反復問い合わせ ⑤ example.comの権威はこちら ⑥ 反復問い合わせ ⑦ Aレコード: 203.0.113.10 ⑧ 回答(TTL付きでキャッシュ) 緑=再帰的問い合わせ(クライアント⇔キャッシュDNS) 黄=反復問い合わせ(キャッシュDNS⇔各階層のサーバー)
DNSの再帰問い合わせと反復問い合わせ。スタブリゾルバはキャッシュDNSサーバーに1回の「再帰的問い合わせ」を行うだけで済み(緑)、キャッシュDNSサーバー自身がルート→TLD→権威サーバーへと階層をたどる「反復問い合わせ」を代行します(黄)。最終的な回答はTTLとともにキャッシュされます。

DNSSECの基礎

DNSは元々、応答が本物かどうかを検証する仕組みを持たず、偽の応答を返す「キャッシュポイズニング」のような攻撃に弱い側面がありました。DNSSEC(DNS Security Extensions)は、ゾーンデータに電子署名を付与し、クライアント側がその署名を公開鍵で検証できるようにする拡張です。

$ sudo dnssec-keygen -a RSASHA256 -b 2048 example.com   # 鍵ペアを生成
Generating key pair...........++++ ...++++
Kexample.com.+008+41234
$ sudo dnssec-signzone -o example.com db.example.com     # ゾーンに署名
Fetching ZSK ... done
Signing zone...
Verifying the zone using the following algorithms: RSASHA256.
Zone signing complete:
Algorithm: RSASHA256: ZSKs: 1, KSKs: 0 active, 0 revoked
db.example.com.signed

この行のこの値に注目: dnssec-keygen実行後に表示されるKexample.com.+008+41234が、生成された鍵ファイル名(K+ドメイン名+アルゴリズム番号+キータグ)です。dnssec-signzone末尾のdb.example.com.signedが実際に署名済みゾーンファイルとして生成されたファイル名で、named.conf側のfile指定をこちらに切り替える必要があります。

DNSSECを導入したゾーンは、親ゾーン(上位のTLDなど)にDS(Delegation Signer)レコードを登録することで、信頼の連鎖(chain of trust)がルートサーバーまでつながります。設定はやや複雑ですが、LPIC-2では「DNSSECが何を解決する技術か」という概念レベルの理解が問われます。

設定の確認と反映

$ sudo named-checkconf              # 設定ファイルの文法チェック(正常時は無出力)
$ sudo named-checkzone example.com /etc/bind/db.example.com   # ゾーンファイルのチェック
zone example.com/IN: loaded serial 2026082101
OK
$ sudo systemctl reload bind9        # 設定を反映(正常時は無出力)

この行のこの値に注目: named-checkconfは/etc/bind/named.conf本体とそこからincludeされる全ファイルの文法を検査し、正常であれば何も表示しません。named-checkzoneは最後にOKと表示されればゾーンファイルの内容も問題なく、loaded serial ...で読み込んだシリアル番号を確認できます。

ゾーンファイルの記述を誤った場合、たとえばレコードの末尾にピリオドを付け忘れる(相対名として解釈されてしまう)ような典型的なミスがあると、次のようなエラーになります。

$ sudo named-checkzone example.com /etc/bind/db.example.com
dns_master_load: /etc/bind/db.example.com:12: www.example.com: no owner
zone example.com/IN: loading from master file db.example.com failed: no owner
zone example.com/IN: not loaded due to errors.

この行のこの値に注目: 12:という行番号がゾーンファイル内のどこに問題があるかを示します。not loaded due to errorsと表示された場合、この状態のままrndc reloadやsystemctl reloadを実行してもゾーンは反映されず、既存の(古い)ゾーンデータが使われ続けるため、エラーを解消してから反映操作を行う必要があります。

reloadとrestartの違い: systemctl reload はプロセスを終了させずに設定・ゾーンファイルだけを再読み込みするため、名前解決サービスを止めずに変更を反映できます。設定ファイルの構文自体を大きく変えた場合や、reloadで反映されない項目を変更した場合のみ restart を使うとよいでしょう。

動作確認

$ dig @192.0.2.10 www.example.com       # 指定したDNSサーバーに直接問い合わせる
;; ANSWER SECTION:
www.example.com.       3600    IN      A       203.0.113.10
;; SERVER: 192.0.2.10#53(192.0.2.10)
$ dig example.com MX                    # MXレコードだけを問い合わせる
;; ANSWER SECTION:
example.com.            3600    IN      MX      10 mail.example.com.
$ dig +short www.example.com            # 回答部分のIPアドレスだけを簡潔に表示
203.0.113.10
$ dig +trace example.com                # ルートサーバーから順にたどる反復問い合わせの過程を表示
.                       518400  IN      NS      a.root-servers.net.
com.                    172800  IN      NS      a.gtld-servers.net.
example.com.            172800  IN      NS      ns1.example.com.
;; Received 65 bytes from 192.0.2.10#53(192.0.2.10) in 4 ms
$ host www.example.com                  # digより簡易な出力の名前解決コマンド
www.example.com has address 203.0.113.10

この行のこの値に注目: @192.0.2.10で問い合わせ先サーバーを明示すると、末尾のSERVER:行で実際にどのサーバーが応答したかを確認できます。+traceはルート→TLD→権威サーバーの順に段階を追って表示するため、どの階層で委任が切れているかをたどって障害切り分けができます。

dig の出力は ANSWER SECTION(実際の回答)、AUTHORITY SECTION(権威サーバーの情報)、ADDITIONAL SECTION(補足情報)に分かれています。トラブルシューティングの際は、まずANSWER SECTIONに期待したレコードが返っているかを確認し、返っていなければAUTHORITY SECTIONで委任先が正しいかを追いかけるのが基本的な流れです。

逆引き(PTRレコード)と正引きの違い

ここまで扱ってきたのは「ホスト名からIPアドレスを引く」正引きですが、その逆に「IPアドレスからホスト名を引く」逆引きという仕組みもあります。逆引きにはPTRレコードが使われ、専用のin-addr.arpaという特殊なドメイン階層で管理されます(IPアドレスのオクテットを逆順に並べた名前になります)。

$ dig -x 192.0.2.10          # IPアドレスからホスト名を逆引き
;; QUESTION SECTION:
;10.2.0.192.in-addr.arpa.      IN      PTR
;; ANSWER SECTION:
10.2.0.192.in-addr.arpa. 3600  IN      PTR     ns1.example.com.

この行のこの値に注目: QUESTION SECTIONにあるように、内部的にはIPアドレスのオクテットを逆順にしたin-addr.arpaドメインへのPTRレコード問い合わせに変換されています。ANSWER SECTIONのPTRレコードが実際に対応するホスト名です。

メールサーバーの送信元IPは、スパム対策の一環として逆引きが正しく設定されているかをチェックされることが多く、逆引きが未設定・不一致だと正当なメールでも迷惑メール判定を受けやすくなります。自社で運用するメールサーバーを構築する際は、正引き・逆引きの両方が正しく対応しているかを必ず確認しましょう。

フォワーダとキャッシュ専用サーバー

自社ネットワーク内に権威DNSサーバーとは別に、社内利用者向けのキャッシュ専用サーバー(フォワーダ)を1台立てておくと、外部への問い合わせを集約しつつ、既にキャッシュされた内容は高速に返せるようになります。named.conf.optionsでforwardersを指定すると、自身で反復問い合わせを行う代わりに、指定した上位のDNSサーバー(プロバイダのDNSやパブリックDNSなど)に問い合わせを委譲できます。

/etc/bind/named.conf.options の一部
options {
    forwarders { 8.8.8.8; 1.1.1.1; };
    forward only;
};

forward onlyを指定すると、フォワーダへの問い合わせが失敗した場合でも自前の反復問い合わせにフォールバックしなくなります。社内ネットワークのように、外向きの直接的な問い合わせを制限したい環境でよく使われる設定です。

options句の主要ディレクティブ

BINDの動作全体に関わる設定は、named.conf.options(またはnamed.confのoptions { }ブロック)にまとめます。ここまでで扱ったforwarders以外にも、セキュリティ・運用上重要なディレクティブが数多くあります。

ディレクティブ意味
directoryゾーンファイルなど相対パスで指定するファイルの基点ディレクトリ
allow-query問い合わせを許可するクライアントの範囲(IPアドレス・ネットワーク)
allow-transferゾーン転送(AXFR/IXFR)を許可するセカンダリの範囲
allow-recursion再帰的な問い合わせを許可するクライアントの範囲
recursion yes/noこのサーバー自身が再帰的問い合わせを行うかどうか
listen-on問い合わせを受け付けるIPv4アドレス・ポート
listen-on-v6問い合わせを受け付けるIPv6アドレス・ポート
versiondigなどのversion.bind問い合わせに対して返す文字列。実際のバージョンを隠すために変更することが多い
dnssec-validation受け取った応答のDNSSEC署名を検証するかどうか(auto/yes/no)
/etc/bind/named.conf.options の例
options {
    directory "/var/cache/bind";
    allow-query { any; };
    allow-transfer { none; };
    allow-recursion { trusted; };
    recursion yes;
    listen-on { any; };
    listen-on-v6 { any; };
    version "unknown";
    dnssec-validation auto;
};
注意: 権威DNSサーバーとして公開する場合、allow-recursionを無制限(any)にしたまま外部に公開してしまうと、第三者に再帰問い合わせを踏み台として使われる「オープンリゾルバ」状態になり、DNS増幅攻撃(DNS amplification attack)に加担してしまう危険があります。権威サーバーとキャッシュサーバーの役割を明確に分離し、権威サーバーではrecursion noとするのが基本です。

acl句による名前付きアクセスリスト

先ほどのallow-queryやallow-transferに、IPアドレスの集合をそのつど書き並べると、設定が長くなり保守しづらくなります。acl句を使うと、よく使うIPアドレスの集合に名前を付けて再利用できます。

named.conf.options(またはnamed.conf.local)の先頭付近
acl "trusted" {
    192.0.2.0/24;
    203.0.113.5;
    localhost;
};

options {
    allow-recursion { trusted; };
};

組み込みのany(すべて)、none(誰も許可しない)、localhost(このサーバー自身)、localnets(このサーバーが直接接続しているネットワーク)といったキーワードも、aclと同様に使えます。

view句によるsplit DNS

社内ネットワークからは内部向けのプライベートIPアドレスを、インターネットからは外部向けのグローバルIPアドレスを返したい、といった要件は「split DNS(またはsplit-horizon DNS)」と呼ばれ、BINDではview句で実現します。

named.conf.local の例
acl "internal-net" { 192.168.1.0/24; };

view "internal" {
    match-clients { internal-net; };
    zone "example.com" {
        type master;
        file "/etc/bind/internal/db.example.com";
    };
};

view "external" {
    match-clients { any; };
    zone "example.com" {
        type master;
        file "/etc/bind/external/db.example.com";
    };
};

この行のこの値に注目: match-clientsで指定した条件に、問い合わせ元のクライアントが一致するviewが上から順に評価され、最初に一致したviewのゾーン定義が使われます。この例ではinternal-netからの問い合わせには社内向けのdb.example.com(プライベートIPを含む)が、それ以外(any)からの問い合わせには社外向けのdb.example.com(グローバルIPのみ)が返されます。view句の定義順序が評価順序に直結するため、より限定的な条件のviewを先に、より広い条件(any)のviewを後に書くのが鉄則です。順序を逆にすると、内部ネットワークからの問い合わせも常に外部向けviewにマッチしてしまいます。

logging句によるログ出力の設定

BINDは既定でも基本的なログをsyslog経由で出力しますが、logging句を使うと、ログの出力先・種類・詳細度を細かく制御できます。

named.conf.options(またはnamed.conf)の例
logging {
    channel "query-log" {
        file "/var/log/named/query.log" versions 5 size 20m;
        severity info;
        print-time yes;
    };
    category queries { query-log; };

    channel "security-log" {
        file "/var/log/named/security.log" versions 3 size 10m;
        severity warning;
        print-time yes;
    };
    category security { security-log; };
};

この行のこの値に注目: channelは「どこに」「どの詳細度で」出力するかを定義する単位で、categoryは「どの種類のイベントを」そのchannelへ振り分けるかを定義します。versions 5 size 20mは、ログファイルが20MiBに達するたびにローテーションし、最大5世代分(query.log.0〜query.log.4)を保持することを意味します。severityは出力する詳細度のしきい値(critical・error・warning・notice・info・debugの順に詳しくなる)で、print-time yesは各ログ行の先頭にタイムスタンプを付与する設定です。

代表的なcategory記録される内容
queries受信したすべての問い合わせ(トラフィック量が多いため既定では無効)
securityアクセス制御による拒否など、セキュリティに関わるイベント
default個別のcategoryが指定されていないすべてのイベント
実務のヒント: queriesカテゴリのログは、すべての問い合わせを記録するためトラフィック解析やトラブルシューティングに有用ですが、負荷の高いサーバーではログの量が非常に大きくなります。常時有効にするのではなく、調査したいときだけrndc querylogで一時的に有効・無効を切り替える運用が実務的です。

rndc — BINDのリモート管理コマンド

rndc(remote name daemon control)は、稼働中のnamedプロセスに対して、設定の再読み込みやゾーンの操作などを指示するための管理コマンドです。rndcとnamedの間は共有鍵(HMAC)による認証が行われ、この鍵はrndc.keyファイルに保存されます。

$ sudo rndc-confgen -a          # /etc/bind/rndc.key を生成(多くのディストリでは初期状態で自動生成済み。正常時は無出力)
$ cat /etc/bind/rndc.key
key "rndc-key" {
    algorithm hmac-sha256;
    secret "xxxxxxxxxxxxxxxxxxxxxxxxxx==";
};

named.conf側では、この鍵を使ってrndcからの接続を受け付けるようcontrols句で指定します。

named.conf の一部
include "/etc/bind/rndc.key";
controls {
    inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { "rndc-key"; };
};

rndcには、運用でよく使う多数のサブコマンドが用意されています。

サブコマンド効果
rndc status稼働状況(バージョン、稼働ゾーン数、再帰問い合わせの状況など)を表示
rndc reloadすべての設定・ゾーンファイルを再読み込みする(プロセスは再起動しない)
rndc reconfignamed.confの変更のみを反映する(既存ゾーンの再読み込みは行わない、reloadより軽量)
rndc flushキャッシュされている全レコードを破棄する
rndc freeze [ゾーン名]指定ゾーン(省略時は全ゾーン)を凍結し、動的更新を一時停止してゾーンファイルを手編集可能にする
rndc thaw [ゾーン名]freezeで凍結したゾーンの動的更新を再開する(ゾーンファイルも再読み込みされる)
rndc querylog問い合わせログ(queryログ)の記録を切り替える(トグル動作)
rndc retransfer ゾーン名セカンダリで、指定ゾーンの全体を強制的に再転送させる
rndc notify ゾーン名プライマリから、そのゾーンのセカンダリへNOTIFYメッセージを再送する
$ sudo rndc status
version: BIND 9.18.30-0ubuntu0.24.04.2-Ubuntu
number of zones: 3 (1 automatic)
recursive clients: 0/900/1000
tcp clients: 0/150
server is up and running
$ sudo rndc reload example.com
zone reload up-to-date
$ sudo rndc flush   # 正常時は無出力

この行のこの値に注目: rndc statusのserver is up and runningで稼働状態を確認でき、number of zonesで実際に読み込まれているゾーン数を確認できます。rndc reload example.comのzone reload up-to-dateは、ゾーンファイルの内容(シリアル番号)に変更がなく再読み込みの必要がなかったことを示します。

試験対策: 動的更新(Dynamic DNS)が有効なゾーンのゾーンファイルは、named自身が随時書き換えるため、管理者が不用意に直接エディタで編集すると、named側の変更と衝突して内容が壊れる危険があります。手動でゾーンファイルを編集する必要がある場合は、必ず先にrndc freeze ゾーン名でそのゾーンへの動的更新を一時停止し、編集後にrndc thaw ゾーン名で再開するという手順を踏みます。この手順はLPIC-2でも狙われやすいポイントです。

TSIG — トランザクション署名によるゾーン転送の保護

ゾーン転送を許可するセカンダリの範囲はallow-transferでIPアドレスによって制限できますが、IPアドレスは送信元詐称(スプーフィング)の対象になりうるため、それだけでは十分な保護とはいえません。TSIG(Transaction Signature)は、プライマリとセカンダリの間で共有鍵を使ってメッセージ全体に署名し、通信内容の改ざん・なりすましを検知できるようにする仕組みです。

$ tsig-keygen tsig-key > /etc/bind/tsig-key.conf   # 正常時は無出力(結果はリダイレクト先のファイルに書き込まれる)
# または dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST tsig-key でも生成可能
$ cat /etc/bind/tsig-key.conf
key "tsig-key" {
    algorithm hmac-sha256;
    secret "yyyyyyyyyyyyyyyyyyyyyyyyyy==";
};

生成した鍵は、プライマリ・セカンダリ双方のnamed.confに同一の内容で配置し、通信相手ごとにserver句で使用する鍵を指定します。

プライマリ側 named.conf
include "/etc/bind/tsig-key.conf";
server 192.0.2.20 {           # セカンダリのIPアドレス
    keys { "tsig-key"; };
};
zone "example.com" {
    type master;
    file "/etc/bind/db.example.com";
    allow-transfer { key tsig-key; };   # IPアドレスではなく鍵の保持を条件にする
};
セカンダリ側 named.conf
include "/etc/bind/tsig-key.conf";
server 192.0.2.10 {           # プライマリのIPアドレス
    keys { "tsig-key"; };
};
zone "example.com" {
    type slave;
    file "/var/cache/bind/db.example.com";
    masters { 192.0.2.10; };
};

TSIGを使った転送が正しく機能しているかは、digに鍵情報を渡すことで手動テストできます。

$ dig @192.0.2.10 example.com AXFR -y hmac-sha256:tsig-key:yyyyyyyyyyyyyyyyyyyyyyyyyy==
example.com.            3600    IN      SOA     ns1.example.com. admin.example.com. 2026082101 3600 900 604800 3600
example.com.            3600    IN      NS      ns1.example.com.
www.example.com.        3600    IN      A       203.0.113.10
example.com.            3600    IN      SOA     ns1.example.com. admin.example.com. 2026082101 3600 900 604800 3600
;; TSIG: hmac-sha256, response signed successfully

この行のこの値に注目: ゾーン全体がSOAレコードで始まりSOAレコードで終わる(AXFRの規約通りの区切り)のが正常な転送結果です。末尾のTSIG: ... response signed successfullyで、応答が正しい鍵で署名されていたことを確認できます。鍵が一致しない場合はtsig verify failureというエラーになり、転送内容は返されません。

なぜIPアドレス制限だけでは不十分なのか: allow-transferによるIPアドレス制限は、送信元IPアドレスを偽装した攻撃(IPスプーフィング)や、正規のセカンダリと同じネットワークに侵入された場合には防御になりません。TSIGは、送信元がどのIPアドレスであっても、正しい共有鍵を持つ相手だけに応答するため、より強固な認証層を追加できます。実務では、IPアドレス制限とTSIGを併用する多層防御が推奨されます。

chroot jailでのBIND実行

namedプロセスがもし脆弱性を突かれて侵害された場合、通常のプロセスと同じ権限のままでは、システム全体のファイルにアクセスされてしまう危険があります。chroot(change root)は、あるプロセスから見えるルートディレクトリを、本来の/ではなく特定のディレクトリに限定する仕組みで、万が一侵害された場合の被害範囲を、そのディレクトリ配下に限定できます。

bind9をchroot環境で動かす場合、通常は/var/named/chroot(ディストリビューションにより異なる)のようなディレクトリの下に、通常のシステムルートに存在する最低限のディレクトリ構造を複製します。

chroot内のディレクトリ用途
etc/named.conf、rndc.key、ゾーンファイルなどの設定一式
var/ログファイル、キャッシュ用ゾーンファイルなどnamedが書き込む領域
dev/namedが必要とするデバイスファイル(/dev/random、/dev/nullなど)

/dev/random(または/dev/urandom)は、DNSSECの署名やクエリIDのランダム化に使う乱数を生成するために必要で、/dev/nullは出力を破棄する際に多くのプログラムが暗黙に利用します。chroot環境ではシステム本来の/devが見えなくなるため、これらのデバイスファイルをchroot内に個別に用意(mknodで作成するか、bind-mountで本来の/devの該当ファイルを持ち込む)しておかないと、namedの起動やDNSSEC関連の処理が失敗します。

ログについても同様の問題があり、chroot内のnamedからは通常の/dev/log(syslogのソケット)が見えなくなるため、syslogデーモン側でchroot内のdev/logにも追加でリッスンさせる設定(例:rsyslogの$AddUnixListenSocket)を行うか、BIND自身のファイル出力ログ(logging句)に切り替える必要があります。

RHEL系ではnamed-chroot.serviceという専用のsystemdユニットが用意されており、これを使うと上記のディレクトリ構造やマウント処理が自動化されます。Debian系では、パッケージ既定ではchroot構成が用意されておらず、必要に応じて管理者自身がディレクトリ構造を構築し、/etc/default/bind9の起動オプションに-t /var/named/chroot -u bindのように指定します。

近年の動向: chrootは伝統的な隔離手法ですが、近年ではsystemdが提供する各種サンドボックス機能(ProtectSystem、ProtectHome、PrivateDevices、NoNewPrivilegesなどをユニットファイルの[Service]セクションに指定する方式)で、より柔軟かつ簡便に同様の隔離効果を得られるようになってきています。chrootの考え方自体は依然として試験範囲・実務知識として重要ですが、最新の環境ではこうしたsystemdの機能で代替されるケースも増えている点は理解しておきましょう。

DANEとTLSAレコードの概要

DANE(DNS-based Authentication of Named Entities)は、証明書の正当性を、既存の認証局(CA)階層とは独立に、DNSSECで保護されたDNS応答を使って検証できるようにする仕組みです。DANEではTLSAレコードという新しいレコードタイプを使い、特定のホスト・ポートで提供されるべきTLS証明書(またはその公開鍵)の情報をDNSに公開します。

TLSAレコードの例(_443._tcp.www.example.com)
_443._tcp.www.example.com. IN TLSA 3 1 1 (
  d2abde240d7cd3ee6b4b28c54df034b9
  7983a1d16e8a410e4561cb106618e971 )

クライアントは、通常のCA階層による証明書検証に加えて、DNSSECで保護されたこのTLSAレコードとサーバー証明書を突き合わせることで、不正な認証局から発行された偽の証明書を検知できます。TLSAレコードの信頼性はDNSSECの署名検証に依存しているため、DANEはDNSSECが正しく機能している環境でのみ意味を持つ点が前提条件です。LPIC-2では、概念(DNSSECを基盤にCA階層を補完・代替する仕組み)としての理解が問われます。

named-compilezoneとバイナリ形式のゾーンファイル

ここまで扱ってきたゾーンファイルは、人間が読み書きしやすいテキスト形式(マスターファイル形式)でした。named-compilezoneを使うと、このテキスト形式のゾーンファイルを、BIND内部で高速に読み込めるバイナリ形式に変換できます。

$ named-compilezone -f text -F raw -o db.example.com.raw example.com db.example.com
zone example.com/IN: loaded serial 2026082101
dump done
# -f text: 入力形式(テキスト)、-F raw: 出力形式(バイナリのraw形式)

この行のこの値に注目: named-checkzoneと同様にloaded serial ...で読み込んだシリアル番号を確認でき、最後のdump doneで変換が完了したことが分かります。生成されたdb.example.com.rawはバイナリ形式のため、テキストエディタで開いても内容は読めません。

変換したバイナリ形式のゾーンファイルを使うよう、named.conf側でmasterfile-format rawを指定します。

named.conf.local の例
zone "example.com" {
    type master;
    file "/etc/bind/db.example.com.raw";
    masterfile-format raw;
};

バイナリ形式は、非常に多くのレコードを持つ大規模なゾーンで、named起動時のゾーン読み込み時間を短縮できるという利点がありますが、テキストエディタで直接内容を読めなくなるため、通常の運用ではテキスト形式のまま管理し、ゾーンファイルの編集履歴もテキスト形式で管理する(rawファイルはあくまで実行時の最適化として生成する)運用が一般的です。

代替DNSサーバーソフトウェアの認識

BINDは最も広く使われているDNSサーバーですが、用途に応じて他のソフトウェアが選ばれることもあります。LPIC-2では、それぞれの位置づけを認識しておくことが求められます。

ソフトウェア位置づけ
dnsmasq小規模ネットワーク向けの軽量なDNS/DHCPサーバー。キャッシュ機能とDHCPサーバー機能を1つのプロセスで兼ねられる手軽さが特徴
PowerDNSゾーンデータをMySQLやPostgreSQLなどのデータベースに保存できる権威DNSサーバー。Web管理画面や大規模なゾーン数の運用と相性がよい
Unbound再帰・キャッシュ専用に特化したDNSサーバー。権威サーバー機能を持たず、シンプルさとセキュリティを重視した設計
djbdnsDaniel J. Bernstein氏が開発した、複数の独立した小さなプログラム群からなるDNSサーバー。歴史的にセキュリティ面で高く評価された

試験対策としては、「権威サーバー専用」「キャッシュ専用」「DB連携が可能」「軽量・小規模向け」といった各ソフトウェアの主な特徴とBINDとの違いを対応付けて覚えておくと十分です。

digの出力の完全な読み方

ここまでdigコマンドを何度も使ってきましたが、その出力の各行が何を意味するかを体系的に押さえておくと、トラブルシューティングの精度が大きく上がります。

$ dig www.example.com

; <<>> DiG 9.18.1 <<>> www.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34521
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;www.example.com.              IN      A

;; ANSWER SECTION:
www.example.com.       86400   IN      A       192.0.2.10

;; AUTHORITY SECTION:
example.com.            86400   IN      NS      ns1.example.com.
example.com.            86400   IN      NS      ns2.example.com.

;; ADDITIONAL SECTION:
ns1.example.com.        86400   IN      A       192.0.2.10
ns2.example.com.         86400   IN      A       192.0.2.11

;; Query time: 12 msec
;; SERVER: 192.0.2.10#53(192.0.2.10)
;; WHEN: Thu Aug 20 10:00:00 JST 2026
;; MSG SIZE  rcvd: 123

この行のこの値に注目: HEADER行のopcodeは問い合わせの種類(通常はQUERY)、statusは応答結果を示すもっとも重要な情報です。

status意味・疑うべき原因
NOERROR問い合わせは正常に処理された(ANSWER SECTIONが空でもNOERRORになりうる点に注意)
NXDOMAIN問い合わせたドメイン自体が存在しない。タイプミスやドメイン未登録を疑う
SERVFAIL権威サーバー側で何らかのエラーが発生した。ゾーンファイルの設定ミスやDNSSEC検証エラーを疑う
REFUSED問い合わせ自体をサーバーに拒否された。allow-queryなどのアクセス制御による拒否を疑う

flags行に並ぶアルファベットは、それぞれ意味を持つビットフラグです。

フラグ意味
qrQuery/Response。このメッセージが応答であることを示す
aaAuthoritative Answer。権威サーバー自身からの回答であることを示す(キャッシュ経由の回答には付かない)
rdRecursion Desired。クライアントが再帰的問い合わせを要求したことを示す
raRecursion Available。応答したサーバーが再帰的問い合わせに対応していることを示す
adAuthenticated Data。DNSSECによる検証に成功したデータであることを示す
cdChecking Disabled。クライアント側がDNSSEC検証を行わないよう要求したことを示す

続く4つのセクションは、それぞれ役割が異なります。QUESTION SECTIONには問い合わせ内容そのもの、ANSWER SECTIONには実際の回答レコード、AUTHORITY SECTIONにはそのゾーンを管理する権威サーバー(NSレコード)の情報、ADDITIONAL SECTIONには回答を補足する追加情報(NSレコードに対応するAレコードなど)が並びます。末尾には、応答にかかった時間(Query time)、問い合わせたサーバー(SERVER)、問い合わせ時刻(WHEN)、メッセージサイズ(MSG SIZE)が表示されます。

ゾーンの委任(親ゾーンでのNSレコードとグルーレコード)

あるドメインのDNS管理を、上位のドメインから切り離して別の権威サーバーに任せることを委任(delegation)と呼びます。たとえばexample.comを管理する組織が、社内システム用にdept.example.comというサブドメインを別チームに管理させたい場合、親ゾーン(example.com)側に、そのサブドメインを担当する権威サーバーを示すNSレコードを追加します。

親ゾーン db.example.com への追記
dept.example.com.    IN  NS  ns1.dept.example.com.
dept.example.com.    IN  NS  ns2.dept.example.com.

グルーレコード(委任先の権威サーバー自体が委任するドメインの中に存在する場合に必須)
ns1.dept.example.com. IN  A   192.0.2.50
ns2.dept.example.com. IN  A   192.0.2.51

この行のこの値に注目: 委任先の権威サーバー名(この例ではns1.dept.example.com)自体が、委任するドメイン(dept.example.com)の中に含まれている場合、「そのサーバーのIPアドレスを知るには、まずそのサーバーに問い合わせる必要がある」という循環参照が発生してしまいます。これを避けるため、親ゾーン側に委任先サーバーのIPアドレス(Aレコード)を直接記載しておく必要があり、これをグルーレコードと呼びます。委任先のネームサーバー名が委任するドメインの外にある場合は、グルーレコードは不要です。

ルート .com example.com dept.example.com 信頼の連鎖:上位のゾーンが下位のゾーンの権威サーバーを保証しながら委任していく 親ゾーン:example.com dept.example.com. NS ns1.dept… dept.example.com. NS ns2.dept… グルーレコード ns1.dept.example.com. A 192.0.2.50 ns2.dept.example.com. A 192.0.2.51 ※権威サーバー名が委任先ドメインの中に あるため、循環参照を避けるのに必須 親ゾーンは委任先を「示す」だけで、 実データそのものは持たない。 子ゾーン:dept.example.com 権威サーバー: ns1 / ns2.dept.example.com この委任先のサーバーが、 dept.example.com配下の 実際のA/MXレコード等を 権威をもって管理する。 委任
DNSゾーンの委任と信頼の連鎖。上位のゾーン(example.com)はNSレコードで下位のゾーン(dept.example.com)に管理を委任します。委任先の権威サーバー名が委任するドメインの中にある場合は、循環参照を避けるためグルーレコード(緑枠)で親ゾーン側にIPアドレスを直接記載します。

ゾーン転送の失敗を診断する手順

セカンダリでゾーンデータが更新されない、あるいはセカンダリの起動時にゾーンが空のままになるといった問題が起きた場合、次の手順で原因を切り分けます。

  1. digで転送を直接試す: dig @プライマリのIP ゾーン名 AXFRを実行し、実際にゾーン転送が成功するかを確認します。Transfer failedのようなエラーが出れば、プライマリ側のアクセス制御(allow-transfer)に問題がある可能性が高いといえます。
  2. namedのログを確認する: プライマリ・セカンダリ双方のログ(journalctl -u bind9や、logging句で指定したログファイル)に、転送拒否やタイムアウトに関するメッセージが出ていないか確認します。
  3. シリアル番号を比較する: dig @プライマリのIP ゾーン名 SOAとdig @セカンダリのIP ゾーン名 SOAを実行し、それぞれのシリアル番号を比較します。セカンダリの値がプライマリより古い場合、転送自体が行われていないか、プライマリ側でシリアル番号の更新を忘れている可能性があります。
  4. allow-transferの設定を確認する: プライマリ側のallow-transferに、セカンダリのIPアドレス(またはTSIG鍵)が正しく含まれているかを再確認します。設定変更後はrndc reloadを忘れずに実行します。
実務のヒント: ゾーン転送のトラブルは、プライマリ側の設定ミスとネットワーク経路(ファイアウォールでTCP 53番ポートがブロックされている)の両方が原因になりえます。ゾーン転送はUDPではなくTCPで行われる点を忘れずに、ファイアウォール側の許可設定も合わせて確認しましょう。

確認クイズ

Q1. 特定のドメインについて「正式な回答」を持つDNSサーバーを何と呼びますか?

解説: 権威DNSサーバーは、担当するゾーンについて正式な回答を持つサーバーです。問い合わせを中継して回答するのがキャッシュDNSサーバー(フルリゾルバ)です。

Q2. ホスト名をIPv4アドレスに変換するDNSレコードの種類はどれですか?

解説: Aレコードはホスト名をIPv4アドレスに変換するレコードです。メールサーバーの指定にはMXレコード、権威サーバーの指定にはNSレコードを使います。

Q3. BINDの設定ファイルの文法エラーがないかを、サービスを再起動せずに確認するコマンドはどれですか?

解説: named-checkconf は named.conf の文法チェックを行うツールです。ゾーンファイル専用のチェックにはnamed-checkzoneを使います。

Q4. 指定したDNSサーバーに直接問い合わせを送って、名前解決結果を確認するコマンドはどれですか?

解説: dig @サーバーIP ホスト名 のように@を付けることで、システムの既定DNSではなく指定したDNSサーバーに直接問い合わせて結果を確認できます。

Q5. 動的更新が有効なゾーンのゾーンファイルを手動で編集する前に実行すべきrndcサブコマンドはどれですか?

解説: rndc freezeでそのゾーンへの動的更新を一時停止してから手編集し、編集後はrndc thawで再開します。編集中に named 自身が書き換えると内容が壊れる危険があります。

Q6. rndc reconfigとrndc reloadの違いとして正しいものはどれですか?

解説: rndc reconfigはnamed.confの変更のみを軽量に反映し、rndc reloadはゾーンファイルも含めてすべて再読み込みします。

Q7. rndcがnamedプロセスと通信する際の認証に使われるファイルはどれですか?

解説: rndc.keyには共有鍵(HMAC)の情報が保存されており、named.confのcontrols句でこの鍵を使った認証が設定されます。

Q8. TSIGがIPアドレスによるallow-transfer制限よりも優れている点はどれですか?

解説: TSIGは共有鍵によるメッセージ署名で認証するため、IPアドレスの偽装(スプーフィング)による攻撃に対しても、IPアドレス制限だけの場合より強固な防御になります。

Q9. プライマリ側でallow-transfer { key tsig-key; }; と設定する意味はどれですか?

解説: allow-transferにkeyキーワードを使うと、IPアドレスではなくTSIG鍵の保持を条件にゾーン転送の可否を判定します。

Q10. BINDをchroot環境で動かす際、chroot内の/dev/にランダムデバイスファイルが必要な主な理由はどれですか?

解説: /dev/random(または/dev/urandom)は、DNSSEC署名やクエリIDランダム化のための乱数生成に必要で、chroot環境では個別に用意しないとnamedの動作に支障が出ます。

Q11. acl句を使う主な目的はどれですか?

解説: acl句は、IPアドレスの集合に名前を付けて定義しておくことで、allow-query・allow-transferなど複数箇所で使い回せるようにする仕組みです。

Q12. view句を使ったsplit DNSの設定で、より限定的な条件のviewを先に、any(すべて)を条件とするviewを後に書くべき理由はどれですか?

解説: view句は上から順に評価され、最初にmatch-clientsの条件が一致したviewが使われます。anyを先に書くと、それ以降のviewには一切マッチしなくなってしまいます。

Q13. DANEにおけるTLSAレコードの役割はどれですか?

解説: TLSAレコードは、DNSSECで保護されたDNS応答を通じて、正当なTLS証明書の情報を公開し、CA階層とは独立した証明書検証を可能にします。

Q14. named-compilezoneの主な用途はどれですか?

解説: named-compilezoneは、テキスト形式(マスターファイル形式)のゾーンファイルをバイナリ形式(raw)に変換し、named起動時の読み込みを高速化するために使います。

Q15. 小規模ネットワーク向けに、DNSキャッシュ機能とDHCPサーバー機能を1つのプロセスで兼ねられる軽量なソフトウェアはどれですか?

解説: dnsmasqは、小規模ネットワーク向けの軽量なDNS/DHCPサーバーで、キャッシュとDHCPの機能を1つのプロセスで兼ねられる手軽さが特徴です。

Q16. 再帰・キャッシュ専用に特化し、権威サーバー機能を持たないDNSサーバーソフトウェアはどれですか?

解説: Unboundは再帰・キャッシュ専用に特化したDNSサーバーで、シンプルさとセキュリティを重視した設計が特徴です。

Q17. digの出力でstatus: NXDOMAINと表示された場合に疑うべき原因はどれですか?

解説: NXDOMAINは、問い合わせたドメイン自体が存在しないことを示す応答です。タイプミスやドメイン未登録を疑います。

Q18. digの出力のflags行にあるaaフラグの意味はどれですか?

解説: aa(Authoritative Answer)は、その応答が権威サーバー自身から返されたものであることを示します。キャッシュ経由の回答には付きません。

Q19. 委任先の権威サーバー名が、委任するドメイン自体の中に含まれている場合に、親ゾーンに必須となるレコードはどれですか?

解説: 委任先のネームサーバー名が委任するドメインの中にある場合、そのサーバーのIPアドレスを直接示すグルーレコードを親ゾーンに置かないと、循環参照が発生してしまいます。

Q20. ゾーン転送の失敗を診断する際に確認すべき、ゾーン転送で使われるトランスポートプロトコルはどれですか?

解説: ゾーン転送(AXFR/IXFR)は通常の問い合わせと異なりTCPで行われるため、ファイアウォールでTCP 53番ポートが許可されているかも確認が必要です。