Raspberry PiにDnsmasqをインストールする


家のネットワーク用にDNSサーバーが欲しくなったのでRaspberry PiにDnsmasqをインストールした。
また、AnsibleでセットアップできるようにRaspbianにDnsmasqをセットアップするplaybookも書いた。

# 環境
構築したDNSサーバーの次の通り。

* Raspberry Pi 2 Model B
* Raspbian Jessie Lite (version: May 2016, Release date: 2016-05-27）
* Dnsmasq 2.72

ちなみに、[Raspbian Jessieのダウンロードサイト](https://www.raspberrypi.org/downloads/raspbian/)に通常のものとLite版があるが、通常のものがデスクトップ用途で約1.3GBあるのに対してLite版は約290MBと1GBほどサイズが小さくなってるので、サーバー用途ならば速くダウンロードできるLite版がおすすめ。

# 前提条件
Dnsmasqをインストールする前にRaspberry Piをセットアップしてネットワークに接続できるようにしておく。

今回は有線接続・固定アドレスでセットアップした。
Raspbian Jessieでの固定アドレスの設定方法は次の記事が参考になる。

[Raspberry Pi に固定IPアドレスを割り当てる方法（Raspbian Jessie）](http://qiita.com/MarieKawasuji/items/b088ffb252a92eee8f5d)

# Dnsmasq
[Dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html)は小規模ネットワーク向けのDNS・DHCPサーバーで、今回のように簡単にDNSサーバーを立てたい時に適している。

## インストール
インストールはapt-getから行う。

    $ sudo apt-get install dnsmasq

## Dnsmasqの設定
設定は/etc/dnsmasq.confを編集する。

    $ sudo vi /etc/dnsmasq.conf

変更するのは次の3箇所。

    # ドメイン名がない場合は上位DNSサーバーに転送しない
    #domain-needed ← コメントアウトを外す
    domain-needed
    
    # プライベートIPアドレスの逆引き要求を上位DNSサーバーに転送しない
    #bogus-priv ← コメントアウトを外す
    bogus-priv
    
    # ローカルなドメインを/etc/hostsかDHCPでのみ解決する
    #local=/localnet/ ← コメントアウトを外して値を変更する
    local=/sample.com/

## レコードの設定
Dnsmasqではレコードを/etc/hostsに設定する。

    $ sudo vi /etc/hosts
    ...
    # 最後にレコードを追記する
    192.168.0.10    raspi1.sample.com
    
## 動作確認
設定が終わったのでDnsmasqを起動する。

    $ sudo service dnsmasq start

今回は動作確認にWindows 10を使う。
まずはネットワークアダプタの設定を変更して、優先DNSサーバーにRaspberry PiのIPアドレスを指定する。

<img width="512px" alt="ehternet-property.png" src="https://qiita-image-store.s3.amazonaws.com/0/39729/193e6e33-f3ab-487e-a8d4-89d5ed4afcd6.png"/>

次にコマンドプロンプトを起動してnslookupを実行する。

    > nslookup raspi1.sample.com
    サーバー:  raspi1.sample.com
    Address:  192.168.0.10
    
    名前:    raspi1.sample.com
    Address:  192.168.0.10
    
    > nslookup 192.168.0.10
    サーバー:  raspi1.sample.com
    Address:  192.168.0.10
    
    名前:    raspi1.sample.com
    Address:  192.168.0.10

ドメイン名とIPアドレスのどちらを指定しても、レコードとして設定したアドレスとドメイン名が返ってくればOK。

### 補足：pingで確認すると失敗する
Windowsでpingを使って名前解決を試したら次のようなエラーが出て失敗した。

    > ping raspi1.sample.com
    ping 要求ではホスト raspi1.sample.com が見つかりませんでした。ホスト名を確認してもう一度実行してください。

調べたらnslookupとpingで名前解決の動作が異なるらしい。

[Windows nslookupで名前解決できるのにpingで名前解決できない問題の真相 | Linuxジャパン技術者ブログ](http://linux-japan.co.jp/tech-blog/blog/2014/05/25/windows-nslookup%E3%81%A7%E5%90%8D%E5%89%8D%E8%A7%A3%E6%B1%BA%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%AE%E3%81%ABping%E3%81%A7%E5%90%8D%E5%89%8D%E8%A7%A3%E6%B1%BA%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E5%95%8F/)

このエラーは上のサイトにあったDNSのキャッシュのクリアで解決した。

    > ipconfig /flushdns

# Ansibleのplaybook
上に書いたインストールと設定を行うplaybookを参考までに載せておく。



    # raspi.yml
    - hosts: raspi1
      remote_user: pi
      become: true
      vars:
        dnsmasq_ver: 2.72-3+deb8u1
      tasks:
        - name: install dnsmasq
          apt: name=dnsmasq={{ dnsmasq_ver }} state=present
    
        - name: setup dnsmasq
          lineinfile:
            dest=/etc/dnsmasq.conf
            backrefs=yes
            state=present
            regexp='{{ item.regexp }}'
            line='{{ item.line }}'
          with_items:
            - regexp: '#domain-needed'
              line: 'domain-needed'
            - regexp: '#bogus-priv'
              line: 'bogus-priv'
            - regexp: '#local=/localnet/'
              line: 'local=/sample.com/'
          notify:
            - restart dnsmasq
    
        - name: setup hosts
          lineinfile:
            dest=/etc/hosts
            line={{ item }}
          with_items:
            - '192.168.0.10    raspi1.sample.com'
          notify:
            - restart dnsmasq
      handlers:
        - name: restart dnsmasq
          service: name=dnsmasq state=restarted