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)。署名を外す順序は次のとおりです。

  1. レジストラの管理画面で DS レコードを削除します。
  2. 親ゾーンの DS の TTL が切れるまで待ちます。余裕を見て1〜2日待つと安心です。
  3. 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 は切り戻しのために残しておきます。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