2026年6月18日

2026年6月18日

dnsmasq から NSD へ移行する手順|ローカルレコードをゾーンファイルにし、転送は残して段階的に切り替える

dnsmasq で答えている社内向けの名前を NSD に移すときは、dnsmasq の設定行をゾーンファイルに書き換え、NSD を別ポートで動かして答えを比べ、最後に dnsmasq(または Unbound)から NSD へ問い合わせを回す、という順に進めると安全です。注意したいのは、NSD が権威 DNS 専用のソフトで、dnsmasq が兼ねていた転送・キャッシュや DHCP は引き継げないことです。この記事では、移行後の構成の決め方、レコードの対応、比較の方法、切り替えと切り戻しまでを説明します。

移行の前に:dnsmasq が担っている役割を分ける

dnsmasq は1つのプロセスで多くの役割を兼ねられるソフトです。移行の最初の作業は、手元の dnsmasq が実際に何をしているかを分けて書き出すことです。

  • 転送とキャッシュ:端末からの問い合わせを上流のリゾルバーへ回し、結果をキャッシュする
  • 社内の静的な名前の応答:host-record や /etc/hosts に書いた名前を答える
  • DHCP:IP アドレスを配り、端末のホスト名を DNS に自動で登録する
  • そのほか:PXE 起動用の TFTP、ルーター広告など

NSD が引き受けられるのは、2つ目の「静的な名前の応答」だけです。NSD は再帰検索をしないため、端末が直接 NSD を DNS サーバーとして使うと、社外の名前が引けなくなります。また NSD は動的更新(RFC 2136)に対応していないため、DHCP で配った端末の名前を自動で登録する使い方もできません。

移行後の構成を決める

よく使われる構成は次の2つです。

  • dnsmasq を残す構成:端末からの問い合わせと DHCP は dnsmasq がこれまでどおり受け、社内ゾーンの問い合わせだけを NSD に回します。変更点が少なく、段階的に移行できます
  • Unbound に置き換える構成:転送とキャッシュを Unbound、社内ゾーンを NSD、DHCP を別のソフト(Kea など)に分けます。役割ごとに入れ替えられる反面、作業量は増えます

この記事では、まず前者で移行し、必要なら後から Unbound に置き換える流れで説明します。DHCP で登録される端末名は、dhcp.corp.example.com のように別のサブドメインに分けて dnsmasq に残すと、NSD のゾーンと名前がぶつかりません。

社内ゾーンの名前には、自社が持つドメインのサブドメイン(例では corp.example.com)を使うのが無難です。.local は mDNS で使われるため避け、家庭や小規模な LAN なら RFC 8375 で定められた home.arpa も選択肢になります。

手順1:dnsmasq の設定とレコードを洗い出す

作業前に、dnsmasq の設定ファイル一式をバックアップしてから、名前に関わる行を抜き出します。

