2026年6月11日

2026年6月11日

PowerDNS から BIND へ移行する手順|ゾーンの書き出し・独自レコードの置き換え・DNSSEC と NS の切り替え

PowerDNS Authoritative Server から BIND への移行は、「pdnsutil でゾーンを書き出す → PowerDNS 独自の機能を置き換える → BIND を別のアドレスで動かして答えを比べる → DNSSEC を考慮して切り替える」の順で進めると、名前解決を止めずに済みます。いちばんの難所は DNSSEC で、署名済みのゾーンを手順を誤って切り替えると、検証するリゾルバーから名前が引けなくなります。この記事では、棚卸しから切り替え後の後片付けまでを順に説明します。

移行前の棚卸し

PowerDNS はデータベースなどのバックエンドにレコードを持ち、API や管理画面から更新する使い方が多いソフトです。BIND はゾーンファイル(または動的更新)が中心なので、まず今の運用で何に頼っているかを洗い出します。

# PowerDNS の版とバックエンド
pdns_server --version
grep -E '^(launch|api|webserver|resolver|expand-alias|enable-lua-records)' /etc/powerdns/pdns.conf

# ゾーンの一覧
pdnsutil list-all-zones

# ゾーンごとの DNSSEC の状態とメタデータ
pdnsutil show-zone example.com
pdnsutil get-meta example.com

pdnsutil のサブコマンドは版によって体系が整理されることがあります。上のコマンドが見つからない場合は pdnsutil --help で対応するものを確認してください(2026年10月現在)。設定ファイルの場所も、パッケージによって /etc/powerdns/ や /etc/pdns/ と異なります。

確認しておきたいのは次の点です。

  • ゾーンの種類(native・primary・secondary):native のゾーンはデータベースの複製でセカンダリに配っているため、AXFR を使っていません。BIND に移ると、セカンダリへの配信を AXFR と NOTIFY に作り直す必要があります。
  • ALIAS レコードと LUA レコード:どちらも PowerDNS 独自の機能で、BIND にはありません。
  • API を使う外部の仕組み:証明書の自動更新(DNS-01 チャレンジ)、管理画面、Kubernetes の external-dns などが PowerDNS の HTTP API を呼んでいる場合、移行後は動かなくなります。
  • DNSSEC:show-zone で鍵が表示されれば、そのゾーンは署名されています。

ゾーンを書き出す

ゾーンごとに pdnsutil list-zone でゾーンファイル形式の出力を取り、BIND の検査ツールで読めるか確かめます。

mkdir -p ~/bind-migrate
for z in $(pdnsutil list-all-zones); do
  pdnsutil list-zone "$z" > ~/bind-migrate/"$z".zone
  named-checkzone "$z" ~/bind-migrate/"$z".zone
done

出力される名前は末尾にドットの付いた FQDN で書かれるため、$ORIGIN を気にせずに使えます。DNSSEC を使っているゾーンでも、PowerDNS は応答時に署名を作るので、通常は RRSIG などの署名レコードは出力に含まれません。もし DNSKEY・RRSIG・NSEC 系のレコードが含まれていたら、BIND で署名し直すため取り除きます。

PowerDNS 独自のレコードを探して置き換える

