設定 - DNSMasq
概要
DNSMasqは、DNSフォワーダ、DHCPサーバ、TFTPサーバ、ルータ広告 (RA) サーバを1つに統合した軽量なネットワークサービスである。
Simon Kelleyによって開発され、GPL v2 / v3以降のライセンスで提供されている。
Linux、BSD、Mac OSで動作し、IPv4 と IPv6 の両方に対応する。
小規模ネットワークやホームネットワーク、組込み機向けの軽量ツールとして広く利用されており、BIND等のフル機能DNSサーバと比較して設定が簡素でメモリ消費が少ないのが特徴である。
主なユースケースを以下に示す。
- 内部向けDNSサーバ (LAN内のホスト名解決)
- DNSキャッシュサーバ (上流DNS応答のキャッシュによる応答速度向上)
- DHCPサーバ (DHCPv4/DHCPv6/BOOTPによるIPアドレス配布)
- PXEネットブート (TFTPサーバとの組合せによるネットワーク起動)
- IPv6 RAサーバ (ステートレスアドレス自動設定の広告)
前提条件
DNSMasqを導入する環境の前提条件を以下に示す。
- RHEL
- ネットワーク管理
- NetworkManager
- パッケージ
- dnsmasq
- dnsmasq-utils (任意)
- ネットワーク管理
- SUSE
- ネットワーク管理
- NetworkManager または wicked
- パッケージ
- dnsmasq
- ネットワーク管理
- Raspberry Pi OS
- 静的IPアドレスの事前設定 (DHCPサーバとして運用する場合)
- パッケージ
- dnsmasq
- dhcpcd5 または NetworkManagerとの競合に注意すること。
※注意
DNSサーバとして稼働させるホストには固定IPアドレスを設定すること。
DNSMasqのインストール
RHEL
dnsmasq-utils は、dhcp_release 等の補助ツールを含む任意パッケージである。
sudo dnf install dnsmasq dnsmasq-utils
留意点を以下に示す。
NetworkManagerは、 dns=dnsmasq 設定で独自のDNSMasqインスタンスを起動する。
スタンドアロンでDNSMasqを運用する場合は、/etc/NetworkManager/NetworkManager.conf ファイルの dns=default 等に変更して無効化することが推奨される。
RHELでは、systemd-resolvedが有効化されている場合がある。
その場合は、systemd-resolvedとの競合回避セクションを参照すること。
SUSE
NetworkManager-dns-dnsmasq パッケージは、NetworkManager連携用の任意パッケージである。
sudo zypper install dnsmasq NetworkManager-dns-dnsmasq
networkリポジトリから最新版を導入する場合は、以下に示す手順を実行する。
sudo zypper addrepo https://download.opensuse.org/repositories/network/$releasever/network.repo Network sudo zypper refresh sudo zypper install dnsmasq
Raspberry Pi OS
sudo apt install dnsmasq
インストール直後にサービスがmasked状態になっている場合は、以下に示すコマンドで有効化する。
sudo systemctl unmask dnsmasq.service sudo systemctl enable dnsmasq.service
※注意
Buster以前のRaspberry Pi OSでは、dhcpcd5がDHCPクライアントとして動作するため、DNSMasqと競合する場合がある。
Bookworm以降は、NetworkManagerに移行しており、dhcpcd5との競合は軽減されている。
DHCPサーバとして運用する場合は、事前に固定IPアドレスを設定しておくこと。
DNSMasqの主な機能
下表に、DNSMasqが提供する主な機能を示す。
| 機能 | 説明 |
|---|---|
| DNSフォワーダ | 上流DNSサーバにクエリを転送して、応答をキャッシュする。 |
| DHCPサーバ | DHCPv4 / DHCPv6 / BOOTPに対応 静的・動的リース両対応 |
| TFTPサーバ | PXEネットブート用の読み取り専用TFTPサーバを提供。 |
| ルータ広告 (RA) | IPv6のRAサーバ機能を提供 |
| DNSキャッシュ | 上流応答をキャッシュして応答速度を向上 |
これらの機能は1つのプロセスで統合的に提供されるため、複数のサービスを個別に導入・設定する必要がない。
DNSMasqの設定
設定ファイルの構成
DNSMasqの設定ファイルの構成を以下に示す。
- メイン設定ファイル
- /etc/dnsmasq.conf
- ドロップイン設定ディレクトリ
- /etc/dnsmasq.d/
- このディレクトリ内の .conf ファイルは自動的に読み込まれる。
- ホスト名登録ファイル
- /etc/hosts (デフォルト) または
--addn-hostsオプションで指定したファイル
- /etc/hosts (デフォルト) または
- 上流DNS参照ファイル
- /etc/resolv.conf (デフォルト) または
--resolv-fileオプションで指定したファイル
- /etc/resolv.conf (デフォルト) または
- リースファイル
- /var/lib/dnsmasq/dnsmasq.leases
- DHCPリース情報が記録される。
ドロップインディレクトリを活用することにより、/etc/dnsmasq.conf ファイルを直接編集せずに設定を追加できる。
/etc/dnsmasq.confの主要設定項目
下表に、/etc/dnsmasq.conf ファイルの主な設定項目を示す。
| 設定項目 | デフォルト値 | 説明 |
|---|---|---|
port=53 |
53 | DNSリッスンポート0 でDNS機能を無効化
|
interface=<name> |
全IF | リッスンするインターフェースを指定 |
listen-address=<ip> |
全アドレス | リッスンするIPアドレスを指定 |
bind-interfaces |
無効 | 指定インターフェースのみbind |
bind-dynamic |
無効 | bind-interfaces相当 + 新IF自動検出 推奨 |
domain-needed |
無効 | ドットなしクエリを上流に転送しない。 |
bogus-priv |
無効 | プライベートIP逆引きを上流に転送しない。(RFC6303) |
no-resolv |
無効 | /etc/resolv.conf ファイルを読まない。 |
resolv-file=<file> |
/etc/resolv.conf | 上流DNS取得ファイルを指定 |
no-poll |
無効 | resolv.conf ファイル変更ポーリングを無効化 |
server=<domain>/<ip> |
なし | ドメイン別の転送先を指定 |
address=<domain>/<ip> |
なし | 常に指定IPを返す。 |
domain=<domain> |
なし | ローカルドメインを指定 |
local=<domain> |
なし | server=/domain/ のシノニム
|
expand-hosts |
無効 | /etc/hosts ファイルの単純名にドメインを付加 |
no-hosts |
無効 | /etc/hosts ファイルを読まない。 |
addn-hosts=<file> |
なし | 追加hostsファイルを指定 |
stop-dns-rebind |
無効 | DNS再バインディング攻撃対策 |
rebind-localhost-ok |
無効 | 127.0.0.0/8, ::1をrebind除外 |
rebind-domain-ok=<domain> |
なし | 指定ドメインをrebind除外 |
local-service |
無効 | ローカルネットワークからのクエリのみ受付 |
cache-size=<num> |
150 | キャッシュ最大サイズ0 で無効
|
dns-forward-max=<num> |
150 | 同時上流クエリ最大数 |
log-queries |
無効 | DNSクエリログを記録 |
log-facility=<facility> |
DAEMON | syslogファシリティを指定 |
user=<username> |
nobody | 起動後の実行ユーザ |
edns-packet-max=<size> |
1232 | EDNS.0 UDP最大サイズ (DNS Flag Day 2020) |
実設定例を以下に示す。
# /etc/dnsmasq.conf # DNSサーバのポート番号 port=53 # リッスンするインターフェース interface=eth0 listen-address=127.0.0.1,192.168.1.100 # ドットなしクエリおよびプライベートIP逆引きを上流に転送しない domain-needed bogus-priv # ローカルドメインの指定 domain=raspi.com local=/raspi.com/ expand-hosts # /etc/hosts は使用せず、追加hostsファイルを使用 no-hosts addn-hosts=/etc/hosts-dnsmasq # 任意のIPアドレスに強制的に接続させたいドメイン address=/raspi.com/192.168.1.100 # キャッシュサイズ cache-size=10000 # 上流DNSサーバ server=192.168.1.1 server=1.1.1.1 # DNS再バインディング攻撃対策 stop-dns-rebind
DHCPサーバ機能の設定
下表に、DHCPサーバ機能の主な設定項目を示す。
| 設定項目 | デフォルト値 | 説明 |
|---|---|---|
dhcp-range |
なし | DHCPリース範囲を指定 例: 192.168.1.100,192.168.1.200,255.255.255.0,12h
|
dhcp-host |
なし | MAC / UID別の静的IP割り当て |
dhcp-option |
なし | 追加DHCPオプション 例: option:router,192.168.1.1
|
dhcp-authoritative |
無効 | 権威DHCPサーバとして宣言 |
dhcp-lease-max |
1000 | 最大リース数 |
log-dhcp |
無効 | DHCP詳細ログを記録 |
no-dhcp-interface=<iface> |
なし | 指定IFでDHCPを無効化 |
DHCPサーバ機能の設定例を以下に示す。
# DHCPリース範囲の指定 dhcp-range=192.168.1.100,192.168.1.200,255.255.255.0,12h # 静的IP割り当て (MACアドレス指定) dhcp-host=aa:bb:cc:dd:ee:ff,192.168.1.50,client1 # デフォルトゲートウェイの通知 dhcp-option=option:router,192.168.1.1 # DNSサーバの通知 dhcp-option=option:dns-server,192.168.1.100 # 権威DHCPサーバとして宣言 dhcp-authoritative # DHCP詳細ログ log-dhcp
ホスト名の登録
ホスト名とIPアドレスの対応は、以下のいずれかの方法で登録する。
/etc/hostsを直接使用する方法
デフォルトでは、DNSMasq は /etc/hosts を読み込んで名前解決を行う。
# /etc/hosts 192.168.1.100 ns.raspi.com ns 192.168.1.101 client1.raspi.com client1 192.168.1.102 client2.raspi.com client2
addn-hostsを使用する方法
/etc/hosts ファイルとは別にホスト名登録用ファイルを用意する場合は、no-hosts と addn-hosts を組合せて使用する。
# /etc/dnsmasq.confファイル no-hosts addn-hosts=/etc/hosts-dnsmasq
# /etc/hosts-dnsmasqファイル 192.168.1.100 ns.raspi.com ns 192.168.1.101 client1.raspi.com client1 192.168.1.102 client2.raspi.com client2
expand-hosts を有効化している場合は、単純名 (例: client1) での問い合わせにも自動的に domain= で指定したドメインが付加される。
動作の流れ
DNSMasqの名前解決の動作の流れを、以下に示す。
- クライアントPCからDNSサーバ (DNSMasq) へ問い合わせが来る。
- ホスト名のみの場合 (例: sle)、local または hostsファイルを参照して名前解決を行う。
- ホスト名 + ドメイン名の場合 (例: sle.suse.com)、local または hostsファイルを参照して名前解決を行う。
- ドメイン外の場合 (例: google.co.jp)、上位のDNSサーバに問い合わせをフォワードする。
上流DNSへのフォワード応答はキャッシュされて、次回以降の同一クエリに対してはキャッシュから応答が返される。
systemd-resolvedとの競合回避
現代のLinuxディストリビューションでは、systemd-resolvedがデフォルトで有効化されている場合がある。
systemd-resolvedは、127.0.0.53:53 でスタブリスナーを起動するため、DNSMasqが53番ポートをバインドしようとすると Address already in use エラーで起動に失敗する。
競合を回避する手順を以下に示す。
- 設定ディレクトリを作成する。
sudo mkdir -p /etc/systemd/resolved.conf.d
- スタブリスナー無効化設定ファイルを作成する。
# /etc/systemd/resolved.conf.d/disable-stub.confファイル [Resolve] DNSStubListener=no
- systemd-resolvedを再起動する。
sudo systemctl restart systemd-resolved
- /etc/resolv.conf ファイルを再設定する。
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf # または手動で nameserver 127.0.0.1 を設定する
- DNSMasqを再起動する。
sudo systemctl restart dnsmasq
- 53番ポートのリッスン状況を確認する。
sudo ss -tulpn | grep :53
※注意
NetworkManagerの dns=dnsmasq 設定は、NetworkManagerが独自のDNSMasqインスタンスを起動する機能である。
スタンドアロンでDNSMasqを運用する場合は、/etc/NetworkManager/NetworkManager.conf ファイルの dns= を default 等に変更して無効化することが推奨される。
systemd-resolvedのスタブリスナーを無効化した後は、/etc/resolv.conf ファイルがDNSMasq (127.0.0.1) を向くように設定すること。
DNSMasqの起動と停止
DNSMasqの起動、停止、有効化、無効化、再起動、状態確認、ログ確認のコマンドを以下に示す。
- 起動
sudo systemctl start DNSMasq
- 停止
sudo systemctl stop dnsmasq
- 自動起動の有効化
sudo systemctl enable dnsmasq
- 自動起動の無効化
sudo systemctl disable dnsmasq
- 再起動
sudo systemctl restart dnsmasq
- 状態確認
sudo systemctl status dnsmasq
- ログ確認
sudo journalctl -u dnsmasq
ファイアウォールの設定
下表に、DNSMasqが使用するポートを環境別に示す。
| 環境 | ツール | DNS (53/UDP+TCP) | DHCP (67/UDP) | TFTP (69/UDP) | コマンド例 |
|---|---|---|---|---|---|
| RHEL | firewalld | dnsサービス | dhcpサービス | tftpサービス | sudo firewall-cmd --permanent --add-service=dns
|
| SUSE | firewalld | dnsサービス | dhcpサービス | tftpサービス | sudo firewall-cmd --permanent --add-service=dns
|
| Raspberry Pi OS | ufw | 53/TCP+UDP | 67/UDP | 69/UDP | sudo ufw allow 53/udp
|
firewalldの場合
# DNS (53/UDP, 53/TCP) の許可 sudo firewall-cmd --permanent --add-service=dns ## またはゾーンを指定 sudo firewall-cmd --zone=internal --permanent --add-service=dns # DHCP (67/UDP) の許可 sudo firewall-cmd --permanent --add-service=dhcp # TFTP (69/UDP) の許可 (PXEブートを使用する場合) sudo firewall-cmd --permanent --add-service=tftp # 設定の反映 sudo firewall-cmd --reload
ポートを閉じる場合は、--add-service オプションを --remove-service オプションに置き換える。
ufwの場合
# DNS (53/UDP, 53/TCP) の許可 sudo ufw allow 53/udp sudo ufw allow 53/tcp # DHCP (67/UDP) の許可 sudo ufw allow 67/udp # TFTP (69/UDP) の許可 (PXEブートを使用する場合) sudo ufw allow 69/udp # 設定の確認 sudo ufw status
クライアントPCの設定
クライアントPCから内部向けDNSサーバを利用するための設定を行う。
まず、ドメイン検索の設定を行う。
- KDEを使用している場合
- [KDEシステム設定]を起動して、[接続]を選択する。
- [接続]画面左の接続名を選択して、[接続]画面右の[IPv4]タブ - [DNSサーバ:]項目に内部向けDNSサーバのIPアドレスを追加する。
- 同様に、[接続]画面右の[IPv4]タブ - [検索ドメイン:]項目に内部向けDNSサーバのドメイン名を入力する。
例えば、DNSサーバ名が ns.suse.com の場合、suse.com と入力する。
- リゾルバファイルを編集する場合
- /etc/resolv.conf ファイルにおいて、内部向けDNSサーバのドメイン名を入力する。
- 例えば、DNSサーバ名が ns.suse.com の場合、suse.com と入力する。
sudo vi /etc/resolv.conf
# /etc/resolv.confファイル domain suse.com # または search suse.com
- SUSEの場合は、編集後に以下に示すコマンドを実行する。
sudo netconfig update -f
次に、クライアントPCのネットワークを再起動する。
- systemctlコマンドを使用する場合
sudo systemctl restart NetworkManager
- nmcliコマンドを使用する場合
- NetworkManagerの全てのインターフェイスを停止した後、これらを起動する。
sudo nmcli networking off sudo nmcli networking on
動作確認
digコマンド
digコマンドは、DNSクエリを送信して応答を確認するツールである。
digコマンドを含むパッケージはディストリビューションにより異なる。
# RHEL sudo dnf install bind-utils # SUSE sudo zypper install bind-utils # Raspberry Pi sudo apt install dnsutils
digコマンドの基本的な使用方法を以下に示す。
# OSに設定されているDNSサーバに問い合わせ dig <問い合わせホスト名> # @以下で指定したDNSサーバに問い合わせ dig @<DNSサーバIP> <問い合わせホスト名> # IPアドレスからの逆引き dig -x <IPアドレス>
digコマンドの主なオプション
下表に、digコマンドの主なオプションを示す。
| オプション | 説明 |
|---|---|
@<server> |
クエリ送信先DNSサーバを指定 |
-x <ip> |
逆引きクエリ (in-addr.arpa自動構築) |
+short |
回答値のみを出力 |
+noall +answer |
ANSWERセクションのみ表示 |
+trace |
ルートサーバから委任チェーンを追跡 |
+time=<sec> |
クエリタイムアウト (デフォルト5) |
+tries=<num> |
再試行回数 (デフォルト3) |
+recurse |
再帰クエリ要求 (デフォルト有効) |
+norecurse |
非再帰クエリ要求 |
+tcp |
TCPで送信 |
+dnssec |
DNSSECレコードを要求 |
+domain=<name> |
検索ドメインを付加 |
+search |
/etc/resolv.conf ファイルのsearchを使用 |
-p <port> |
ポートを指定 |
正引きおよび逆引き
各クライアントPCの正引きおよび逆引きができるかどうかを確認する。
nslookupコマンドを使用する例を以下に示す。
nslookup ns.suse.com # 内部向けDNSサーバの正引き nslookup pc1.suse.com # クライアントPC 1の正引き nslookup pc2.suse.com # クライアントPC 2の正引き nslookup pc3.suse.com # クライアントPC 3の正引き nslookup 192.168.1.XX # 内部向けDNSサーバの逆引き nslookup 192.168.1.YY # クライアントPC 1の逆引き nslookup 192.168.1.ZZ # クライアントPC 2の逆引き nslookup 192.168.1.AA # クライアントPC 3の逆引き
digコマンドを使用する例を以下に示す。
# 正引き (回答値のみ) dig @127.0.0.1 ns.suse.com +short dig @127.0.0.1 pc1.suse.com +short # 逆引き (回答値のみ) dig -x 192.168.1.XX +short dig -x 192.168.1.YY +short
再帰問い合わせが無効の場合 (recursion=no) は、クライアントPCのIPアドレスを直接指定して問い合わせる。
dig @<PCのIPアドレス> <ドメイン名> # 例1 dig @192.168.10.5 ns.suse.net # 例2 dig @192.168.10.6 pc01.suse.net
トラブルシューティング
53番ポートが既に使用されている
- 原因
- systemd-resolved または 他のDNSサーバ (bind, unbound, Pi-hole等) が53番ポートを占有している。
- 確認方法
sudo ss -tulpn | grep :53
- 解決方法
- systemd-resolvedのスタブリスナーを無効化する。
前述のsystemd-resolvedとの競合回避セクションを参照すること。 - 他のDNSサーバを停止する。
- dnsmasq を再起動する。
- systemd-resolvedのスタブリスナーを無効化する。
名前解決できない (上流DNS到達不可)
- 原因
- /etc/resolv.conf ファイル または
--resolv-fileオプションで指定した上流サーバに到達不能。
- /etc/resolv.conf ファイル または
- 確認方法
dig @8.8.8.8 example.com +short sudo journalctl -u dnsmasq
- 解決方法
- /etc/resolv.conf ファイルの内容を確認して、到達可能な上流DNSを指定する。
no-resolv使用時は、server=で上流DNSを明示指定する。- ファイアウォールで53番ポート (UDP / TCP) の送信を許可する。
設定ファイルの構文エラー
- 原因
- オプション名の誤り あるいは 値の形式間違い。
- 確認方法
sudo dnsmasq --test
- 解決方法
--testオプションで指摘された行を修正する。- 再度、
--testオプションを付加して検証する。 - DNSmasqを再起動する。
sudo systemctl restart dnsmasq
サービスが起動しない
- 原因
- 構文エラー、53番ポートの競合、interfaceが存在しない、権限不足
- 確認方法
sudo systemctl status dnsmasq sudo journalctl -u dnsmasq sudo systemctl is-enabled dnsmasq
- 解決方法
dnsmasq --testオプションで構文を修正する。- 53番ポートの競合問題を解決する。
前述のsystemd-resolvedセクションを参照すること。 - bind-interfaces を bind-dynamic に変更する。
- masked状態の場合は、unmaskする。
sudo systemctl unmask dnsmasq.service
DNS再バインディング攻撃を止める
- 原因
- 外部攻撃者がDNS応答でプライベートIPを返して、内部ネットワークへアクセスを試みる。
- 確認方法
sudo journalctl -u dnsmasq | grep -i rebind
- 解決方法
- stop-dns-rebind を有効化する。
- 例外ドメインは、rebind-domain-ok=<domain> で指定する。
- rebind-localhost-ok で、127.0.0.0/8 と ::1 をrebind除外に設定する。
関連情報
- dnsmasq 公式ドキュメント
- dnsmasq man ページ
- Red Hat Enterprise Linux 10 ドキュメント
- SUSE Linux Enterprise Server 16 ドキュメント
- Raspberry Pi 公式ドキュメント
- サーバ - DHCP