| サイズ: 35233 コメント:  | サイズ: 35063 コメント:  | 
| 削除された箇所はこのように表示されます。 | 追加された箇所はこのように表示されます。 | 
| 行 130: | 行 130: | 
| * マスターゾーンである。 * マスターゾーン変更に対する通知(Notification)は明示的に指定する(notify および also-notify 設定)。 * スレイブサーバーからのSOAクエリがあるので答えられるように設定(allow-query)。 * スレイブサーバーからのゾーン転送に答えられるように設定(allow-transfer) | * マスターゾーン変更に対する通知(Notification)は明示的に指定する(notify および also-notify 設定)。 * スレイブサーバーからのSOAクエリがあるので答えられるように設定(allow-query 設定)。 * スレイブサーバーからのゾーン転送に答えられるように設定(allow-transfer 設定) | 
| 行 151: | 行 150: | 
| masters         IN      A       ns0のIPv4アドレス label.masters IN A ns0のIPv4アドレス label.masters IN TXT "ns0-nsN." allow-query IN APL 1:0.0.0.0/0 2:::/0 allow-transfer IN APL !1:0.0.0.0/0 !2:::/0 }}} * ゾーン定義ではSOAとNSレコードの指定が必須なので、 | }}} * ゾーン定義ではSOAとNSレコードの指定が必須なので、以下のように設定する。 | 
| 行 161: | 行 155: | 
| * よって、「version」レコード(つまり version.catalog.example.)が最低でも必須となる。 | * よってカタログゾーン運用のための本質的に必要なレコード「version」(つまり version.catalog.example.)が最低でも必須となる。 | 
| 行 163: | 行 157: | 
| * 今後カタログゾーン自体の仕様変更があれば、この「version」の指定が変わることが予定されている(「1」以外の指定の場合の振る舞いは知らない)。 * 「masters」レコードにて、スレイブサーバーでの「masters」のデフォルトの設定を指定することができる(後述)。 * デフォルトなので後で指定するゾーン毎にこの設定は変更できる。 * 「label.masters」レコードにて、指定サーバーに対するTSIGキー名を指定することができる(後述)。 * デフォルトなので後で指定するゾーン毎にこの設定は変更できる。 * もちろんではあるが、これらレコードの設定は「catalog.example」ゾーン自体には適用されない。 ==== masters.catalog.example ==== 本レコード設定は、指定されたAレコード(orAAAAレコード)を、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{{ masters { ns0のIPアドレス; }; }}} デフォルトの設定となるため、今後追加されるゾーンに対しては、特に指定せずとも、指定されたマスターサーバーよりゾーン転送しようとするようになる。 またスレーブサーバー側の設定として default-masters で指定可能である。 ==== label.masters.catalog.example ==== 本レコード設定は、Aレコード・TXTレコードを、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{{ server ns0のIPアドレス { keys "ns0-nsN."; }; }}} またスレーブサーバー側の設定として default-masters で指定可能である。 ==== allow-query.catalog.example ==== 本レコード設定は、[[https://tools.ietf.org/html/rfc3123|APRレコード]]を、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{{ allow-query { any; }; }}} 本設定によりスレーブサーバー側の設定に寄らず、本設定が「デフォルト」として機能する。 ==== allow-transfer.catalog.example ==== 本レコード設定は、[[https://tools.ietf.org/html/rfc3123|APRレコード]]を、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{{ allow-trasnfer { none; }; }}} 本設定によりスレーブサーバー側の設定に寄らず、本設定が「デフォルト」として機能する。 | * 今後カタログゾーン自体の仕様変更があれば、この「version」の指定が変わることが予定されている。 * なお「1」以外の指定の場合の振る舞いは知らないし、調べる気もない。 | 
| 行 311: | 行 260: | 
| * default-masters 設定によりデフォルトの masters が指定される。 * default-masters 設定についてはマスター側のカタログゾーン内における masters.catalog.example/label.masters.catalog.example レコードでの指定と同等となる。 | * default-masters 設定によりカタログゾーンで定義されるゾーンのデフォルト masters が指定される。 | 
| 行 316: | 行 264: | 
| * スレーブゾーンである。 * このスレーブゾーンを更にマスターにするような運用はしない(notify, allow-transfer 設定による明示的な無効化)。 * 特に必要ないが、マスターからの問い合わせ(クエリおよびゾーン転送)に回答できるようにしておく(気が向いた時のデバッグ用)。 * このゾーンはサービスゾーンではないので、クエリに答える必要は無い。 | * このスレーブゾーンを更にマスターにするような運用はしない(notify, allow-transfer 設定による明示的な無効化)。 * 特に必要ないのだが、マスターからの問い合わせ(クエリおよびゾーン転送)に回答できるようにしておく(気が向いた時のデバッグ用)。 * 繰り返しとなるが、このゾーン自体はサービスゾーンではないので、外部からのクエリに答える必要は無い。 | 
| 行 338: | 行 285: | 
| ※作業内容を確認するとわかるが、確認以外のいわゆる上記作業内容において、マスターサーバーのみ実施すれば良いことがわかる。 | |
| 行 388: | 行 337: | 
| @@ -1,5 +1,5 @@ | @@ -1,4 +1,5 @@ | 
| 行 394: | 行 343: | 
| masters                IN      A       ns0のIPアドレス @@ -7,3 +7,9 @@ label.masters IN TXT "ns0-nsN." allow-query IN APL 1:0.0.0.0/0 2:0:0:0:0:0:0:0:0/0 allow-transfer IN APL !1:0.0.0.0/0 !2:0:0:0:0:0:0:0:0/0 +eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN PTR example.jp. +masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN A ns0のIPアドレス +label.masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN A ns0のIPアドレス +label.masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN TXT "ns0-nsN." +allow-query.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL 1:0.0.0.0/0 2:0:0:0:0:0:0:0:0/0 +allow-transfer.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL !1:0.0.0.0/0 !2:0:0:0:0:0:0:0:0/0 }}} * カタログゾーン機能の一番の肝がここ。 * 色々準備した前提であれば以下の一行の追加だけでOK。 {{{ eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN PTR example.jp. }}} そして「eb7b38678a581b9e32078e8b009d0c5c789bce7a」というハッシュ値と思われる文字列の作り方は、 | +eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN      PTR     example.jp. }}} ※カタログゾーン機能の一番の肝がこの行に集約される。 「eb7b38678a581b9e32078e8b009d0c5c789bce7a」というハッシュ値と思われる文字列の作り方は、 | 
| 行 415: | 行 350: | 
| となる。意味不明なので個別に作業工程を分解する。 * 「example.jp」を「.」で分解する(最後に暗黙の「.」がある前提)。「example」「jp」「」の3つに分かれる。 * それぞれの文字数をカウントする。「example」=「7」、「jp」=「2」、「」=「0」。 * 文字数をプレフィックスとするバイナリデータとして文字列破片を結合する。 * 得られたバイナリデータ(「0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x02 0x6a 0x70 0x00」)、これがワイヤーフォーマットと言われるものである。 * バイナリの編集は難しいので、コマンドで実行する場合は、以下の通り。 | というまさにハッシュ値なのである。 意味不明なので個別に作業工程を分解する。 1. 「example.jp」を「.」で分解する(最後に暗黙の「.」がある前提)。結果は「example」「jp」「」の3つに分かれる。 1. それぞれの文字数をカウントする。「example」=「7」、「jp」=「2」、「」=「0」。 1. 文字数をバイナリとして各文字列破片に対するプレフィックスとして、全ての文字列破片を結合する。 1. 得られたバイナリデータ(「0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x02 0x6a 0x70 0x00」)、これがワイヤーフォーマットと言われるものである。 1. バイナリの編集は難しいので、コマンドで実行する場合は、以下の通り。 | 
| 行 425: | 行 361: | 
| * これをSHA1通して16進数に変換する。 | 1. これをSHA1通して16進数に変換する。 | 
| 行 436: | 行 372: | 
| ログを見るとスレーブサーバーで不思議な振る舞いが見受けられる。 example.jp ゾーン追加の際に、SOAクエリおよびゾーントランスファーで、 TSIG無しクエリ(UDP)、TSIG無しクエリ(TCP)、 TSIG有りクエリ(TCP)とリトライを繰り返してる点である。 マスターサーバー側の設定に間違いないことはこのログから確認できたわけだが(TSIG無しでは全て refused)、 スレーブサーバー側でこのような振る舞いをするのは不思議と言わざるを得ない。 とりあえず致命的では無いけど、ログ見て一瞬焦らないように注意したいところ。 | コマンド実行後のログの振る舞いを以下に示す。 | 
| 行 462: | 行 390: | 
| named[12189]: client @0x802b01a00 ns1のIPアドレス#59463 (example.jp): query 'example.jp/SOA/IN' denied named[12189]: client @0x802b03600 ns1のIPアドレス#20891 (example.jp): zone transfer 'example.jp/AXFR/IN' denied | |
| 行 481: | 行 407: | 
| named[38318]: zone example.jp/IN: refresh: unexpected rcode (REFUSED) from master ns0のIPアドレス#53 (source 0.0.0.0#0) named[38318]: zone example.jp/IN: Transfer started. named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: connected using ns1のIPアドレス#20891 named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: failed while receiving responses: REFUSED named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: Transfer status: REFUSED named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: Transfer completed: 0 messages, 0 records, 0 bytes, 0.001 secs (0 bytes/sec) | |
| 行 516: | 行 436: | 
| 今回 view は使わなかったけど、view の使い方については後述。 ゾーン転送された内容はバイナリ化されてるので、named-compilezone コマンドを使用してゾーンファイル(テキストフォーマット)に変換できる。 | 今回 view は使わなかったけど、view を使わないとできない使い方については後述。 またゾーン転送された内容はバイナリ化されてるので、named-compilezone コマンドを使用してゾーンファイル(テキストフォーマット)に変換できる。 | 
| 行 539: | 行 459: | 
| }}} === マスターサーバーでのスレーブサーバーの状態の確認 === 本例ではそれができるよう設定を行ったため、スレーブからマスターを見た先の例と同じく、マスターからスレーブの状態を確認することができる。 ※なお下記例でのnsNはns1またはns2を示す。 {{{ dig -k /usr/local/etc/namedb/ns0-nsN.key +short example.jp soa @nsNのIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key +short catalog.example soa @nsNのIPアドレス }}} ゾーン転送もお手の物。これとオリジナルのファイルの内容と比較して転送されているかを確認する。 {{{ dig -k /usr/local/etc/namedb/ns0-nsN.key example.jp axfr @nsNのIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key catalog.example axfr @nsNのIPアドレス | |
| 行 551: | 行 487: | 
| ※作業内容を確認するとわかるが、確認以外のいわゆる上記作業内容において、マスターサーバーのみ実施すれば良いことがわかる。 | |
| 行 555: | 行 493: | 
| @@ -1,5 +1,5 @@ | @@ -1,5 +1,4 @@ | 
| 行 561: | 行 499: | 
| masters                IN      A       ns0のIPアドレス @@ -7,9 +7,3 @@ label.masters IN TXT "ns0-nsN." allow-query IN APL 1:0.0.0.0/0 2:0:0:0:0:0:0:0:0/0 allow-transfer IN APL !1:0.0.0.0/0 !2:0:0:0:0:0:0:0:0/0 -eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN PTR example.jp. -masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN A ns0のIPアドレス -label.masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN A ns0のIPアドレス -label.masters.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN TXT "ns0-nsN." -allow-query.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL 1:0.0.0.0/0 2:0:0:0:0:0:0:0:0/0 -allow-transfer.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL !1:0.0.0.0/0 !2:0:0:0:0:0:0:0:0/0 }}} * とりあえず消したいゾーンは「ハッシュ値.zones」かつPTRなレコードを確認して、当該ハッシュ値を含むレコードを削除、かな。 * ハッシュ値をわざわざ計算しなくてもいいです。 | -eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN      PTR     example.jp. }}} * とりあえず消したいゾーンは「ハッシュ値.zones」かつPTRなレコードを確認して、<<当該ハッシュ値を含むレコード>>を削除、かな。 * ハッシュ値は、わざわざ計算しなくてもいいです。 | 
| 行 581: | 行 509: | 
| }}} あるいは本ケース(手抜き)の場合、以下の手順でもよい。 {{{ rndc reload catalog.example | |
| 行 608: | 行 542: | 
| = マスターサーバーによるスレーブサーバーへのポリシーの強制 = 物々しいタイトルではあるが、カタログゾーンを通じて、いくつかのポリシーをスレーブ側に強制することができる。 そのポリシーは、スレーブ側の設定によらず、マスター側の設定が正となる(設定の上書き)。 更にそのポリシーはゾーン毎に制御可能で、以下の優先度で設定がオーバーライドできる。 1. ゾーン個別設定 1. カタログゾーンデフォルト設定 1. スレーブサーバーのグローバル設定 上記優先順位の意味するところは以下の通りである。よってこれらポリシーが混ざることはない。 1. 「ゾーン個別設定」が【無ければ】「カタログゾーンデフォルト設定」に従う。 1. 「カタログゾーンデフォルト設定」が【無ければ】「スレーブサーバーのグローバル設定」に従う。 {{{#!wiki comment == ポリシーの種類 == masters IN A ns0のIPv4アドレス label.masters IN A ns0のIPv4アドレス label.masters IN TXT "ns0-nsN." allow-query IN APL 1:0.0.0.0/0 2:::/0 allow-transfer IN APL !1:0.0.0.0/0 !2:::/0 * 「masters」レコードにて、スレイブサーバーでの「masters」のデフォルトの設定を指定することができる(後述)。 * デフォルトなので後で指定するゾーン毎にこの設定は変更できる。 * 「label.masters」レコードにて、指定サーバーに対するTSIGキー名を指定することができる(後述)。 * デフォルトなので後で指定するゾーン毎にこの設定は変更できる。 * 「allow-query」レコード(allow-query.catalog.example.)と「allow-transfer」レコード(allow-transfer.catalog.example.)はカタログゾーンで運用されるゾーンに対する「allow-query 設定」と「allow-trasfer 設定」のデフォルトを示す。 * もちろんではあるが、これらレコードの設定は「catalog.example」ゾーン自体には適用されない。 ==== masters.catalog.example ==== 本レコード設定は、指定されたAレコード(orAAAAレコード)を、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{ masters { ns0のIPアドレス; }; }} デフォルトの設定となるため、今後追加されるゾーンに対しては、特に指定せずとも、指定されたマスターサーバーよりゾーン転送しようとするようになる。 またスレーブサーバー側の設定として default-masters で指定可能である。 ==== label.masters.catalog.example ==== 本レコード設定は、Aレコード・TXTレコードを、【スレーブサーバー】に対して、以下の設定を行うのと同等となる。 {{ server ns0のIPアドレス { keys "ns0-nsN."; }; }} またスレーブサーバー側の設定として default-masters で指定可能である。 ==== allow-query.catalog.example ==== 本レコード設定は、[[https://tools.ietf.org/html/rfc3123|APRレコード]]を、【スレーブサーバー】に対して、以下の設定(本例では)を行うのと同等となる。 {{ allow-query { any; }; }} 本設定によりスレーブサーバー側の設定に寄らず、本設定が「デフォルト」として機能する。 ==== allow-transfer.catalog.example ==== 本レコード設定は、[[https://tools.ietf.org/html/rfc3123|APRレコード]]を、【スレーブサーバー】に対して、以下の設定(本例では)を行うのと同等となる。 {{ allow-trasnfer { none; }; }} 本設定によりスレーブサーバー側の設定に寄らず、本設定が「デフォルト」として機能する。 * default-masters 設定についてはマスター側のカタログゾーン内における masters.catalog.example/label.masters.catalog.example レコードでの指定と同等となる。 }}} = よくある質問とその答え = == Q.allow-query/allow-transfer の指定が意味不明です。まずは解説を! == <<Include(bind9/Memo_Of_Answer_ACL)>> | 
DNSのレプリケーション設定と運用
目次
検証環境
- 以下のソフトウェアの利用を前提に検証を実施した。いずれも現時点で最新のリリースに基づいて検証しているが、ある程度古い環境、より新しい環境でも問題無いと思われる。 - OS: FreeBSD 11.2-R
- DNSコンテンツサーバー: BIND 9.13.3
 
- 上記以外の環境では、以下の点に相違が発生する。当該環境に応じて読み替えたし。 - インストール方法
- インストールされるディレクトリ
 
- 逆に以下の点は参考にできる。 - 設定パラメータとその意味
- 運用事例
 
検証内容
- DNSコンテンツサーバーの構築。以下の3台のDNSサーバーを構築する。 - マスターDNSサーバー ns0.example.jp
- スレーブDNSサーバー ns1.example.jp
- スレーブDNSサーバー ns2.example.jp
- いわゆる ns0.example.jp を隠れ(hidden)マスターとし、ns1.example.jp, ns2.exmaple.jp が対外的なサービスを提供する。
 
- 構成に当り、以下の機能を使用してゾーン転送(レプリケーション)を行う。 - AFXR/IFXRによるゾーン転送。
- TSIGキーによるマスター/スレーブの認証。
- カタログゾーン機能による、スレーブDNSサーバーの設定フリー(たぶん)。
- なおカタログゾーン機能はBIND 9.11以降の機能であるため、それ未満のサーバー上では運用できない(残念)。
- 他の実装については今時点不明。現在ドラフト状態にあり、RFCに移行するかどうかと関わってくると思われる。
 
レプリケーションについて
- この手の設定を調べてみると、あまり「レプリケーション」という「言葉」が出てこない。
- では何かというと「セカンダリDNSサーバー」「ゾーン転送」となる。
- 言わんとすることわかるけど、レプリケーションじゃないかなぁということで、ここではそのように表現しておく。
- マスター・スレイブ、プライマリ・セカンダリ、今回は関係ないけど、権威サーバー・コンテンツサーバー、キャッシュサーバー・フルリゾルバ、色々と表現あるけど、適度な使い分けで。
DNSコンテンツサーバーの基本設定(準備)
DNSコンテンツマスターサーバーの基本設定
- DNSサーバーとして ports/dns/bind913 をインストールする。 
- ここでは特にカスタムする要素は無いので、デフォルトのままとする。
- 説明のため、稼働に必要な最低限の設定とする。
/etc/rc.conf
以下の設定を追加する。
named_enable="YES" named_chrootdir="/var/named" altlog_proglist="named"
※altlog_proglist が既に設定済みの場合、「 named」を追加する。
あるいは下記コマンドを実行する(結果は同じ)。
sysrc named_enable=YES sysrc named_chrootdir=/var/named sysrc altlog_proglist+=named
/usr/local/etc/namedb/named.conf
   1 --- /usr/local/etc/namedb/named.conf.orig       2018-09-25 03:54:24.724317000 +0900
   2 +++ /usr/local/etc/namedb/named.conf    2018-11-10 21:38:31.343856000 +0900
   3 @@ -16,15 +16,22 @@
   4         dump-file       "/var/dump/named_dump.db";
   5         statistics-file "/var/stats/named.stats";
   6 
   7 +       recursion       no;
   8 +       allow-query       { none; };
   9 +       allow-recursion   { none; };
  10 +       allow-query-cache { none; };
  11 +
  12 +       allow-new-zones yes;
  13 +
  14  // If named is being used only as a local resolver, this is a safe default.
  15  // For named to be accessible to the network, comment this option, specify
  16  // the proper IP address, or delete this option.
  17 -       listen-on       { 127.0.0.1; };
  18 +       listen-on       { any; };
  19 
  20  // If you have IPv6 enabled on this system, uncomment this option for
  21  // use as a local resolver.  To give access to the network, specify
  22  // an IPv6 address, or the keyword "any".
  23 -//     listen-on-v6    { ::1; };
  24 +       listen-on-v6    { any; };
  25 
  26  // These zones are already covered by the empty zones listed below.
  27  // If you remove the related empty zones below, comment these lines out.
  28 @@ -378,3 +385,23 @@
  29         };
  30  };
  31  */
  32 +
  33 +include "/usr/local/etc/namedb/ns0-nsN.key";
  34 +
  35 +zone "catalog.example" {
  36 +       type    master;
  37 +       file    "/usr/local/etc/namedb/master/catalog.example.db";
  38 +       notify  explicit;
  39 +       allow-query {
  40 +               { !{ !ns1のIPアドレス; any; }; key "ns0-nsN."; };
  41 +               { !{ !ns2のIPアドレス; any; }; key "ns0-nsN."; };
  42 +       };
  43 +       allow-transfer {
  44 +               { !{ !ns1のIPアドレス; any; }; key "ns0-nsN."; };
  45 +               { !{ !ns2のIPアドレス; any; }; key "ns0-nsN."; };
  46 +       };
  47 +       also-notify {
  48 +                     ns1のIPアドレス          key "ns0-nsN.";
  49 +                     ns2のIPアドレス          key "ns0-nsN.";
  50 +       };
  51 +};
  52 
- DNS隠れコンテンツマスターサーバーとして、以下の設定を行うものとする。 - IPv4/IPv6問わず、全てのクエリを受け付けない。
- 原則クエリは受け付けないけど、再帰問い合わせには答えないものとする。
 
- DNSSEC設定/運用、ログ出力設定、ビュー設定といった機能については説明しない。
※カタログゾーン運用のための設定
- 「allow-new-zones yes;」を設定する。
- カタログゾーン(catalog.example)を定義する。
- このゾーンはゾーンのフリしたカタログ管理用データベースを意味し、その具体性はゾーンファイル(/usr/local/etc/namedb/master/catalog.example.db)にて定義される。
- よって named.conf レベルの設定では他のマスターゾーン定義と変わらない。
- ゾーンの命名規則については「catalog.組織名」辺りが妥当と思われる(本サイトで言うなら catalog.ninth-nine など)。
- 「catalog.localhost」辺りは実在しそうなゾーンっポイので止めておいた方がいいと思われ。
※catalog.exmaple ゾーンに関する諸設定
- マスターゾーン変更に対する通知(Notification)は明示的に指定する(notify および also-notify 設定)。
- スレイブサーバーからのSOAクエリがあるので答えられるように設定(allow-query 設定)。
- スレイブサーバーからのゾーン転送に答えられるように設定(allow-transfer 設定)
- いずれも、内容に改ざんが無いことを証明するため、TSIGキーで保護する(暗号化を意味するわけでは無い)。
/usr/local/etc/namedb/ns0-nsN.key
以下のコマンドを使用してTSIGキーを作成する。内容例については特に記載しない。
tsig-keygen -a hmac-sha256 ns0-nsN. > /usr/local/etc/namedb/ns0-nsN.key chown bind:wheel /usr/local/etc/namedb/ns0-nsN.key chmod 0400 /usr/local/etc/namedb/ns0-nsN.key
/usr/local/etc/namedb/master/catalog.example.db
$TTL    3600
@               IN      SOA     . . ( 1 86400 3600 86400 3600 )
                IN      NS      invalid.
version         IN      TXT     "1"- ゾーン定義ではSOAとNSレコードの指定が必須なので、以下のように設定する。 - 特に意味を持たないのでSOAの指定はシンプルに(だそうで)。
- NSレコードも参照されないのでテキトーに(だそうで)。
 
- よってカタログゾーン運用のための本質的に必要なレコード「version」(つまり version.catalog.example.)が最低でも必須となる。 - これはテキストレコードで、現時点で「1」だけとなる。
- 今後カタログゾーン自体の仕様変更があれば、この「version」の指定が変わることが予定されている。
- なお「1」以外の指定の場合の振る舞いは知らないし、調べる気もない。
 
DNSコンテンツスレーブサーバーの基本設定
- DNSサーバーとして ports/dns/bind913 をインストールする。 
- ここでは特にカスタムする要素は無いので、デフォルトのままとする。
- 説明のため、稼働に必要な最低限の設定とする。
/etc/rc.conf
以下の設定を追加する。
named_enable="YES" named_chrootdir="/var/named" altlog_proglist="named"
※altlog_proglist が既に設定済みの場合、「 named」を追加する。
あるいは下記コマンドを実行する(結果は同じ)。
sysrc named_enable=YES sysrc named_chrootdir=/var/named sysrc altlog_proglist+=named
/usr/local/etc/namedb/catalog/ ディレクトリ
install -d -o bind -g wheel -m 0755 /usr/local/etc/namedb/catalog
/usr/local/etc/namedb/named.conf
   1 --- /usr/local/etc/namedb/named.conf.orig       2018-10-11 00:09:07.998066000 +0900
   2 +++ /usr/local/etc/namedb/named.conf    2018-11-10 22:10:47.557521000 +0900
   3 @@ -16,15 +16,28 @@
   4         dump-file       "/var/dump/named_dump.db";
   5         statistics-file "/var/stats/named.stats";
   6 
   7 +       recursion       no;
   8 +       allow-query       { any;  };
   9 +       allow-recursion   { none; };
  10 +       allow-query-cache { none; };
  11 +
  12 +       allow-new-zones yes;
  13 +       catalog-zones {
  14 +               zone            "catalog.example"
  15 +               zone-directory  "/usr/local/etc/namedb/catalog"
  16 +               in-memory       no
  17 +               default-masters { ns0のIPアドレス key "ns0-nsN."; };
  18 +       };
  19 +
  20  // If named is being used only as a local resolver, this is a safe default.
  21  // For named to be accessible to the network, comment this option, specify
  22  // the proper IP address, or delete this option.
  23 -       listen-on       { 127.0.0.1; };
  24 +       listen-on       { any; };
  25 
  26  // If you have IPv6 enabled on this system, uncomment this option for
  27  // use as a local resolver.  To give access to the network, specify
  28  // an IPv6 address, or the keyword "any".
  29 -//     listen-on-v6    { ::1; };
  30 +       listen-on-v6    { any; };
  31 
  32  // These zones are already covered by the empty zones listed below.
  33  // If you remove the related empty zones below, comment these lines out.
  34 @@ -378,3 +391,20 @@
  35         };
  36  };
  37  */
  38 +
  39 +include "/usr/local/etc/namedb/ns0-nsN.key";
  40 +
  41 +zone "catalog.example" {
  42 +       type    slave;
  43 +       file    "/usr/local/etc/namedb/slave/catalog.example.db";
  44 +       notify  no;
  45 +       masters {
  46 +               ns0のIPアドレス key "ns0-nsN.";
  47 +       };
  48 +       allow-query {
  49 +               !{ !ns0のIPアドレス; any; }; key "ns0-nsN.";
  50 +       };
  51 +       allow-transfer {
  52 +               !{ !ns0のIPアドレス; any; }; key "ns0-nsN.";
  53 +       };
  54 +};
  55 
- DNSコンテンツスレーブサーバーとして、以下の設定を行うものとする。 - IPv4/IPv6問わず、全てのクエリを受け付ける。
- 再帰問い合わせには答えないものとする。
 
- DNSSEC設定/運用、ログ出力設定、ビュー設定といった機能については説明しない。
※カタログゾーン運用のための設定
- 「allow-new-zones yes;」を設定する。
- カタログゾーン設定(catalog-zones)を行う。 - zone 設定によりカタログゾーンを指定する(指定されたゾーンの内容は別途定義)。
- zone-directory 設定により追加されたゾーンファイルの収容先ディレクトリを指定する(デフォルトで /usr/local/etc/namedb/working/)。 
- in-memory 設定によりファイルに保存するか決める(no の場合)。
- 内部ではLMDBにより管理されている。
- default-masters 設定によりカタログゾーンで定義されるゾーンのデフォルト masters が指定される。
 
※catalog.exmaple ゾーンに関する諸設定
- このスレーブゾーンを更にマスターにするような運用はしない(notify, allow-transfer 設定による明示的な無効化)。
- 特に必要ないのだが、マスターからの問い合わせ(クエリおよびゾーン転送)に回答できるようにしておく(気が向いた時のデバッグ用)。
- 繰り返しとなるが、このゾーン自体はサービスゾーンではないので、外部からのクエリに答える必要は無い。
/usr/local/etc/namedb/ns0-nsN.key
ns0.example.jp サーバーよりTSIGキーをコピーする。
scp -p root@ns0.example.jp:/usr/local/etc/namedb/ns0-nsN.key /usr/local/etc/namedb/ chown bind:wheel /usr/local/etc/namedb/ns0-nsN.key chmod 0400 /usr/local/etc/namedb/ns0-nsN.key
ゾーンの追加
- example.jp ゾーンを追加してみる。
- マスターサーバーにおいて、以下の4つ作業を実施する。 - 当該ゾーンファイル(/usr/local/etc/namedb/master/example.jp.db)の作成。
- ゾーン設定の追加(named.conf の zone 設定)。
- カタログゾーン(catalog.example)への当該ゾーン情報追加。
- リロード(rndc reload)。
 
※作業内容を確認するとわかるが、確認以外のいわゆる上記作業内容において、マスターサーバーのみ実施すれば良いことがわかる。
/usr/local/etc/namedb/master/example.jp.db
$TTL   300
@               IN SOA ns0.example.jp. domain.example.jp. (
                        2018111101 ; serial
                        7200      ; refresh (2 hours)
                        900       ; retry (15 minutes)
                        2419200   ; expire (4 weeks)
                        86400     ; minimum (1 day)
                       )
                IN NS ns1
                IN NS ns2
ns1             IN A  ns1のIPアドレス
ns2             IN A  ns2のIPアドレス
/usr/local/etc/namedb/named.conf
   1 --- /usr/local/etc/namedb/named.conf.orig       2018-11-11 20:34:01.464258000 +0900
   2 +++ /usr/local/etc/namedb/named.conf    2018-11-11 20:50:14.935238000 +0900
   3 @@ -405,3 +405,21 @@
   4                       ns2のIPアドレス                        key "ns0-nsN.";
   5         };
   6  };
   7 +
   8 +zone "example.jp" {
   9 +       type    master;
  10 +       file    "/usr/local/etc/namedb/master/example.jp.db";
  11 +       notify  explicit;
  12 +       allow-query {
  13 +               { !{ !ns1のIPアドレス; any; }; key "ns0-nsN."; };
  14 +               { !{ !ns2のIPアドレス; any; }; key "ns0-nsN."; };
  15 +       };
  16 +       allow-transfer {
  17 +               { !{ !ns1のIPアドレス; any; }; key "ns0-nsN."; };
  18 +               { !{ !ns2のIPアドレス; any; }; key "ns0-nsN."; };
  19 +       };
  20 +       also-notify {
  21 +                     ns1のIPアドレス          key "ns0-nsN.";
  22 +                     ns2のIPアドレス          key "ns0-nsN.";
  23 +       };
  24 +};
  25 
/usr/local/etc/namedb/master/catalog.example.db
   1 --- /usr/local/etc/namedb/master/catalog.example.db.orig        2018-11-11 19:22:56.198224000 +0900
   2 +++ /usr/local/etc/namedb/master/catalog.example.db     2018-11-11 21:32:18.140863000 +0900
   3 @@ -1,4 +1,5 @@
   4  $TTL   3600
   5 -@              IN      SOA     . . ( 1 86400 3600 86400 3600 )
   6 +@              IN      SOA     . . ( 2 86400 3600 86400 3600 )
   7                 IN      NS      invalid.
   8  version                IN      TXT     "1"
   9 +eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN      PTR     example.jp.
  10 
※カタログゾーン機能の一番の肝がこの行に集約される。
「eb7b38678a581b9e32078e8b009d0c5c789bce7a」というハッシュ値と思われる文字列の作り方は、 『「example.jp」のワイヤーフォーマット(wire format)をSHA1通して16進変換したもの』 というまさにハッシュ値なのである。
意味不明なので個別に作業工程を分解する。
- 「example.jp」を「.」で分解する(最後に暗黙の「.」がある前提)。結果は「example」「jp」「」の3つに分かれる。
- それぞれの文字数をカウントする。「example」=「7」、「jp」=「2」、「」=「0」。
- 文字数をバイナリとして各文字列破片に対するプレフィックスとして、全ての文字列破片を結合する。
- 得られたバイナリデータ(「0x07 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x02 0x6a 0x70 0x00」)、これがワイヤーフォーマットと言われるものである。
- バイナリの編集は難しいので、コマンドで実行する場合は、以下の通り。
printf '\7example\2jp\0'
- これをSHA1通して16進数に変換する。
printf '\7example\2jp\0' | openssl sha1
リロード
マスターサーバーにて、以下のコマンドで再読み込みする。
rndc reload
コマンド実行後のログの振る舞いを以下に示す。
マスターサーバーのログ
named[12189]: received control channel command 'reload' named[12189]: loading configuration from '/usr/local/etc/namedb/named.conf' : named[12189]: reloading configuration succeeded named[12189]: reloading zones succeeded named[12189]: zone example.jp/IN: loaded serial 2018111101 named[12189]: all zones loaded named[12189]: zone example.jp/IN: sending notifies (serial 2018111101) named[12189]: zone catalog.example/IN: loaded serial 2 named[12189]: zone catalog.example/IN: sending notifies (serial 2) named[12189]: running named[12189]: client @0x802b09800 ns1のIPアドレス#38989/key ns0-nsn (catalog.example): transfer of 'catalog.example/IN': AXFR-style IXFR started: TSIG ns0-nsn (serial 2) named[12189]: client @0x802b09800 ns1のIPアドレス#38989/key ns0-nsn (catalog.example): transfer of 'catalog.example/IN': AXFR-style IXFR ended : named[12189]: client @0x802b0a600 ns1のIPアドレス#58236/key ns0-nsn (example.jp): transfer of 'example.jp/IN': AXFR started: TSIG ns0-nsn (serial 2018111101) named[12189]: client @0x802b0a600 ns1のIPアドレス#58236/key ns0-nsn (example.jp): transfer of 'example.jp/IN': AXFR ended named[12189]: client @0x802b01a00 ns1のIPアドレス#51278: received notify for zone 'example.jp'
スレーブサーバーのログ
named[38318]: client @0x802b02800 ns0のIPアドレス#61756/key ns0-nsn: received notify for zone 'example.jp': TSIG 'ns0-nsn': not authoritative named[38318]: client @0x802b01a00 ns0のIPアドレス#55618/key ns0-nsn: received notify for zone 'catalog.example': TSIG 'ns0-nsn' named[38318]: zone catalog.example/IN: notify from ns0のIPアドレス#55618: serial 2 named[38318]: zone catalog.example/IN: Transfer started. named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: connected using ns1のIPアドレス#38989 TSIG ns0-nsn named[38318]: catz: updating catalog zone 'catalog.example' with serial 2 named[38318]: zone catalog.example/IN: transferred serial 2: TSIG 'ns0-nsn' named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: Transfer status: success named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: Transfer completed: 1 messages, 15 records, 578 bytes, 0.001 secs (578000 bytes/sec) named[38318]: catz: adding zone 'example.jp' from catalog 'catalog.example' - success named[38318]: zone example.jp/IN: Transfer started. named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: connected using ns1のIPアドレス#58236 TSIG ns0-nsn named[38318]: zone example.jp/IN: transferred serial 2018111101: TSIG 'ns0-nsn' named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: Transfer status: success named[38318]: transfer of 'example.jp/IN' from ns0のIPアドレス#53: Transfer completed: 1 messages, 6 records, 259 bytes, 0.003 secs (86333 bytes/sec) named[38318]: zone example.jp/IN: sending notifies (serial 2018111101)
スレーブサーバーで運用しているゾーン情報の確認
ゾーン転送された内容はバイナリ化されてるので、named-compilezone コマンドを使用してゾーンファイル(テキストフォーマット)に変換できる。
named-compilezone -f raw -F text -o /dev/stdout catalog.example /usr/local/etc/namedb/slave/catalog.example.db
※なお -f と -o オプションは必須である。-F オプションは体裁整えただけ(-f, -F オプションともに text がデフォルト)、ということで。
これに例えば | awk '/PTR/{ print $3 }' とフィルタしてしまえば、運用ゾーンの一覧が取得できたりする。
スレーブサーバーでのゾーン個別の転送状態の確認
カタログゾーンにより転送されたゾーン情報は /usr/local/etc/namedb/catalog/__catz___default_catalog.example_example.jp.db というファイルに保存される。
- 「/usr/local/etc/namedb/catalog/」は zone-directory で指定したディレクトリ。 
- 「__catz__」はカタログゾーンを示すプレフィックス。 
- 「_default」はデフォルトビュー(view _default)を示す(今回 view は未使用のため)。 
- 「catalog.example」はカタログゾーン名を示す。 
- 「example.jp」は転送されたゾーン名となる。 
この事から、スレーブサーバーでは、複数のマスターサーバーからの同期を想定していることが予想される。 今回 view は使わなかったけど、view を使わないとできない使い方については後述。
またゾーン転送された内容はバイナリ化されてるので、named-compilezone コマンドを使用してゾーンファイル(テキストフォーマット)に変換できる。
named-compilezone -f raw -F text -o /dev/stdout example.jp /usr/local/etc/namedb/catalog/__catz___default_catalog.example_example.jp.db
※なお -f と -o オプションは必須である。-F オプションは体裁整えただけ(-f, -F オプションともに text がデフォルト)、ということで。
スレーブサーバーでのマスターサーバーの状態の確認
マスターサーバーのゾーン定義で許可された allow-query 設定により、スレーブサーバーからマスターサーバーの状態を確認できる。
dig -k /usr/local/etc/namedb/ns0-nsN.key +short example.jp soa @ns0のIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key +short catalog.example soa @ns0のIPアドレス
ゾーン転送もお手の物。これと先のファイルの内容と比較して転送されているかを確認する。
dig -k /usr/local/etc/namedb/ns0-nsN.key example.jp axfr @ns0のIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key catalog.example axfr @ns0のIPアドレス
マスターサーバーでのスレーブサーバーの状態の確認
本例ではそれができるよう設定を行ったため、スレーブからマスターを見た先の例と同じく、マスターからスレーブの状態を確認することができる。
※なお下記例でのnsNはns1またはns2を示す。
dig -k /usr/local/etc/namedb/ns0-nsN.key +short example.jp soa @nsNのIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key +short catalog.example soa @nsNのIPアドレス
ゾーン転送もお手の物。これとオリジナルのファイルの内容と比較して転送されているかを確認する。
dig -k /usr/local/etc/namedb/ns0-nsN.key example.jp axfr @nsNのIPアドレス dig -k /usr/local/etc/namedb/ns0-nsN.key catalog.example axfr @nsNのIPアドレス
ゾーンの削除
- 先に追加した example.jp ゾーンを削除してみる。基本的には追加工程の反対の作業となる。
- マスターサーバーにおいて、以下の4つ作業を実施する。 - カタログゾーン(catalog.example)への当該ゾーン情報の削除。
- ゾーン設定の削除(named.conf の zone 設定の削除)。
- 当該ゾーンファイル(/usr/local/etc/namedb/master/example.jp.db)の削除。
- リロード(rndc reload)。
 
- 本質的には1と4だけ実行すればスレーブサーバーからは消える。
- よって本例では1と4の工程だけ説明する。もちろん運用上は2と3も作業すること(少なくともコメントアウトはしよう)。
※作業内容を確認するとわかるが、確認以外のいわゆる上記作業内容において、マスターサーバーのみ実施すれば良いことがわかる。
/usr/local/etc/namedb/master/catalog.example.db
   1 --- /usr/local/etc/namedb/master/catalog.example.db.orig        2018-11-11 21:32:18.140863000 +0900
   2 +++ /usr/local/etc/namedb/master/catalog.example.db     2018-11-11 23:44:01.315413000 +0900
   3 @@ -1,5 +1,4 @@
   4  $TTL   3600
   5 -@              IN      SOA     . . ( 2 86400 3600 86400 3600 )
   6 +@              IN      SOA     . . ( 3 86400 3600 86400 3600 )
   7                 IN      NS      invalid.
   8  version                IN      TXT     "1"
   9 -eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN      PTR     example.jp.
  10 
- とりあえず消したいゾーンは「ハッシュ値.zones」かつPTRなレコードを確認して、<<当該ハッシュ値を含むレコード>>を削除、かな。
- ハッシュ値は、わざわざ計算しなくてもいいです。
リロード
マスターサーバーにて、以下のコマンドで再読み込みする。
rndc reload
あるいは本ケース(手抜き)の場合、以下の手順でもよい。
rndc reload catalog.example
マスターサーバーのログ
named[12189]: received control channel command 'reload' named[12189]: loading configuration from '/usr/local/etc/namedb/named.conf' : named[12189]: zone catalog.example/IN: loaded serial 3 named[12189]: zone catalog.example/IN: sending notifies (serial 3) named[12189]: client @0x802b03600 ns1のIPアドレス#26365/key ns0-nsn (catalog.example): transfer of 'catalog.example/IN': AXFR-style IXFR started: TSIG ns0-nsn (serial 3) named[12189]: client @0x802b03600 ns1のIPアドレス#26365/key ns0-nsn (catalog.example): transfer of 'catalog.example/IN': AXFR-style IXFR ended
スレーブサーバーのログ
named[38318]: client @0x802b01a00 ns0のIPアドレス#51757/key ns0-nsn: received notify for zone 'catalog.example': TSIG 'ns0-nsn' named[38318]: zone catalog.example/IN: notify from ns0のIPアドレス#51757: serial 3 named[38318]: zone catalog.example/IN: Transfer started. named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: connected using ns1のIPアドレス#26365 TSIG ns0-nsn named[38318]: catz: updating catalog zone 'catalog.example' with serial 3 named[38318]: zone catalog.example/IN: transferred serial 3: TSIG 'ns0-nsn' named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: Transfer status: success named[38318]: transfer of 'catalog.example/IN' from ns0のIPアドレス#53: Transfer completed: 1 messages, 9 records, 358 bytes, 0.005 secs (71600 bytes/sec) named[38318]: catz: deleting zone 'example.jp' from catalog 'catalog.example' - success named[38318]: catz: catz_delzone_taskaction: zone 'example.jp' deleted
マスターサーバーによるスレーブサーバーへのポリシーの強制
物々しいタイトルではあるが、カタログゾーンを通じて、いくつかのポリシーをスレーブ側に強制することができる。 そのポリシーは、スレーブ側の設定によらず、マスター側の設定が正となる(設定の上書き)。 更にそのポリシーはゾーン毎に制御可能で、以下の優先度で設定がオーバーライドできる。
- ゾーン個別設定
- カタログゾーンデフォルト設定
- スレーブサーバーのグローバル設定
上記優先順位の意味するところは以下の通りである。よってこれらポリシーが混ざることはない。
- 「ゾーン個別設定」が【無ければ】「カタログゾーンデフォルト設定」に従う。
- 「カタログゾーンデフォルト設定」が【無ければ】「スレーブサーバーのグローバル設定」に従う。
よくある質問とその答え
Q.allow-query/allow-transfer の指定が意味不明です。まずは解説を!
A.BIND9のACL(Access Controll Lists)の癖となります。詳しくは参考文献をお読みください。 というのは不親切なので、解説すると、
- ACLの処理はリストの左から右へ評価されます。これはAND結合であるということを意味しません。
- よってブール論理で解釈するのではなく、ファーストマッチ・ファーストアウトで解釈する必要があります。
- 接続元IPアドレスに対して、以下の3つが判断されます。 - match and accept(一致かつ受諾)
- match and reject(一致かつ拒絶)
- no match(一致しない、なので次のリストに委ねる)
 
