インフィニットループ 技術ブログ

2015年04月21日 (火)

著者 : mizuno_as

Dnsmasqでお手軽ご家庭DNSサーバーを作ろう

こんにちは、mizuno_asです。
単にアクセスしやすいからであったり、テスト環境で名前ベースのVirtualHostを使いたいからであったりとその理由は様々ですが、ローカルIPアドレスを使っているLAN内においても、名前解決したいというケースはよくありますよね。avahiでは嫌だし、hostsをメンテするのは大変だし、BINDを立てるのはコスト的に重い……。今日はそんな時に役立つかもしれない、Dnsmasqを紹介します。

Dnsmasqとは?

Dnsmasqとは、小規模ネットワーク向けのDNS/DHCP/TFTPサーバーです。UbuntuデスクトップではDNSリゾルバとしてNetworkManagerから起動されているため、知らず知らずのうちに利用している人も多いのではないでしょうか。Dnsmasqは自身の/etc/hostsファイルを参照してDNSクエリに応答してくれるため、/etc/hostsにレコードを追加するだけで、お手軽に家庭内DNSコンテンツサーバー兼キャッシュサーバーとして利用することができます。

Dnsmasqをインストールしよう

ここではUbuntu 14.04 LTS ServerにDnsmasqをインストールします。apt-getコマンドでdnsmasqパッケージをインストールするだけでDnsmasqが起動し、DNSサーバーとして動作しはじめます。

$ sudo apt-get install dnsmasq

前述の通りDnsmasqは、/etc/hostsを見てクエリに応答します。しかしそれだけではなく、キャッシュサーバーでもある以上、自分が知らないアドレスに対するクエリは上位のDNSサーバーにフォワードしなければなりません。Dnsmasqは通常、/etc/resolv.confを参照してクエリを投げる上位サーバーを決定します(ちなみに/etc/resolv.confを無視する”–no-resolv”というオプションもあります)。しかしUbuntuのパッケージからインストールされるDnsmasqはresolvconfと連携しており、

  • resolvconfが/var/run/dnsmasq/resolv.confを自動的に作成し、/etc/network/interfaces内でdns-nameserversオプションを使って指定されたDNSサーバーを書き込む。
  • /etc/resolv.confには127.0.0.1とだけ書き込む。
  • dnsmasqが/var/run/dnsmasq/resolv.confを読み込むよう、”-r”オプションつきで起動。

という振舞いをします。つまり上位DNSサーバーを指定したい場合は、かならず/etc/network/interfaces内に記述する必要があるのです。また常に”-r”オプションつきでdnsmasqプロセスが起動するため、/etc/dnsmasq.conf内で、”resolv-file”オプションを独自に指定することができないことに注意してください。

$ cat /etc/resolv.conf
nameserver 127.0.0.1
$ cat /etc/network/interfaces
(...snip...)
auto eth0
iface eth0 inet static
    address (IPアドレス)
    netmask (ネットマスク)
    network (ネットワークアドレス)
    broadcast (ブロードキャストアドレス)
    gateway (デフォルトゲートウェイのアドレス)
    dns-nameservers (上位DNSサーバーのアドレス)

DNSレコードを追加しよう

/etc/hostsにレコードを追加するだけです。追加後はDnsmasqのリスタートが必要です。

$ cat /etc/hosts
(...snip...)
10.0.3.1    www.example.com
10.0.3.2    db.example.com
10.0.3.3    app.example.com
$ dig @127.0.0.1 +norec www.example.com
;; QUESTION SECTION:
;www.example.com.		IN	A
;; ANSWER SECTION:
www.example.com.	0	IN	A	10.0.3.1

/etc/hostsを直接いじらない方法

DNSラウンドロビンとは、あるドメイン名に対して複数のIPアドレスを登録しておき、問い合わせの度に順番を入れ替えた応答を返すことで、サーバーへのアクセスを分散させる技術です。Dnsmasqでは/etc/hostsに以下のような記述をしておくことで、DNSラウンドロビンを実現することができます。

$ cat /etc/hosts
(...snip...)
10.0.3.11   web.example.com
10.0.3.12   web.example.com
10.0.3.13   web.example.com
10.0.3.14   web.example.com
10.0.3.15   web.example.com

/etc/nsswitch.confは、そのホストの名前解決の参照順を指定するファイルです。一般的な環境であれば

$ cat /etc/nsswitch.conf
(...snip...)
hosts:          files dns

