はじめに
DNSコンテンツサーバーを自前で運用しなくなった時代ではありますが、そんな運用をしないといけない人向けに、運用負荷低減のための仕組みついて紹介します。
具体的にはプライマリーコンテンツサーバー1とセカンダリーコンテンツサーバー2間でゾーン管理を簡易化する仕組みであるところの「カタログゾーン」(catalog zones)機能について説明します。
なお従来、マスター・スレーブと呼称していたこれら名称は、(ポリティカルコレクトネス的要請により削除)のため、プライマリー・セカンダリーと呼称するようになりました。
互換性の観点から type master;
および type slave;
といった設定は使えますが、type primary;
および type secondary;
という設定に置き換えて行きましょう!
一応(ポリティカルコレクトネス的要請により削除)のため、権威サーバーという表現もコンテンツサーバーと表現するようにしています。まぁこちらは実務的な話ではありますが。
なお本題において、BIND9の設定を行ったことがある人を対象に書いています。想定バージョンは9.18です。
カタログゾーンとは
カタログゾーンは、プライマリーサーバーからセカンダリサーバーへ「転送すべきゾーン」を管理するためのゾーンです。
ゾーンの形式を取ることで、プライマリーサーバー・セカンダリーサーバー間の管理すべきゾーン情報を、従来のAXFR/IXFRを通して共有できるようになります。
ゾーンを管理するゾーンということで、各種ゾーン機能(クエリー応答の可否、転送可否など)を制御して、プライマリーサーバーで管理しているゾーンをセカンダリーサーバーでも設定されます。セカンダリーサーバーの設定変更無しに、プライマリーサーバー側だけで自由にゾーンの追加・削除を行うことができるようになります。
これは従来の運用形態から考えると設定漏れが起きにくい仕組みではあります。合わせてセカンダリーサーバーで作業しなくてよいメリットがあります。
この機能に対応しているサーバーはBIND9、KnotDNS、PowerDNSであることを確認しています(サポート状態は未確認)。
ここではフルスペック(プライマリーサーバー・セカンダリーサーバー共に)で対応しているBIND9を例に説明します。
なお本機能はBIND9.11より対応(バージョン1)していますが、BIND9.18.3以降対応のバージョン2で例示します。
プライマリーコンテンツDNSサーバーでのカタログゾーンの設定
named.conf
側には allow-new-zones
の設定と、catalog.exmaple
ゾーンの追加を実施します。
catalog.example
というゾーン名は catalog.屋号
程度に設定しておくのがよいと思います。
運用上どれくらい自由度があるのかは不明ですが、実在しそうに無い、ジャンクなゾーン名がいいかもしれません。
下手な名前にすると混乱を引き起こす可能性がありますが。
下記例では、極めてミニマムに設定しています。このゾーン自体はセカンダリーサーバーからしかアクセスがないので、アクセス制限を実施するなどの配慮が必要です。
この例ではセカンダリーサーバーのIPアドレスアドレスからの問い合わせかつ、特定のTSIGキー(後述)による問い合わせが行われていること、でアクセスを制限しています。
options {
allow-new-zones yes;
}
zone "catalog.example" {
type primary;
file "primary/catalog.example.db";
allow-query {
{ !{ !セカンダリーサーバーのIPアドレスv4/32; "any"; }; key "TSIGキー名"; };
{ !{ !セカンダリーサーバーのIPアドレスv6/128; "any"; }; key "TSIGキー名"; };
};
allow-transfer {
{ !{ !セカンダリーサーバーのIPアドレスv4/32; "any"; }; key "TSIGキー名"; };
{ !{ !セカンダリーサーバーのIPアドレスv6/128; "any"; }; key "TSIGキー名"; };
};
};
また上記設定に合わせるようにゾーン情報を書きます。この部分の書き方については下記のテンプレそのまま利用します。
@ IN SOA . . 1 86400 3600 86400 3600
@ IN NS invalid.
version IN TXT "2"
- SOAレコードのシリアルを1から始めてますが、日付ベースの指定でも構いません。
- いずれにせよレコード変更の度にシリアルを上げます。
- ゾーンを構成するため、SOAとNSレコードが(ダミーでも)必須。
- カタログゾーンとして運用するためには
version
レコードが必須となります。
セカンダリーコンテンツDNSサーバーでのカタログゾーンの設定
options {
catalog-zones {
zone "catalog.example";
};
};
zone "catalog.example" {
type secondary;
file "secondary/catalog.example.db";
primaries { プライマリーサーバーのIPアドレス key "TSIGキー名"; }
};
プライマリーサーバー/セカンダリーサーバー間で共有するTSIGキー
プライマリーサーバー側でTSIGキーを生成します。
「TSIGキー名」は何でも構わないのですが、どういう名前にするのか悩んだ場合、BIND9のマニュアルによれば、プライマリーサーバーのホスト名とセカンダリーのホスト名を繋いだものが例示されています。
プライマリーサーバーを ns0.example.jp
、セカンダリーを ns1.example.jp
とした時、ns0-ns1.
という名前で、TSIGキーファイル名は ns0-ns1.key
となります。
$ sudo tsig-keygen -a hmac-sha256 TSIGキー名 > TSIGキー.key
$ sudo chmod 0400 TSIGキー.key
このファイルをセカンダリーにもコピーします。プライマリーサーバーもセカンダリサーバーも同じく、named.conf には以下のような形で設定を読み込みます。
include "TSIGキー.key";
ゾーンの追加方法
example.jp
というゾーンを追加してみます。
事前に、プライマリーサーバー側にてゾーンファイルの作成および zone "example.jp" { ... };
の設定を行った後、カタログゾーンにレコードを追加します。
まずこのゾーン名からハッシュ値を生成します。シンプルにワイヤー形式をSHA1でハッシュ化します。
取り出しましたる eb7b38678a581b9e32078e8b009d0c5c789bce7a
という文字列を下記のように設定します。
@ IN SOA . . 2 86400 3600 86400 3600
eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN PTR example.jp.
その後 rndc reload
でゾーンファイルを読み直します。
ワイヤー形式
ハッシュ値を計算するための元となるワイヤー形式(wire format)について説明します。
これの定義についてはRFC1035の 3.1 Name space definitions
に準拠します。
ドメイン名(ゾーン名) example.jp
を例に取ると、以下のようにして組み立てす。
-
.
を基準に分割します。その際、最後に.
があるものとして3つに分割します。 - 具体的には
exmaple
、jp
、 - 各文字列を数えます。7文字、2文字、0文字となります。
- 各レベルの直前に文字数をバイナリ(1オクテットの)で表現して
printf "\7example\2jp\0"
コマンドを実行します(バイナリです)。
この時得られるバイナリのことをワイヤー形式となります。
$ printf "\7example\2jp\0" | hexdump -C
00000000 07 65 78 61 6d 70 6c 65 02 6a 70 00 |.example.jp.|
0000000c
これをSHA1でハッシュ化します。
$ printf "\7example\2jp\0" | openssl sha1
(stdin)= eb7b38678a581b9e32078e8b009d0c5c789bce7a
この時得られた eb7b38678a581b9e32078e8b009d0c5c789bce7a
をカタログゾーンに設定します。
実装依存のカスタムプロパティの指定
セカンダリサーバーでの挙動を制御するためのカスタムプロパティが設定できます。
このカスタムプロパティは実装依存で、以下の説明ではBIND9の仕様に基づいて説明しています。
他のサーバーでは機能する保証が無いため、都度確認する必要があります。
デフォルトプライマリーサーバーの指定
以下の設定を行うことで、デフォルトのプライマリーサーバーを指定することができます。
label.primaries.ext IN A XXX.XXX.XXX.XXX
label.primaries.ext IN AAAA XXXX::XXX
label.primaries.ext IN TXT "TSIGキー名"
-
label.primaries.ext
でプライマリーサーバー情報を設定します。 - AおよびAAAAレコードで、プライマリーサーバーのIPアドレスを設定します。
- TXTレコードでTSIGキー名を指定します。
これはセカンダリサーバーに対して下記のを行ったのと同じになります。なお同時に設定した場合の振る舞い(どちらを優先するか)は未確認です。
options {
catalog-zones {
zone "catalog.example"
default-primaries {
プライマリーサーバーのIPv4アドレス key "TSIGキー名";
プライマリーサーバーのIPv6アドレス key "TSIGキー名";
};
};
};
デフォルトのクエリー許可設定
TODO
allow-query.ext IN APL 1:0.0.0.0/0 2:::/0
デフォルトのゾーン転送許可設定
TODO
allow-query.ext IN APL 1!:0.0.0.0/0 2!:::/0
ゾーン毎のカスタムの事例
TODO
label.primaries.ext.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN A XXX.XXX.XXX.XXX
label.primaries.ext.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN AAAA XXXX::XXX
label.primaries.ext.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN TXT "TSIGキー名"
allow-query.ext.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL 1:0.0.0.0/0 2:::/0
allow-query.ext.eb7b38678a581b9e32078e8b009d0c5c789bce7a.zones IN APL 1!:0.0.0.0/0 2!:::/0
よくある質問とその答え
TODO
Q.primaries.ext
レコードと label.primaries.ext
レコードがあるようですが、違いは何?
A.どちらもプライマリーサーバーを指定するモノですが、後者はTSIGキーを指定して、アクセス制御(認証)を行う点が違います。前者の使用は推奨されませんので、ここでは無視します。
Q.primaries.ext
レコードと label.primaries.ext
レコードを同時に指定した場合の振る舞いは?
A.知らんでもいい…のですが、試したところ、指定された分、下記の設定とイコールになります。
options {
catalog-zones {
zone "catalog.example"
default-primaries {
primaries.ext で指定されたIPアドレス;
label.primaries.ext で指定されたIPアドレス key "TSIGキー名";
};
};
};
この時 primaries.ext
で指定された分のアクセスが行われた後、label.primaries.ext
で指定された分のアクセスがラウンドロビンで実施されます3。
Q.バージョン1とバージョン2の違いは?
A.カスタムプロパティのレコードに .ext
というサフィックスが付くか、付かないかの差だそうです。多分ですが、.zones.catalog.example.
サブドメインと .ext.catalog.example.
サブドメインとで、対称的に設定させたかったのでは無いかとみてます。
Q.TODO
A.TODO
参考文献
検索して出てくる資料も悪くないですが、本家ドキュメント(英語ではありますが)を参照の上で設定しましょう。
参考資料では想定が甘かったり、抜けていたり、変っていたり、間違っているケースが多々見られます。
正しい運用は正しい設定から始まります。
- BIND9ドキュメントの概要
- BIND9最新管理者リファレンス マニュアル
- BIND9.18管理者リファレンス マニュアル
- DNSのレプリケーション設定と運用
- A short introduction to Catalog Zones
- Catalog zones in BIND 9.11
- DNSソフトウェア最新動向(権威DNSサーバー編)
- implement a Catalog zones
- ひとりRFCの旅 introduction && RFC1035 DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION