設定 - DNSMasq

提供: MochiuWiki : SUSE, EC, PCB

概要

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が提供する主な機能を示す。

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 オプションで指定したファイル
  • 上流DNS参照ファイル
    /etc/resolv.conf (デフォルト) または --resolv-file オプションで指定したファイル
  • リースファイル
    /var/lib/dnsmasq/dnsmasq.leases
    DHCPリース情報が記録される。


ドロップインディレクトリを活用することにより、/etc/dnsmasq.conf ファイルを直接編集せずに設定を追加できる。

/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サーバ機能の主な設定項目
設定項目 デフォルト値 説明
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-hostsaddn-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の名前解決の動作の流れを、以下に示す。

  1. クライアントPCからDNSサーバ (DNSMasq) へ問い合わせが来る。
  2. ホスト名のみの場合 (例: sle)、local または hostsファイルを参照して名前解決を行う。
  3. ホスト名 + ドメイン名の場合 (例: sle.suse.com)、local または hostsファイルを参照して名前解決を行う。
  4. ドメイン外の場合 (例: google.co.jp)、上位のDNSサーバに問い合わせをフォワードする。


上流DNSへのフォワード応答はキャッシュされて、次回以降の同一クエリに対してはキャッシュから応答が返される。


systemd-resolvedとの競合回避

現代のLinuxディストリビューションでは、systemd-resolvedがデフォルトで有効化されている場合がある。

systemd-resolvedは、127.0.0.53:53 でスタブリスナーを起動するため、DNSMasqが53番ポートをバインドしようとすると Address already in use エラーで起動に失敗する。

競合を回避する手順を以下に示す。

  1. 設定ディレクトリを作成する。
    sudo mkdir -p /etc/systemd/resolved.conf.d
  2. スタブリスナー無効化設定ファイルを作成する。
     # /etc/systemd/resolved.conf.d/disable-stub.confファイル
     
     [Resolve]
     DNSStubListener=no
    

  3. systemd-resolvedを再起動する。
    sudo systemctl restart systemd-resolved
  4. /etc/resolv.conf ファイルを再設定する。
     sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
     # または手動で nameserver 127.0.0.1 を設定する
    
  5. DNSMasqを再起動する。
    sudo systemctl restart dnsmasq
  6. 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を使用している場合
    1. [KDEシステム設定]を起動して、[接続]を選択する。
    2. [接続]画面左の接続名を選択して、[接続]画面右の[IPv4]タブ - [DNSサーバ:]項目に内部向けDNSサーバのIPアドレスを追加する。
    3. 同様に、[接続]画面右の[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コマンドの主なオプションを示す。

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 を再起動する。


名前解決できない (上流DNS到達不可)

  • 原因
    /etc/resolv.conf ファイル または --resolv-file オプションで指定した上流サーバに到達不能。

  • 確認方法
     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-interfacesbind-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除外に設定する。



関連情報