2026年6月7日
2026年6月7日
BIND から TinyDNS へ移行する手順|axfr-get でゾーンを変換し、DNSSEC・シリアル・NS を切り替える
BIND の権威ゾーンを TinyDNS に移すには、djbdns に含まれる axfr-get で BIND からゾーン転送(AXFR)を受け、TinyDNS の data 形式に変換するのが手早い方法です。ゾーンファイルを手で書き直す必要がなく、変換後のデータを並行稼働で BIND の答えと比べてから、NS を切り替えられます。ただし TinyDNS は DNSSEC・動的更新・TSIG に対応していないため、それらを使っているゾーンは移行の前に手当てが要ります。この記事では、事前の確認、変換、署名とシリアルの扱い、比較、切り替えと切り戻しまでを順に説明します。
TinyDNS のインストールは済んでいる前提です。djbdns は 1.05 以降、作者による公式な更新がありません(2026年10月現在)。移行先として TinyDNS を選ぶのは、既存の djbdns の運用にそろえたい場合や、data ファイルでの管理を重視する場合です。DNSSEC を続けたいなら、NSD や Knot DNS など署名に対応した実装への移行のほうが向いています。
移行の前に BIND の使い方を確認する
named.conf を見て、BIND が権威ゾーンを答える以外の仕事をしていないか確認します。TinyDNS は権威DNSの機能しか持たないため、ほかの役割は別の手段に移す必要があります。
sudo named-checkconf -p | grep -nE 'recursion|view|allow-update|update-policy|dnssec-policy|inline-signing|also-notify|allow-transfer|key '
- 再帰(recursion yes):社内クライアントの名前解決も BIND が担っているなら、Unbound や dnscache などのキャッシュDNSを別に用意します。
- ビュー(view):問い合わせ元によって答えを変えている場合、TinyDNS では data ファイルの「ロケーション」機能(
%の行で問い合わせ元の範囲を定義し、レコードの末尾にロケーションを付ける)で置き換えます。ビューが多い構成は移行の手間が大きくなります。 - 動的更新(allow-update・update-policy):DHCP からの登録や、ACME の DNS-01 認証を RFC 2136 の更新で行っている場合、TinyDNS では受けられません。DNS-01 であれば、
_acme-challengeを動的更新に対応した別のゾーンへ CNAME で向ける方法がよく使われます。 - DNSSEC(dnssec-policy・inline-signing):TinyDNS は署名できないので、移行前に署名をやめる手順が要ります(後述)。
- セカンダリへの配信(also-notify・allow-transfer・TSIG の key):TinyDNS は NOTIFY を送らず、TSIG にも対応しません。セカンダリをどう同期するかを決めておきます。
変換の準備:BIND からゾーン転送を許可する
axfr-get は TCP でゾーン転送を受けます。TSIG に対応していないので、変換を行うホストのアドレスからの転送を、作業の間だけ許可します。変更前に named.conf の控えを取っておきます。
// named.conf の該当ゾーン(作業の間だけ追加し、終わったら戻す)
zone "example.com" {
type primary;
file "/var/lib/bind/db.example.com";
allow-transfer { 127.0.0.1; 192.0.2.53; };
};
sudo named-checkconf && sudo rndc reconfig
dig @127.0.0.1 example.com AXFR | tail -n 3 # 転送できるか確認
古い版の BIND では type primary の代わりに type master と書かれています。どちらでも意味は同じです。
axfr-get で data 形式に変換する
axfr-get は ucspi-tcp の tcpclient と組み合わせて使います。tcpclient が接続を作り、axfr-get が受け取ったゾーンを data 形式で書き出します。
mkdir -p ~/migrate && cd ~/migrate
tcpclient 127.0.0.1 53 axfr-get example.com example.com.data example.com.tmp
less example.com.data
引数は順に、ゾーン名、書き出すファイル、作業用の一時ファイルです。転送が最後まで成功したときだけ一時ファイルが本来の名前に置き換わるので、途中で切れた場合に壊れたデータが残りません。
出力は、SOA が Z、NS が &、A が +、MX が @、CNAME が C、TXT が '、PTR が ^ の行になります。AAAA・SRV・CAA など、標準の記号がない種類は汎用レコードの : の行(種類番号と8進数のエスケープ)で書き出され、TinyDNS はそのまま答えられます。出力の細部は版やパッチによって違うことがあるので、まずはファイルを開いて全体を確認してください。
ゾーンが複数あるときは、ゾーンごとにファイルを作り、TinyDNS 側で連結して1つの data にします。
for z in example.com example.net 2.0.192.in-addr.arpa; do
tcpclient 127.0.0.1 53 axfr-get "$z" "$z.data" "$z.tmp"
done
cat *.data > data.new
AXFR が使えない事情がある場合は、named-compilezone -f raw -F text -s full -o - example.com ゾーンファイル でゾーンを省略のないテキストに展開してから変換する方法もあります。こちらは手作業か自前のスクリプトでの変換になります。
署名済みのゾーンを扱う
DNSSEC で署名しているゾーンを転送すると、RRSIG・NSEC・DNSKEY などの署名関係のレコードも汎用レコードとして書き出されます。TinyDNS はこれらを署名として扱えず、署名の期限が切れると検証に失敗するので、移行先のデータに残してはいけません。
順番は「署名をやめてから移行」です。署名したまま NS だけ切り替えると、親ゾーンの DS レコードが残っているのに署名のないゾーンが返り、検証するリゾルバからは名前解決ができなくなります。
- レジストラで DS レコードを削除します。
- 親ゾーンの DS の TTL に余裕を加えた時間が過ぎるまで待ちます。
- BIND の署名を止めます。BIND 9.18 以降の
dnssec-policyを使っている場合は、いったんdnssec-policy insecure;にして署名のない状態へ移すのが公式の手順です。版によって手順が違うので、使っている版のドキュメントを確認してください。 - 署名のない状態のゾーンをあらためて
axfr-getで取得します。
変換後のデータに署名関係のレコードが残っていないかは、種類番号で確認できます。
# 43=DS 46=RRSIG 47=NSEC 48=DNSKEY 50=NSEC3 51=NSEC3PARAM 59=CDS 60=CDNSKEY
grep -nE '^:[^:]*:(43|46|47|48|50|51|59|60):' data.new
何も表示されなければ問題ありません。DS の削除から署名の停止までの順序と待ち時間は、DNSSEC の有効化・無効化の記事で詳しく扱っています。
SOA のシリアルを決める
axfr-get が書き出した Z の行には、BIND で使っていたシリアル(2026101801 のような日付形式が多い)がそのまま入ります。TinyDNS では Z を使う限り、シリアルは自分で管理します。
ここで . の行に書き換えて自動のシリアルに任せると、問題が起きることがあります。TinyDNS の自動シリアルは data ファイルの更新時刻(1970年からの秒数)で、2026年時点では約17億9千万です。日付形式の 2026101801(約20億)より小さいため、BIND のセカンダリなど、シリアルが増えたときだけ更新するサーバーは新しいデータを取り込まなくなります。
セカンダリがある構成では Z の行を残し、変更のたびにシリアルを上げる運用にします。セカンダリを使わず、TinyDNS 同士で data.cdb をコピーして同期する構成なら、シリアルの大小は同期に影響しません。
並行稼働で答えを比べる
変換したデータを TinyDNS に置き、BIND とは別のアドレスで動かして、同じ問い合わせへの答えを比べます。
sudo cp data.new /etc/tinydns/root/data
cd /etc/tinydns/root && sudo make
比べる名前と種類の一覧は、BIND の AXFR から作ります。
dig @127.0.0.1 example.com AXFR +noall +answer \
| awk '$4 !~ /^(SOA|RRSIG|NSEC|NSEC3|NSEC3PARAM|DNSKEY|CDS|CDNSKEY)$/ {print $1, $4}' \
| sort -u > pairs.txt
while read -r name type; do
old=$(dig @192.0.2.10 +norec +noall +answer "$name" "$type" | awk '{$2=""; print}' | sort)
new=$(dig @192.0.2.53 +norec +noall +answer "$name" "$type" | awk '{$2=""; print}' | sort)
[ "$old" = "$new" ] || printf 'DIFF %s %s\n< %s\n> %s\n' "$name" "$type" "$old" "$new"
done < pairs.txt
192.0.2.10 が BIND、192.0.2.53 が TinyDNS の例です。awk '{$2=""; print}' で TTL の列を除いているので、TTL の違いは差分に出ません。長い TXT レコードは、文字列の区切り方がサーバーごとに違って差分に出ることがあります。連結した内容が同じなら問題ありません。サブドメインの委任(NS)は、どちらも委任の応答になり answer 欄が空になるので、dig +norec の authority 欄を個別に確認します。
切り替えと切り戻し
切り替えの数日前に、主要なレコードと NS の TTL を短くしておくと、問題があったときに戻しやすくなります。
切り替えの方法は2つあります。
- アドレスを引き継ぐ:TinyDNS のサーバーに BIND と同じ IP アドレスを付け替えます。レジストラでの変更が要らず、戻すときもアドレスを戻すだけです。
- NS を変える:ゾーン内の NS レコードと、レジストラに登録した NS(自ゾーン内の名前ならグルーレコードも)を TinyDNS のサーバーに変えます。親ゾーンの NS の TTL(1〜2日のことが多い)が過ぎるまでは古い NS を参照するリゾルバが残るので、その間は BIND を止めずに同じ内容を答えさせておきます。
切り替え後は、外部から dig +trace example.com で親ゾーンからの委任をたどり、新しいサーバーが aa 付きで答えていることを確認します。
問題が起きたら、アドレスや NS を BIND に戻します。BIND のゾーンファイルと設定は、移行が落ち着くまで消さずに残しておきます。最後に、作業のために追加した allow-transfer を元に戻すのを忘れないようにします。
まとめ
- BIND から TinyDNS へは、
tcpclientとaxfr-getでゾーン転送を受けて data 形式に変換するのが手早い方法です。標準の記号がない種類は汎用レコードとして変換されます。 - 再帰・ビュー・動的更新・DNSSEC・TSIG を使っているかを先に確認し、TinyDNS が持たない機能の移し先を決めます。
- 署名済みのゾーンは、DS の削除 → 待機 → 署名の停止 → 再取得の順で署名をやめてから移行し、署名関係のレコードが残っていないか確認します。
- 自動のシリアルは日付形式より小さくなるため、セカンダリがある構成では
Zの行で管理します。 - 並行稼働で全レコードの答えを比べてから、アドレスの引き継ぎか NS の変更で切り替え、古い NS の TTL が過ぎるまで BIND を残します。