grep -nE '\s(ALIAS|LUA)\s' ~/bind-migrate/*.zone
  • ALIAS:ゾーンの頂点(example.com そのもの)を CDN やクラウドのホスト名に向けるためによく使われます。BIND では、向け先の A・AAAA レコードを直接書くか、頂点を CDN 事業者の DNS に任せるなどの方法に変える必要があります。向け先の IP アドレスが変わる場合は、手で追従する運用になる点に注意します。
  • LUA:応答時にスクリプトで答えを決める仕組み(死活監視つきの振り分けなど)です。BIND では同じことはできないため、固定のレコードにするか、ロードバランサーなど別の仕組みに移します。

API の代わりを用意する

API でレコードを更新していた仕組みは、BIND では TSIG で認証した動的更新(RFC 2136、nsupdate)に置き換えるのが一般的です。主要な ACME クライアントの多くは RFC 2136 に対応したプラグインを持っていますが、対応状況はツールごとに確認してください。

BIND を設定する

比較のため、最初は PowerDNS とは別のアドレスで待ち受けます。BIND 9.16 以降は type primary と書けます(古い master も引き続き使えます)。設定ファイルの場所は、Debian・Ubuntu 系が /etc/bind/、RHEL 系が /etc/named.conf と /var/named/ です。

# /etc/bind/named.conf.options(Debian 系の例)
options {
    directory "/var/cache/bind";
    listen-on { 192.0.2.54; };
    listen-on-v6 { none; };
    recursion no;
    allow-transfer { none; };
    version none;
};

# /etc/bind/named.conf.local
zone "example.com" {
    type primary;
    file "/etc/bind/zones/example.com.zone";
};

権威専用のサーバーなので recursion no; を入れ、外部からの再帰問い合わせに答える状態(オープンリゾルバー)にならないようにします。

sudo mkdir -p /etc/bind/zones
sudo cp ~/bind-migrate/*.zone /etc/bind/zones/
sudo named-checkconf
sudo systemctl restart named   # Debian 系では bind9 のこともある
dig @192.0.2.54 example.com SOA +norec

SOA シリアルを揃える

PowerDNS では SOA-EDIT や SOA-EDIT-API のメタデータによって、応答に出るシリアルが保存されている値と違うことがあります。dig @PowerDNSのアドレス example.com SOA +short で今配っているシリアルを確かめ、BIND のゾーンファイルにはそれ以上の値を書きます。値が下がると、既存のセカンダリが更新を受け取らなくなります。

セカンダリを作り直す

セカンダリには TSIG 鍵を作って転送を限定します。

sudo tsig-keygen -a hmac-sha256 xfr-key > /etc/bind/xfr-key.conf

プライマリ側のゾーンに allow-transfer { key xfr-key; }; と also-notify { セカンダリのアドレス; }; を書き、セカンダリ側では type secondary; と primaries { プライマリのアドレス key xfr-key; }; を指定します。鍵ファイルは両方のサーバーで include し、読み取り権限を named のユーザーだけに絞ります。

並行稼働で答えを比べる

PowerDNS(192.0.2.53)と BIND(192.0.2.54)に同じ問い合わせをして、差分を探します。

awk '!/^[;$]/ && NF>=5 {print $1, $4}' ~/bind-migrate/*.zone | 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

SOA のシリアルを上げていれば差が出るのは正常です。ALIAS を置き換えた名前も差が出ることがあるので、向け先と同じアドレスになっているかを確認します。存在しない名前で NXDOMAIN が返るかも試します。

DNSSEC を使っているゾーンの切り替え

親ゾーン(レジストリ)に登録されている DS レコードは、PowerDNS の鍵に対応しています。BIND で新しい鍵を作って署名し、DS をそのままにして切り替えると、検証するリゾルバーは署名を確かめられず SERVFAIL を返します。主な進め方は次の2つです。

  1. いったん署名を外す方法(手順が単純):レジストラで DS を削除し、親ゾーンの DS の TTL が切れるまで待ちます(余裕を見て1〜2日)。その後に BIND へ切り替え、dnssec-policy で署名を始め、新しい DS を登録します。作業の間は DNSSEC による保護がなくなります。
  2. 署名を保ったまま移す方法:PowerDNS の鍵を pdnsutil export-zone-key で書き出して BIND で使う、または両方の鍵の DNSKEY を公開してから切り替える(複数署名者の構成)方法です。鍵の形式や DNSKEY・DS の TTL を正しく扱う必要があり、検証環境での練習が欠かせません。

BIND 側では、ゾーンに dnssec-policy default; を指定すると鍵の生成と署名を自動で行います。ゾーンファイルを手で編集する運用では、版によって inline-signing yes; の指定が必要になるため、使う版の管理者向け文書(ARM)を確認してください。DS の登録順序の考え方は、DNSSEC の有効化の手順と同じです。

切り替えと切り戻し

切り替えは、同じ IP アドレスを BIND に引き継ぐか、レジストラで NS とグルーレコードを向け替えるかのどちらかです。

  • 同じ IP を引き継ぐ:PowerDNS を停止して自動起動を無効にし(systemctl disable --now pdns)、BIND の listen-on を元のアドレスに変えて再起動します。停止から起動までの短い間は応答が止まります。
  • NS を向け替える:数日前に各レコードの TTL を短くしておき、NS を変えた後も上位の NS の TTL が切れるまでは PowerDNS を止めずに動かします。この間に PowerDNS 側のレコードを変更すると、両方の内容がずれるので変更を止めておきます。

問題が出たら、PowerDNS を起動し直す(または NS を戻す)だけで元に戻せるよう、PowerDNS のデータベースと設定は移行が落ち着くまで消さずに残します。作業の前にはデータベースのバックアップ(MySQL なら mysqldump など)を取っておきます。

まとめ

  • 棚卸しで、native ゾーンの複製・ALIAS・LUA・API 連携・DNSSEC の有無を確かめます。
  • pdnsutil list-zone で書き出し、named-checkzone で検査し、PowerDNS 独自のレコードは BIND で表せる形に置き換えます。
  • BIND は別のアドレスで起動し、recursion no; とシリアルの引き継ぎを確認してから全レコードを比べます。
  • DNSSEC のゾーンは、DS を消してから移すか、鍵を引き継ぐかを決めてから切り替えます。古い DS を残したまま新しい鍵に変えないことが要点です。

お気軽にご相談ください

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