sudo cp -a /etc/dnsmasq.conf /etc/dnsmasq.d /root/dnsmasq-backup/
grep -hE '^(address|host-record|cname|mx-host|srv-host|txt-record|ptr-record|addn-hosts|local|domain|server|rev-server|local-ttl)=' \
  /etc/dnsmasq.conf /etc/dnsmasq.d/*.conf

no-hosts が設定されていなければ、dnsmasq は /etc/hosts の内容も答えています。addn-hosts で指定された追加の hosts ファイルも合わせて確認します。見落としやすいのはこの hosts ファイル経由の名前です。

手順2:ゾーンファイルを作る

dnsmasq の設定行は、おおむね次のようにゾーンファイルのレコードへ対応します。

  • host-record=名前,IP → 正引きの A(IPv6 なら AAAA)と、逆引きゾーンの PTR の2つ
  • address=/名前/IP → A。ただし dnsmasq ではその名前の配下すべてにも同じ IP を返すため、必要なら *.名前 のワイルドカードも書きます
  • cname=別名,別名先 → CNAME
  • mx-host=ドメイン,MX名,優先度 → MX
  • srv-host=_サービス._プロトコル.ドメイン,ターゲット,ポート,優先度,重み → SRV。ゾーンファイルでは「優先度 重み ポート ターゲット」の順になるので、並び替えに注意します
  • txt-record=名前,"文字列" → TXT
  • /etc/hosts の行 → A と PTR

dnsmasq の host-record や hosts ファイルは逆引きを自動で作りますが、NSD では逆引きゾーンを別に用意しないと PTR は返りません。

正引きゾーンの例です(/etc/nsd/zones/corp.example.com.zone)。

$ORIGIN corp.example.com.
$TTL 300
@       IN SOA  ns1.corp.example.com. hostmaster.example.com. (
                2026101801 ; serial(更新のたびに増やす)
                3600       ; refresh
                900        ; retry
                1209600    ; expire
                300 )      ; 否定応答のキャッシュ時間
        IN NS   ns1.corp.example.com.
        IN MX   10 mail.corp.example.com.
        IN TXT  "v=spf1 mx -all"
ns1     IN A    192.168.1.53
www     IN A    192.168.1.10
mail    IN A    192.168.1.25
wiki    IN CNAME www.corp.example.com.
_ldap._tcp IN SRV 0 100 389 dc1.corp.example.com.
dc1     IN A    192.168.1.30

逆引きゾーンの例です(/etc/nsd/zones/1.168.192.in-addr.arpa.zone)。

$ORIGIN 1.168.192.in-addr.arpa.
$TTL 300
@   IN SOA ns1.corp.example.com. hostmaster.example.com. (
        2026101801 3600 900 1209600 300 )
    IN NS  ns1.corp.example.com.
10  IN PTR www.corp.example.com.
25  IN PTR mail.corp.example.com.
30  IN PTR dc1.corp.example.com.
53  IN PTR ns1.corp.example.com.

TTL にも違いがあります。dnsmasq は自分で答える名前の TTL を既定で 0 にしており、local-ttl を指定していなければ端末は毎回問い合わせていたはずです。ゾーンファイルの $TTL を長くすると、変更の反映がその分遅れます。最初は数分程度にしておき、運用が落ち着いてから見直すとよいでしょう。

手順3:NSD を別ポートで起動する

同じサーバーでは dnsmasq がすでに 53 番を使っているため、NSD はループバックの別ポートで待ち受けさせます。ここでは 5300 番を使います(5353 番は mDNS が使うので避けます)。

# /etc/nsd/nsd.conf
server:
    ip-address: 127.0.0.1
    port: 5300
    zonesdir: "/etc/nsd/zones"
    hide-version: yes

remote-control:
    control-enable: yes

zone:
    name: "corp.example.com"
    zonefile: "corp.example.com.zone"

zone:
    name: "1.168.192.in-addr.arpa"
    zonefile: "1.168.192.in-addr.arpa.zone"

設定とゾーンの文法を確かめてから起動します。nsd-control を使うには、最初に nsd-control-setup で制御用の鍵を作ります(パッケージによっては導入時に作成済みです)。

sudo nsd-checkconf /etc/nsd/nsd.conf
sudo nsd-checkzone corp.example.com /etc/nsd/zones/corp.example.com.zone
sudo nsd-checkzone 1.168.192.in-addr.arpa /etc/nsd/zones/1.168.192.in-addr.arpa.zone
sudo nsd-control-setup
sudo systemctl restart nsd
dig @127.0.0.1 -p 5300 www.corp.example.com A

NSD のバージョンは 4 系が広く使われています(2026年10月現在)。設定項目はディストリビューションのパッケージの版で差があるため、man nsd.conf で確認してください。

手順4:dnsmasq と NSD の答えを比べる

切り替え前に、同じ名前を両方に問い合わせて結果を並べます。比べる名前は、手順1で抜き出した一覧から作ります。

# names.txt は1行に「名前 種類」
while read -r name type; do
  old=$(dig @127.0.0.1 "$name" "$type" +short | sort | tr '\n' ' ')
  new=$(dig @127.0.0.1 -p 5300 "$name" "$type" +short | sort | tr '\n' ' ')
  [ "$old" = "$new" ] && s=OK || s=DIFF
  printf '%-4s %-35s %-5s old=[%s] new=[%s]\n' "$s" "$name" "$type" "$old" "$new"
done < names.txt

逆引きは dig -x 192.168.1.10 と dig @127.0.0.1 -p 5300 -x 192.168.1.10 で比べます。DIFF が出やすいのは、hosts ファイルにしかなかった名前の書き漏れ、address 行のワイルドカード的な動き、SRV の項目の並び順です。

手順5:dnsmasq から NSD へ問い合わせを回す

比較で差がなくなったら、dnsmasq 側の静的なレコード定義を外し、該当ゾーンを NSD に回す行を追加します。

# /etc/dnsmasq.d/forward-to-nsd.conf
server=/corp.example.com/127.0.0.1#5300
rev-server=192.168.1.0/24,127.0.0.1#5300

移した名前の host-record などの行と、local=/corp.example.com/ があれば削除します。local= が残っていると、dnsmasq がそのドメインを自分で答えようとして NSD に回りません。また bogus-priv を有効にしていると、プライベートアドレスの逆引きの扱いが期待と異なる場合があるため、切り替え後に逆引きが期待どおり返るかを個別にテストします。

dnsmasq は SIGHUP では hosts ファイルなどを読み直すだけで、設定ファイルの変更は反映しません。設定を変えたら再起動します。

sudo dnsmasq --test
sudo systemctl restart dnsmasq
dig @192.168.1.53 www.corp.example.com
dig @192.168.1.53 -x 192.168.1.10
dig @192.168.1.53 www.example.org

社内名・逆引き・社外の名前の3つが引ければ切り替えは完了です。

Unbound に置き換える場合の要点

後から dnsmasq を Unbound に置き換える場合は、stub-zone で社内ゾーンを NSD に回します。Unbound は既定でループバックへ問い合わせない設定になっているため、do-not-query-localhost: no が要ります。

server:
    do-not-query-localhost: no
    private-domain: "corp.example.com"
    domain-insecure: "corp.example.com"
    local-zone: "168.192.in-addr.arpa." nodefault
    domain-insecure: "168.192.in-addr.arpa."

stub-zone:
    name: "corp.example.com"
    stub-addr: 127.0.0.1@5300

stub-zone:
    name: "1.168.192.in-addr.arpa"
    stub-addr: 127.0.0.1@5300

private-domain は、プライベートアドレスを含む応答を捨てる設定(private-address)を使っている場合に、社内ゾーンを例外にするためのものです。domain-insecure は、DNSSEC の検証を有効にしているときに、署名のない社内ゾーンを検証対象から外します。

ゾーンを更新するときと切り戻し

運用に入ったら、レコードを変えるたびに次の順で作業します。シリアルを上げ忘れると、将来セカンダリを追加したときに転送されない原因になります。

sudo vi /etc/nsd/zones/corp.example.com.zone   # serial を増やす
sudo nsd-checkzone corp.example.com /etc/nsd/zones/corp.example.com.zone
sudo nsd-control reload corp.example.com

問題が起きたときは、forward-to-nsd.conf を外し、バックアップしておいた dnsmasq の設定を戻して再起動すれば元の状態に戻ります。NSD は止めずに残しておけば、原因を調べてから再度切り替えられます。

まとめ

  • NSD は権威 DNS 専用なので、dnsmasq の転送・キャッシュ・DHCP は残すか別のソフトに分けます。
  • dnsmasq の設定行と hosts ファイルを洗い出し、正引きと逆引きのゾーンファイルに書き換えます。SRV の並び順や address 行の動きに注意します。
  • NSD を別ポートで起動して全レコードの答えを比べ、server= と rev-server= で NSD に問い合わせを回して切り替えます。
  • 更新時はシリアルを上げ、nsd-checkzone で確かめてから nsd-control reload します。

お気軽にご相談ください

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