- これは「!」(reject)と「 」(accept、「!」が指定されてない)のニュアンスが直感的に違うことを意味します(今まで一致・不一致に見えませんでしたか?)。
- ネスト({・・・})されていた場合、その内容について下記の2つの評価を行い(ここでは一致・不一致の直感とマッチする)、その結果に対して上記3つの判断が実施されます。 - match(一致)
- no match(不一致)
 
- 当然ネストの中に更にネストできるので、それは上記2評価(match または no match)の繰り返しとなる。
上記ルールを踏まえ、問題のルールを解析すると・・・。
- 大枠は2つのリストに分かれる(「!」の意味に注意)。 - !{ !IPv4アドレス; !IPv6アドレス; any; } → match and reject
- key "TSIGキー名." → accept or reject
 
- 最初のネストを分解すると、3つのリストに分かれる。 - !IPv4アドレス → 一致した場合「no match」という評価で完了
- !IPv6アドレス → 一致した場合「no match」という評価で完了
- any → 一致(常に一致する)した場合「match」という評価で完了
 
上記をまとめて解釈すると、
- 最初のネスト内では以下の評価を行う(「!」の評価に注意)。 - 「IPv4アドレス『ではない』」の評価をする。 - 指定された「IPv4アドレス」であれば「no match」として評価完了。
- そうでないなら「match」として次の評価。
 
- 「IPv6アドレス『ではない』」の評価をする。 - 指定された「IPv6アドレス」であれば「no match」として評価完了。
- そうでないなら「match」として次の評価。
 
- 「any」(任意の全てのアドレス)に・・・とここまで来ると常に match と解釈され、評価が終了する。
- また any の時点で既に、「match」評価されてるので、この場合の「any」の指定のあり/無しに意味はない - ※人間の直感には反するから入れておいた方がいい。
 
 
- 「IPv4アドレス『ではない』」の評価をする。 
- このネストでの結果を全体「!」=match and reject で評価することから、「no match」(つまり次のリストの評価)の時は、次のリスト key が評価される。
付録1.APRレコード
- APRレコードは早々見ないレコードなので簡単に解説。
- 1レコード中に複数指定可能。
- [ |!]<1|2>:<IPv4|IPv6>/<プレフィックス> という4つの構成からなる。 
- 先頭の「!」が無い場合はマッチ、ある場合は「マッチしない」を意味する。
- 次の「1」または「2」はアドレスファミリーを意味し、1=「IPv4」、2=「IPv6」となる。
- プレフィックスにより指定されたアドレスの範囲が指定される。
