2026年6月13日
2026年6月13日
Knot DNS から djbdns(tinydns)へ移行する手順|失う機能の確認・axfr-get での変換・並行稼働と切り替え
Knot DNS から djbdns の tinydns へ移行するには、「失う機能を確かめる → DNSSEC を使っていれば先に外す → Knot から AXFR でゾーンを取り出し、axfr-get で tinydns の data 形式にする → 別のアドレスで答えを比べてから切り替える」の順で進めます。ただし、djbdns は長く更新されておらず、Knot DNS が持つ DNSSEC などの機能の多くを手放すことになります。この記事では、移行してよいかの判断材料を最初に示したうえで、具体的な手順と切り戻しの方法を説明します。
移行の前に知っておきたいこと
djbdns は D. J. Bernstein 氏による DNS ソフトで、1.05(2001年)が最後の公式版です。その後パブリックドメインになり、いくつかのディストリビューションや有志が修正版を配っていますが、本家での開発は止まっています(2026年10月現在)。一方の Knot DNS は CZ.NIC が開発を続けている権威DNSサーバーです。移行すると、主に次の機能が使えなくなります。
- DNSSEC:tinydns は署名済みゾーンの配信にも対応していません。
- NOTIFY と IXFR:変更をセカンダリに知らせる仕組みがなく、差分転送もできません。
- 動的更新(RFC 2136):
nsupdateや ACME クライアントの DNS-01 チャレンジで Knot に直接書き込んでいた運用は使えなくなります。 - EDNS0:大きな応答を UDP で返せず、512バイトを超える応答は TCP に切り替わります。
- AAAA・SRV・CAA などの新しめのレコード:data ファイルの専用の記号はなく、汎用の書き方(
:の行)で表します。
すでに社内の他のサーバーが djbdns で統一されている、data ファイルを生成する仕組みが整っている、といった理由があるなら移行の意味はあります。そうでなければ、NSD や BIND など、開発が続いていて DNSSEC に対応したソフトを選ぶほうが長期的には楽です。進める場合も、上の制約を関係者と共有してから始めます。
棚卸し:ゾーンと使っている機能を確かめる
# 設定の構文確認と、設定されているゾーンの一覧
sudo knotc conf-check
sudo knotc conf-read zone.domain
# 各ゾーンの状態(シリアル、DNSSEC の署名など)
sudo knotc zone-status
設定ファイル(多くは /etc/knot/knot.conf)で、dnssec-signing: on や dnssec-policy が付いたゾーンがあれば DNSSEC を使っています。acl に action: update があれば動的更新を許可しています。動的更新で書き換えたレコードはゾーンファイルではなくジャーナルにだけ入っている場合があるため、ゾーンファイルを直接読むのではなく、次の節のようにゾーン転送で取り出すほうが漏れがありません。
DNSSEC を使っているゾーンは先に署名を外す
親ゾーン(レジストリ)に DS レコードが登録されたまま、署名のない tinydns に切り替えると、検証するリゾルバーはそのドメインを引けなくなります(SERVFAIL)。署名を外す順序は次のとおりです。
- レジストラの管理画面で DS レコードを削除します。
- 親ゾーンの DS の TTL が切れるまで待ちます。余裕を見て1〜2日待つと安心です。
dig example.com DS +shortを外部のリゾルバーで実行し、何も返らないことを確かめます。
ここまで済めば、Knot 側は署名したままでも移行の作業に入れます。署名レコードは次の変換の段階で取り除きます。CDS・CDNSKEY を使った自動更新をしている場合は、DS が再登録されないよう Knot 側の設定も見直します。
Knot からゾーンを取り出す
一時的な転送の許可
変換を行うホスト(ここでは Knot と同じサーバーの 127.0.0.1)からの AXFR を許可します。作業前に knot.conf のコピーを取っておきます。
# /etc/knot/knot.conf(追加する部分)
acl:
- id: migrate_xfr
address: 127.0.0.1
action: transfer
zone:
- domain: example.com
acl: [ migrate_xfr ]
すでにゾーンに acl: を書いている場合は、acl: [ 既存のid, migrate_xfr ] のように並べて追加します。置き換えてしまうと、既存のセカンダリへの転送が止まるので注意します。
sudo knotc conf-check && sudo knotc reload
dig @127.0.0.1 example.com AXFR +onesoa | head
axfr-get で data 形式にする
djbdns に含まれる axfr-get は、AXFR で受け取ったゾーンを tinydns-data の形式で書き出すプログラムです。ucspi-tcp の tcpclient と組み合わせて使います。
mkdir -p ~/tinydns-migrate && cd ~/tinydns-migrate
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
出力には SOA(Z)、NS(&)、A(+)、MX(@)などが専用の記号で並び、記号のない種類は汎用の :名前:種類番号:データ:TTL の行になります。DNSSEC の署名が付いたゾーンからは、RRSIG(46)・NSEC(47)・DNSKEY(48)・NSEC3(50)・NSEC3PARAM(51)・CDS(59)・CDNSKEY(60)も汎用の行として出てくるので、取り除きます。
for f in *.data; do
grep -vE '^:[^:]*:(46|47|48|50|51|59|60):' "$f" > "$f".clean
done
grep -c '' *.data *.clean
除いた後の行数と、Knot のゾーンにあるレコードの数がおおむね合うかを見ておきます。AAAA や SRV が : の行で8進数のエスケープを含む形になるのは正常です。
data ファイルにまとめる
tinydns は1つの data ファイルからすべてのゾーンを作ります。ゾーンごとのファイルを連結し、tinydns-data で data.cdb を作ります。
cat ~/tinydns-migrate/*.data.clean | sudo tee /etc/tinydns/root/data > /dev/null
cd /etc/tinydns/root && sudo make
make は内部で tinydns-data を実行し、書式に誤りがあれば止まります。SOA のシリアルは axfr-get が Knot の値をそのまま書くので、現在のシリアルが引き継がれます。今後シリアルを上げる手順(Z の行のシリアルを編集する、または空欄にして data ファイルの更新時刻を使う)を決めておきます。
tinydns と axfrdns を用意する
tinydns 自体のインストールと daemontools での起動は別記事に譲り、ここでは移行で気をつける点を挙げます。比較のため、tinydns は Knot とは別のアドレス(ここでは 192.0.2.54)で待ち受けます。
sudo tinydns-conf tinydns dnslog /etc/tinydns 192.0.2.54
sudo ln -s /etc/tinydns /etc/service/tinydns # svscan の監視ディレクトリに合わせる
tinydns は UDP でしか答えません。TCP での問い合わせ(大きな応答や、TCP を使うリゾルバー)に答えるには axfrdns も同じアドレスで動かします。axfrdns はゾーン転送だけでなく、通常の TCP の問い合わせにも答えます。セカンダリへのゾーン転送もこの axfrdns が担当し、tcp ファイルで許可する相手を決めます。NOTIFY がないため、セカンダリは SOA の refresh の間隔で取りに来るか、data.cdb を rsync などで配る運用に変えます。
並行稼働で答えを比べる
Knot(192.0.2.53)と tinydns(192.0.2.54)に同じ問い合わせをして、差分を探します。
dig @127.0.0.1 example.com AXFR +onesoa +nocmd +nostats \
| awk '!/^;/ && NF>=5 && $4!~/^(RRSIG|NSEC|NSEC3|NSEC3PARAM|DNSKEY|CDS|CDNSKEY)$/ {print $1, $4}' \
| sort -u > names.txt
while read -r name type; do
a=$(dig @192.0.2.53 "$name" "$type" +norec +short | sort)
b=$(dig @192.0.2.54 "$name" "$type" +norec +short | sort)
[ "$a" = "$b" ] || echo "DIFF: $name $type"
done < names.txt
差が出やすいのは、TXT(長い文字列の分割のされ方)、ワイルドカード、存在しない名前への応答です。dig @192.0.2.54 nothing.example.com +norec で NXDOMAIN と SOA が返るか、+tcp を付けた問い合わせに axfrdns が答えるかも確認します。
切り替えと切り戻し
切り替えの方法は2つです。
- 同じ IP アドレスを引き継ぐ:Knot を止めて自動起動を無効にし(
sudo systemctl disable --now knot)、tinydns と axfrdns の待ち受けアドレスを元のアドレスに変えます。アドレスは各サービスディレクトリのenv/IPで変えられます。停止から起動までの短い間は応答が止まります。 - NS を向け替える:レジストラで NS とグルーレコードを新しいアドレスに変え、上位の NS の TTL が切れるまでは Knot も動かしたままにします。この間はどちらのレコードも変更しないようにします。
問題が出たときは、tinydns を止め(svc -d と down ファイル)、Knot を systemctl enable --now knot で起動し直せば元に戻ります。Knot の設定とゾーンのデータは、移行が落ち着くまで消さずに残しておきます。一時的に追加した migrate_xfr の ACL は、作業が終わったら削除して knotc reload します。DNSSEC を外したゾーンは、そのまま署名のない状態になる点も運用の記録に残しておきます。
まとめ
- djbdns は本家の開発が止まっており、DNSSEC・NOTIFY・動的更新・EDNS0 を失うことを確かめてから移行を決めます。
- DNSSEC のゾーンは、DS を削除して TTL が切れるのを待ってから移行します。
- Knot に一時的な転送の ACL を足し、
tcpclientとaxfr-getで data 形式に変換し、署名関係の行を取り除きます。 - tinydns は UDP だけなので、TCP とゾーン転送のために axfrdns も動かします。
- 別のアドレスで全レコードを比べてから切り替え、Knot は切り戻しのために残しておきます。