2026年6月11日
2026年6月11日
Unbound から CoreDNS へ移行する手順|unbound.conf を Corefile に置き換え、並行稼働で比べてから切り替える
Unbound から CoreDNS へ移行するには、unbound.conf の設定を1項目ずつ Corefile のプラグインに置き換え、CoreDNS を別のポートで並行して動かして応答を比べてから、待ち受けを切り替えます。ただし、2つのソフトは得意なことが違います。Unbound はルートから自分で名前を解決し、DNSSEC の検証も行うフルリゾルバですが、標準の CoreDNS は問い合わせを上流に転送するフォワーダーとして動き、DNSSEC の検証も行いません。この記事では、移行で失われる機能とその補い方を最初に確認し、設定の対応表、並行稼働での確認、切り替えと切り戻しの手順を説明します。
プラグインの仕様は版によって変わることがあるため、手元の版の公式ドキュメント(coredns.io の各プラグインのページ)と照らし合わせてください。以下は執筆時点の情報です(2026年10月現在)。作業前には unbound.conf をバックアップし、Unbound はすぐに戻せるよう、切り替え後もしばらくは停止するだけにしてアンインストールしないでおきます。
移行の前に確認すること
再帰問い合わせと DNSSEC の検証をどうするか
Unbound をフルリゾルバとして使っている(forward-zone を書かずにルートから解決している)場合、標準の CoreDNS にはそれに当たる機能がありません。CoreDNS へ移すと、次のどちらかの形になります。
- 上流のリゾルバに転送する:プロバイダーや社内のリゾルバ、公開リゾルバなどに
forwardプラグインで転送します。上流が DNSSEC を検証していれば、検証済みの結果を受け取れます。 - Unbound を残し、CoreDNS を前段に置く:社内向けのゾーンや振り分けを CoreDNS で行い、外部の名前解決は Unbound に転送します。再帰と検証は Unbound が引き続き担当します。
CoreDNS の dnssec プラグインはゾーンに署名するための機能で、問い合わせの結果を検証するものではありません。DNSSEC の検証を手元で行うことが要件なら、2つ目の形を選ぶか、移行そのものを見直します。
移行する理由を整理する
CoreDNS へ移す理由は、Kubernetes と同じ仕組みに統一したい、プラグインで振り分けやメトリクスを柔軟に組みたい、などが一般的です。単にキャッシュ DNS として速くしたいだけなら、Unbound のままの調整で足りることもあります。理由がはっきりしていると、どこまで移すか(全部か、一部の機能だけか)を決めやすくなります。
設定の対応を確認する
よく使う unbound.conf の項目と、CoreDNS での置き換え先は次のとおりです。
| unbound.conf | CoreDNS(Corefile) |
|---|---|
interface: |
サーバーブロックのポートと bind プラグイン |
access-control: |
acl プラグイン |
forward-zone:(name: ".") |
forward . 上流のアドレス |
forward-zone: / stub-zone:(特定のゾーン) |
ゾーンごとのサーバーブロックと forward |
local-zone: / local-data: |
hosts プラグイン、または file プラグイン |
キャッシュ関係(msg-cache-size、prefetch など) |
cache プラグイン |
serve-expired: |
cache プラグインの serve_stale |
unbound-control stats |
prometheus プラグイン |
private-address:(DNS リバインディング対策)のように、そのまま対応するプラグインがない項目もあります。今の unbound.conf を上から順に読み、対応先がない項目は、必要かどうかと代わりの手段を移行前に決めておきます。
Corefile を書く
次の unbound.conf を例に、置き換えた Corefile を示します。
# 移行前の /etc/unbound/unbound.conf(抜粋)
server:
interface: 192.168.10.53
access-control: 192.168.10.0/24 allow
prefetch: yes
serve-expired: yes
local-zone: "home.example." static
local-data: "nas.home.example. IN A 192.168.10.20"
forward-zone:
name: "corp.example."
forward-addr: 10.0.0.53
forward-zone:
name: "."
forward-addr: 192.0.2.53
forward-addr: 198.51.100.53
# 移行後の /etc/coredns/Corefile(並行稼働のため、まずは 1053 番で待ち受ける)
home.example:1053 {
bind 192.168.10.53
acl {
allow net 192.168.10.0/24
block
}
hosts {
192.168.10.20 nas.home.example
}
log
errors
}
corp.example:1053 {
bind 192.168.10.53
acl {
allow net 192.168.10.0/24
block
}
forward . 10.0.0.53
cache 30
errors
}
.:1053 {
bind 192.168.10.53
acl {
allow net 192.168.10.0/24
block
}
forward . 192.0.2.53 198.51.100.53
cache {
prefetch 10
serve_stale
}
loop
prometheus 127.0.0.1:9153
errors
}
書くときのポイントは次のとおりです。
- アクセス制限はサーバーブロックごとに書く:
aclはそのブロックの中だけに効きます。ゾーンを分けてブロックを増やしたら、それぞれに書きます。書き忘れたブロックは誰からでも問い合わせを受け付けるため、外部に開いたオープンリゾルバになるおそれがあります。 - **ローカルの名前は
hostsかfileで**:数件ならhostsが手軽です。件数が多い、または MX や TXT なども使うなら、ゾーンファイルを書いてfileプラグインで読み込みます。 - **
loopを入れておく**:上流の指定を誤って自分自身に転送すると、問い合わせが回り続けます。loopはこれを検出して CoreDNS を止めてくれます。 - キャッシュの値は少しずつ:
cacheの件数や秒数は、まずは既定に近い値で動かし、移行後にprometheusのヒット率を見て調整します。
上流との通信を暗号化したい場合は、forward . tls://上流のアドレス と tls_servername を使う DNS over TLS の書き方もあります。上流が対応しているかどうかを確認してから使います。
並行稼働で応答を比べる
CoreDNS を 1053 番で起動し、同じ問い合わせを Unbound(53番)と CoreDNS(1053番)に送って結果を比べます。
# 構文と起動の確認(フォアグラウンドで動かし、ログを見る)
coredns -conf /etc/coredns/Corefile
# 別の端末から比較する
for name in www.example.com nas.home.example intranet.corp.example; do
echo "== $name"
dig +short @192.168.10.53 -p 53 "$name"
dig +short @192.168.10.53 -p 1053 "$name"
done
比べておきたいのは、外部ドメインの名前解決、ローカルの名前、社内ゾーンの転送、存在しない名前(NXDOMAIN が返るか)、許可していないアドレスからの問い合わせが拒否されるか、の5点です。許可外のアドレスからの確認は、別のネットワークの端末から行います。
数件の確認だけでは見落としが出やすいので、Unbound のログや利用者からよく問い合わせのある名前を集めてリストにし、スクリプトで両方に送って差分を見ておくと安心です。
切り替える
比較で問題がなければ、待ち受けを入れ替えます。
- Corefile のポートを
1053から53に書き換えます。 - Unbound を止め、CoreDNS を systemd のサービスとして起動します。
sudo systemctl stop unbound
sudo systemctl disable unbound
sudo systemctl enable --now coredns
CoreDNS を root 以外のユーザーで動かす場合、53番で待ち受けるには CAP_NET_BIND_SERVICE の権限が必要です。公式が配布している systemd のユニットファイルの例を参考にし、手元の配置に合わせて調整します。また、同じサーバーで systemd-resolved が 53 番を使っていると、CoreDNS が起動に失敗します。ss -lunp | grep :53 で、53番を使っているプロセスを確認します。
切り替えたら、クライアント側から名前解決を確認し、しばらくは CoreDNS のログとメトリクスでエラーや SERVFAIL の増加がないかを見ます。DHCP でクライアントに配っている DNS サーバーのアドレスを変えないで済むよう、同じアドレスで待ち受ける形にしておくと、切り替えも切り戻しも短時間で終わります。
問題が出たときの切り戻し
CoreDNS で問題が起きたら、CoreDNS を止めて Unbound を起動し直します。
sudo systemctl stop coredns
sudo systemctl enable --now unbound
unbound.conf を残したままにしておけば、この2行で元の状態に戻れます。原因を調べたら、再び並行稼働での比較からやり直します。
まとめ
- 標準の CoreDNS はフォワーダーで、DNSSEC の検証も行いません。フルリゾルバと検証が必要なら、上流に任せるか Unbound を後段に残します。
- unbound.conf の項目を
bind・acl・forward・hosts・cacheなどのプラグインに置き換え、対応先がない項目は移行前に扱いを決めます。 aclはサーバーブロックごとに書き、loopで転送ループを防ぎます。- 別のポートで並行稼働して応答を比べてから切り替え、Unbound はしばらく停止するだけにして切り戻しに備えます。