2026年6月12日
2026年6月12日
dnsmasq のインストール方法|53番ポートの競合を避けて、LAN 向けの DNS キャッシュとして動かすまで
dnsmasq は、Debian・Ubuntu なら apt install dnsmasq、RHEL 系(AlmaLinux・Rocky Linux など)なら dnf install dnsmasq で入ります。インストール自体は1行ですが、多くの環境では systemd-resolved などがすでに53番ポートを使っているため、そのままでは起動に失敗します。この記事では、インストール前の確認、ディストリビューションごとの導入、ポートの競合の解き方、最小限の設定、動作確認とファイアウォールまでを順に説明し、LAN 向けの DNS キャッシュ兼ローカル名の解決として動かせる状態を目指します。
パッケージ名や既定の設定ファイルの内容はディストリビューションと版によって異なります。記載は執筆時点(2026年10月現在)の情報です。本番機に入れる前に、同じ OS の検証環境で一度試すことをおすすめします。
インストールの前に決めておくこと
dnsmasq は小さなソフトですが、DNS の転送とキャッシュ、ローカル名の解決、DHCP、TFTP など多くの機能を持っています。最初に次の3点を決めておくと、設定で迷いません。
- 用途:DNS だけを使うのか、DHCP も dnsmasq に任せるのか。この記事では DNS だけを扱います。DHCP は
dhcp-rangeを書かない限り動かないため、ルーターの DHCP と衝突する心配はありません。 - 待ち受けるアドレス:LAN 側のアドレス(例:
192.168.1.10)と、自分自身用の127.0.0.1だけにします。インターネットに面したアドレスで待ち受けると、誰でも使えるオープンリゾルバーになり、DNS 増幅攻撃の踏み台にされるおそれがあります。 - 上流の DNS:問い合わせを転送する先。プロバイダーやクラウドのリゾルバー、社内の DNS など。
手順1:53番ポートを使っているプロセスを確認する
sudo ss -lntup 'sport = :53'
よく見かけるのは次のような先客です。
- systemd-resolved:Ubuntu などで
127.0.0.53(版によっては127.0.0.54も)で待ち受けています。 - libvirt の dnsmasq:仮想マシン用のブリッジ(
virbr0など)のアドレスで、libvirt が自分用の dnsmasq を動かしています。 - 別の DNS サーバー:BIND や Unbound がすでに入っている場合。
ここで何がいるかを把握しておくと、後の手順3で選ぶ方法が決まります。
手順2:パッケージをインストールする
Debian・Ubuntu
sudo apt update
sudo apt install dnsmasq
Debian 系では、インストール直後に dnsmasq のサービスが自動で起動しようとします。systemd-resolved が53番を使っている環境では、ここで「failed to create listening socket for port 53: Address already in use」のようなエラーが出て起動に失敗することがありますが、インストール自体は完了しています。手順3で競合を解いてから起動し直せば問題ありません。
NetworkManager や libvirt の依存で dnsmasq-base だけが入っていることもあります。これはプログラム本体だけのパッケージで、常駐サービスとして使うための設定やユニットファイルは dnsmasq パッケージに含まれます。
RHEL 系
sudo dnf install dnsmasq
RHEL 系では、インストールしてもサービスは自動では起動しません。設定を書いてから手順5で有効にします。
インストールできたら、版と組み込まれている機能を確認します。
dnsmasq --version
2行目あたりに「Compile time options」として、DNSSEC や DHCP などの対応の有無が表示されます。
手順3:53番ポートの競合を解く
方法は大きく2つあります。
方法A:待ち受けアドレスを分けて共存させる(おすすめ)
systemd-resolved は 127.0.0.53 で、dnsmasq は 127.0.0.1 と LAN 側のアドレスで待ち受ければ、同じ53番でもぶつかりません。そのためには、dnsmasq に「指定したアドレスにだけ結び付く」よう bind-interfaces を設定します(設定内容は手順4)。OS 側の設定を変えずに済むため、影響範囲がもっとも小さい方法です。libvirt の dnsmasq がいる環境でも、同じ考え方で共存できます。
方法B:systemd-resolved の待ち受けを止める
このサーバー自身の名前解決も dnsmasq に任せたい場合は、systemd-resolved のスタブリスナーを止めます。
sudo mkdir -p /etc/systemd/resolved.conf.d
printf '[Resolve]\nDNSStubListener=no\n' | sudo tee /etc/systemd/resolved.conf.d/no-stub.conf
sudo systemctl restart systemd-resolved
この方法では、/etc/resolv.conf に注意が要ります。Ubuntu では resolv.conf が 127.0.0.53 を指すファイルへのシンボリックリンクになっていることが多く、スタブを止めるとサーバー自身が名前を引けなくなります。dnsmasq を起動したあとに、resolv.conf の向き先を 127.0.0.1 にするか、systemd-resolved が上流の一覧を書き出すファイルに張り替えます。どちらがよいかは NetworkManager や netplan の使い方によって変わるため、変更前に元のリンク先をメモしておきます。
手順4:最小限の設定を書く
設定は /etc/dnsmasq.conf に直接書くこともできますが、パッケージの更新で衝突しないよう、別ファイルに分けるのがおすすめです。Debian 系・RHEL 系とも /etc/dnsmasq.d/ を読み込む設定になっていることが多いので、grep conf-dir /etc/dnsmasq.conf などで確かめてから、/etc/dnsmasq.d/local.conf を作ります。
# /etc/dnsmasq.d/local.conf
# 待ち受け:自分自身と LAN 側のアドレスだけ
listen-address=127.0.0.1,192.168.1.10
bind-interfaces
# 上流:resolv.conf は読まず、ここに書いたサーバーへ転送する
no-resolv
server=192.0.2.53
server=198.51.100.53
# ドットの無い名前とプライベートアドレスの逆引きを上流に流さない
domain-needed
bogus-priv
# キャッシュする件数
cache-size=1000
# LAN 内の名前(home.arpa は家庭内ネットワーク向けに予約されたドメイン)
local=/home.arpa/
domain=home.arpa
host-record=nas.home.arpa,192.168.1.20
host-record=printer.home.arpa,192.168.1.30
それぞれの意味と、つまずきやすい点です。
- **
listen-addressとbind-interfaces**:listen-addressだけを書いた場合、127.0.0.1は自動では待ち受けに入らないため、明示して書きます。bind-interfacesを付けないと、dnsmasq はすべてのアドレスで受けてから振り分ける動きになり、systemd-resolved と競合します。 - **
no-resolv**:dnsmasq は既定で/etc/resolv.confから上流を読みます。手順3の方法Bで resolv.conf を127.0.0.1に向けると、自分自身に転送してループします。上流はserver=で明示しておくほうが安全です。 - **
local=/home.arpa/**:このドメインは上流へ問い合わせず、dnsmasq が持つ情報だけで答えます。 - **
host-record**:名前とアドレスを登録し、逆引き(PTR)も自動で答えます。/etc/hostsに書いた名前も既定で答えに使われます。
手順5:文法を確認して起動する
# 文法の確認(問題なければ "syntax check OK" と表示される)
dnsmasq --test
sudo systemctl enable --now dnsmasq
sudo systemctl restart dnsmasq
systemctl status dnsmasq
起動に失敗したら、journalctl -u dnsmasq -e でログを確認します。「Address already in use」なら手順3の競合がまだ残っている、「unknown interface」なら listen-address に書いたアドレスがそのサーバーに無い、という切り分けができます。
手順6:動作を確認する
# 外部の名前(2回続けて引くと、2回目は Query time が短くなる)
dig @192.168.1.10 example.com A
# LAN 内の名前と逆引き
dig @192.168.1.10 nas.home.arpa A
dig @192.168.1.10 -x 192.168.1.20
# キャッシュの統計(dnsmasq は CHAOS クラスの TXT で統計を返す)
dig @127.0.0.1 cachesize.bind CH TXT +short
dig @127.0.0.1 hits.bind CH TXT +short
LAN 内の別の端末からも dig や nslookup で問い合わせ、答えが返るかを確かめます。返らない場合は、次のファイアウォールを確認します。
手順7:ファイアウォールで問い合わせ元を絞る
LAN からの問い合わせだけを通します。DNS は UDP と TCP の両方を使うため、両方を許可します。
# ufw(Ubuntu など)
sudo ufw allow from 192.168.1.0/24 to any port 53
# firewalld(RHEL 系):LAN 側のゾーンにだけ dns を許可する
sudo firewall-cmd --permanent --zone=internal --add-source=192.168.1.0/24
sudo firewall-cmd --permanent --zone=internal --add-service=dns
sudo firewall-cmd --reload
VPS やクラウドのサーバーに入れる場合は、事業者側のセキュリティグループやファイアウォールでも53番を外部に開けていないかを確認します。待ち受けアドレスを LAN 側に限っていても、設定の書き換えで公開アドレスに広がる事故を防ぐため、二重に絞っておくのが基本です。
端末側の設定と、元に戻す方法
LAN 内の端末に dnsmasq を使わせるには、ルーターの DHCP 設定で配る DNS サーバーを dnsmasq のアドレスにするか、端末ごとに DNS サーバーを指定します。いきなり全台を切り替えず、1台で数日使ってから広げると、問題が出ても影響が小さく済みます。
元に戻すときは、端末の DNS を元に戻してから sudo systemctl disable --now dnsmasq で止めます。手順3の方法Bを取った場合は、作成した no-stub.conf を削除して systemd-resolved を再起動し、resolv.conf のリンク先を元に戻します。パッケージを削除する場合、Debian 系の apt remove は設定ファイルを残し、apt purge は消すため、必要な設定は先にバックアップします。
まとめ
- インストールは
apt install dnsmasqまたはdnf install dnsmasqで済みますが、先にss -lntup 'sport = :53'で53番の先客を確認します。 - systemd-resolved とは、
listen-addressとbind-interfacesで待ち受けアドレスを分ければ共存できます。 - 上流は
no-resolvとserver=で明示し、LAN 内の名前はlocal=とhost-recordで答えさせます。 dnsmasq --testで文法を確認してから起動し、ファイアウォールで LAN からの問い合わせだけを通します。