Ansibleで自宅サーバーにBIND9 DNSサーバーを構築

Table of Contents

1. はじめに

今回は、Ubuntu 24.04 サーバーにBIND9を使ってDNSサーバーを構築しました!

保守性を考えて Ansible Playbook を使った構築になっています。

2. Ansible Playbook 構成

今回作成したプレイブックの構成はこんな感じです:

home-dns/
├── README.md
├── bind9.yml
├── inventory.yml
├── requirements.txt
└── templates/
    ├── db.j2
    ├── named.conf.local.j2
    └── named.conf.options.j2

シンプルな構成で、最低限必要な機能を提供します。

Task

bind9.ymlがメインのプレイブックです:

- name: Deploy BIND9 DNS Server
  hosts: dns_servers
  become: true
  vars:
    local_network: <LOCAL_NETWORK_CIDR>
    domain_name: <DOMAIN_NAME>

  tasks:
    - name: Update apt cache
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Install BIND9
      ansible.builtin.package:
        name:
          - bind9
          - bind9utils
          - dnsutils
        state: present

    - name: Configure named.conf.options
      ansible.builtin.template:
        src: named.conf.options.j2
        dest: /etc/bind/named.conf.options
        owner: root
        group: bind
        mode: "0644"
      notify: restart bind9

    - name: Configure named.conf.local
      ansible.builtin.template:
        src: named.conf.local.j2
        dest: /etc/bind/named.conf.local
        owner: root
        group: bind
        mode: "0644"
      notify: restart bind9

    - name: Create zone file
      ansible.builtin.template:
        src: db.j2
        dest: /etc/bind/db.{{ domain_name }}
        owner: root
        group: root
        mode: "0644"
      notify: restart bind9

    - name: Start and enable BIND9
      ansible.builtin.service:
        name: bind9
        state: started
        enabled: true

  handlers:
    - name: restart bind9
      ansible.builtin.service:
        name: bind9
        state: restarted

bind9をインストールし、設定ファイルをテンプレートから生成して配置、bind9 serviceの起動を行います。

3. BIND9設定 Template

基本オプション設定

templates/named.conf.options.j2

options {
    directory "/var/cache/bind";

    // Forwarders
    forwarders {
        1.1.1.1;
        8.8.8.8;
    };

    // Allow queries from
    allow-query {
        127.0.0.1;
        {{ local_network }};
    };

    // Basic settings
    recursion yes;
    dnssec-validation auto;
    listen-on-v6 { any; };
};

ここで重要なのは:

  • forwarders: 外部ドメインのクエリをCloudflare (1.1.1.1)とGoogle (8.8.8.8)に転送
  • allow-query: ローカルネットワークからのクエリのみ許可
  • recursion: 再帰クエリを有効化

といった感じです。

ローカルゾーン設定

templates/named.conf.local.j2

//
// Local zone configuration
//

zone "{{ domain_name }}" {
    type master;
    file "/etc/bind/db.{{ domain_name }}";
};

ローカルドメインのゾーン設定のファイルを指定しています。

ゾーンファイル

templates/db.j2

$TTL 604800
@       IN      SOA     ns.{{ domain_name }}. admin.{{ domain_name }}. (
                        2025081101      ; Serial
                        604800          ; Refresh
                        86400           ; Retry
                        2419200         ; Expire
                        604800          ; Negative Cache TTL
)

; Name servers
@       IN      NS      ns.{{ domain_name }}.

; A Records
ns      IN      A       {{ ansible_host }}
test    IN      A       {{ ansible_host }}

基本的なSOAレコードとNSレコード、そしてテスト用のAレコードを定義しています。test.<DOMAIN_NAME>でDNSサーバーのIPアドレスを取得できるようになっています。

4. デプロイと動作確認

デプロイ実行

プレイブックの実行は簡単です:

ansible-playbook -i inventory.yml bind9.yml

初回実行では、パッケージのインストールから設定ファイルの作成、サービスの起動まで自動で行われます。

動作確認

デプロイが完了したら、以下のコマンドで動作確認できます:

# ローカルドメインのテスト
dig @<DNS_SERVER> test.<DOMAIN_NAME>

# 外部ドメインの転送テスト
dig @<DNS_SERVER> google.com

正常に動作していれば、ローカルドメインは設定したIPアドレスが返され、外部ドメインは正しく解決されるはずです。

5. まとめ

AnsibleでBIND9 DNSサーバーを構築することで、自宅サーバー環境でローカルドメインによる名前解決を導入することができました。

今回のポイント:

  • Ansibleテンプレートを使った設定ファイルの自動生成
  • セキュリティを考慮したクエリ制限
  • 外部DNSへの適切な転送設定
  • ハンドラーを使った設定変更時の自動再起動

この構成なら、新しいサービスを追加するときもゾーンファイルのテンプレートを編集してプレイブックを実行するだけです。めっちゃ楽ですね!

自宅サーバー環境でDNSサーバーを運用すると、各種サービスへのアクセスがかなり便利になります。みなさんもぜひ試してみてください。

最後まで読んでいただき、ありがとうございました。

7. 参考資料