BINDでDNSサーバーを構築する方法

# 概要
BINDを使用してDNSサーバーを構築します。DNSサーバーで2台のWebサーバーが名前解決できるように設定します。
## 検証環境
VMWare ESXi上の仮想環境に構築します。
OS:Ubuntu 22.04 LTS
DNSサーバー:ns.internal.
IPアドレス:192.168.22.1

Webサーバー1:www1.internal.
IPアドレス:192.168.20.1

Webサーバー2:www2.internal.
IPアドレス:192.168.21.1
ネットワーク構成
![スクリーンショット 2024-11-22 135202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3893444/b1d7f550-94a7-9e12-fc3f-c4b0d7d6dadb.png)

引用先：https://qiita.com/grandes_vacances/private/5f2ef017a3f5bb0f38f6

BINDのバージョン:BIND 9.18.28
## DNSとは？
DNS (Domain Name System) は、ドメイン名をIPアドレスに変換するアプリケーション層のプロトコルです。DNSの仕組みによって、覚えにくいIPアドレスの代わりに、覚えやすいURLを入力してWebにアクセスできます。

## FQDNの構造
FQDNの例
www.google.example.com
ホスト名.サブドメイン.ドメイン名.トップレベルドメイン(TLD)
ルートドメイン.は省略されます。


# 手順
## 1.BINDインストール

`sudo apt install bind9 bind9utils -y`

## 2.BIND設定ファイルを編集する
まずBINDの設定ファイルのディレクトリに移動します。

`cd /etc/bind/`

ファイルを編集します。

`sudo vi named.conf.default-zones`

```xxx:実行結果
// prime the server with knowledge of the root servers
zone "." {
        type hint;
        file "/usr/share/dns/root.hints";
};

// be authoritative for the localhost forward and reverse zones, and for
// broadcast zones as per RFC 1912

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

zone "127.in-addr.arpa" {
        type master;
        file "/etc/bind/db.127";
};

zone "0.in-addr.arpa" {
        type master;
        file "/etc/bind/db.0";
};

zone "255.in-addr.arpa" {
        type master;
        file "/etc/bind/db.255";
};
＃internal. という名前のドメインゾーンを追加するため以下を追加する
zone "internal." {
    type master;
    file "/etc/bind/db.internal";＃ゾーン情報を定義するファイル
    allow-update { none; };
};
```
## 3.ゾーンファイルを編集する
db.internalというゾーンファイルを作成し、ドメイン名とIPアドレスの対応情報を入れます。

`sudo vim db.internal`

Aレコード：ドメイン名に対応するIPアドレス(IPv4)を指定する
NSレコード：ドメイン名と権威サーバを指定する
```xxx:実行結果
$TTL 8h
@ IN SOA ns.internal. hostmaster.internal. ＃権威DNSサーバーと管理者メールアドレスを設定する(
                          2024092002 ; serial number＃シリアルナンバーを編集
                          1d         ; refresh period
                          3h         ; retry period
                          3d         ; expire time
                          3h )       ; minimum TTL

ns                IN A    192.168.22.1
@                 IN NS   ns.internal.
www1              IN A    192.168.20.1
www2              IN A    192.168.21.1
```

:::note info
リソースレコードの省略表記
* 明示的にORIGINを指定しない場合、そのゾーンファイルのドメイン名が暗黙に指定される。
* ORIGINと同じドメイン名は @ で記載される。 例 - internal. ⇒ @
* ORIGINの前にホスト名を付加する場合はそのホスト名を記載して最後に「. 」をつけない。例 - www1.internal. ⇒ www1
（ドメイン名の最後に「. 」をつけるとFQDNと解釈される。「 . 」をつけないと ORIGIN の内容が末尾に付加されることになる。）
引用先：https://www.infraexpert.com/study/tcpip23.html#google_vignette）
:::

今回は権威サーバーを設定する際、`ns.internal` に最後のピリオドをつけ忘れたため、`ns.internal.internal.` となってしまいました。`named-checkconf` や `named-checkzone` では構文エラーが表示されなかったものの、この設定ミスにより、DNSサーバーが正しく応答できませんでした。


## 4.サーバーを再起動する
設定ファイルを編集したため、DNSサーバーを再起動します。

`systemctl restart named`


## 5.サーバーの状態を確認する

`sudo systemctl status named`

activeになっていることを確認します。
```xxx:実行結果
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2024-09-20 07:04:32 UTC; 5 days ago
       …
```
## 6.名前解決が正常に行われているかを確認する
`dig www1.internal @localhost`
`dig`は、DNSのクエリツールで、特定のドメイン名に対してDNSサーバーに問い合わせを行い、そのドメインに関するDNS情報を取得します。

www1.internal というドメインに対してAレコードの問い合わせを行います。

@ の後に続くのは、クエリを送信するDNSサーバーの指定です。この場合、localhostに指定することで、ローカルで動作しているDNSサーバーに対して問い合わせを行います。

出力の中からANSWER SECTIONの部分を確認すると、クエリ対象www1.internal. とIPアドレス192.168.20.1表示されていることから、名前解決が成功していることがわかります。
さらに、NOERROR表示されているから、クエリが正常に処理されたことが分かります。

```xxx:実行結果
; <<>> DiG 9.18.28-0ubuntu0.22.04.1-Ubuntu <<>> www1.internal @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 6681
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: f51bd9442e42a47b0100000066ed1eefd6ba5c9a82c23936 (good)
;; QUESTION SECTION:
;www1.internal.                 IN      A

;; ANSWER SECTION:
www1.internal.          28800   IN      A       192.168.20.1

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(localhost) (UDP)
;; WHEN: Fri Sep 20 07:06:23 UTC 2024
;; MSG SIZE  rcvd: 86
```

もう一つのWebサーバーも確認します。

`dig www2.internal @localhost`を実行します。
```xxx:実行結果
; <<>> DiG 9.18.28-0ubuntu0.22.04.1-Ubuntu <<>> www2.internal @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57535
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 31fec689282c4b090100000066ed1f607c6266255918c6ba (good)
;; QUESTION SECTION:
;www2.internal.               IN      A

;; ANSWER SECTION:
www2.internal.        28800   IN      A       192.168.21.1

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(localhost) (UDP)
;; WHEN: Fri Sep 20 07:08:16 UTC 2024
;; MSG SIZE  rcvd: 88
```
こちらも正常に名前解決ができています。

参考資料
[BIND DNS サーバーでのゾーンの設定](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/managing_networking_infrastructure_services/assembly_configuring-zones-on-a-bind-dns-server_assembly_setting-up-and-configuring-a-bind-dns-server)
[BIND9ServerHowto](https://help.ubuntu.com/community/BIND9ServerHowto)
[DNS zone / DNS records](https://www.infraexpert.com/study/tcpip23.html#google_vignette)