のように書かれており、まず/etc/hostsを参照した後に、DNSサーバーへクエリを投げることになっているはずです。つまりDnsmasqサーバー自身はDnsmasqのサービスを経由せず、直接/etc/hostsを見て名前解決をしてしまうため、DNSラウンドロビンを期待しているアドレスに対して常に同じIPアドレスが返ってしまうのです。
そこで/etc/hostsを直接編集することはせず、別ファイルを読み込む方法を推奨します。Dnsmasqには”addn-hosts”という、指定した任意のファイルを個別に読み込ませるオプションが用意されています。またファイルでなくディレクトリを指定すると、そのディレクトリ内にあるすべてのファイルを読み込んでくれます。これらのファイルのフォーマットは/etc/hostsと同じです。
ちなみに/etc/hostsファイルをそもそも無視する”–no-hosts”というオプションもありますので、/etc/hostsとDnsmasq用のレコードを分離したいような場合に利用してみてください。

$ grep addn-hosts /etc/dnsmasq.conf
addn-hosts=/etc/add-hosts
$ cat /etc/add-hosts
10.0.3.11   web.example.com
10.0.3.12   web.example.com
10.0.3.13   web.example.com
10.0.3.14   web.example.com
10.0.3.15   web.example.com

キャッシュ数を変更しよう

/etc/dnsmasq.conf内の”cache-size”オプションで、キャッシュできるレコード数を指定することができます(デフォルトは150)。ここを”0″にしておけば、応答をキャッシュしなくなります。たとえばUbuntuでは、(NetworkManagerのパッケージに)dnsmasq起動時のコマンドラインオプションを強制的に”–cache-size=0″にする独自パッチが当たっているため、UbuntuデスクトップでNetworkManagerから起動されたdnsmasqはキャッシュリゾルバとしては動作しません。これはローカルDNSサーバーに対するキャッシュポイゾニングを想定したセキュリティ上の仕様となり、設定ファイルでキャッシュサイズをオーバーライドすることはできなくなっています。
またネガティブキャッシュのみキャッシュしない”–no-negcache”というオプションも存在します。詳しくはマニュアルを参照してください。

$ grep cache-size /etc/dnsmasq.conf
cache-size=1024

クエリログを記録しよう

セキュリティ的な理由で、あるいはデバッグ目的でクエリログを記録したい場合があるかもしれません。/etc/dnsmasq.confで”log-queries”オプションを指定すると、クエリログを出力することができます。ログのファシリティは”log-facility=local0″のように指定できますので、あとはrsyslogとログローテーションの設定を適宜行ってください。
あるいは、dnsmasqの起動時に”-q”オプションを与えることでも、クエリログを出力させることができます。Ubuntuの場合、/etc/default/dnsmasq内で起動時のオプションを指定していますので、一時的な設定であれば、ここに”-q”を書き加えてもよいでしょう。

$ grep log- /etc/dnsmasq.conf
log-queries
log-facility=local0
$ cat /var/log/syslog
(...snip...)
Apr 17 11:11:26 dnsmasq dnsmasq[1689]: query[A] infiniteloop.co.jp from 127.0.0.1
Apr 17 11:11:26 dnsmasq dnsmasq[1689]: forwarded infiniteloop.co.jp to 8.8.8.8
Apr 17 11:11:26 dnsmasq dnsmasq[1689]: reply infiniteloop.co.jp is 59.158.36.124
Apr 17 11:11:31 dnsmasq dnsmasq[1689]: query[A] infiniteloop.co.jp from 127.0.0.1
Apr 17 11:11:31 dnsmasq dnsmasq[1689]: cached infiniteloop.co.jp is 59.158.36.124

おわりに

このように、家庭内でちょっとだけDNSサーバーで名前解決したいんだけど……という時に、Dnsmasqはうってつけではないかと思います。またTFTPやDHCPサーバーの機能も持っているため、適切にセットアップされたDnsmasqをLAN内に置いておくだけで、「適当なLANポートにケーブルを挿してPCを起動すると、Ubuntuのインストールがはじまる」というようなネットワークを作ることもできそうです。ご家庭内DNSサーバーとして、導入を検討してみてみるのもいいかもしれませんね!

ブログ記事検索

このブログについて

このブログは、札幌市・仙台市の「株式会社インフィニットループ」が運営する技術ブログです。 お仕事で使えるITネタを社員たちが発信します!