RHEL8 上に BIND を構築する


#1.はじめに

社内のローカル環境で使用する DNS サーバーが必要になったので、BIND を構築しました。

環境は RHEL 8.2 を使用しています。

#### 環境のイメージ図
![イメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/fb1630f2-555e-d662-b6e8-eded88819454.png)


# 2.BIND のインストール

```
$ yum install bind bind-utils
```
bind-utils は、 dig 等の、細かな設定確認のために必要なコマンドが含まれています。

# 3.作業に必要な基本コマンド

参照用に作業に必要な基本的なコマンドを並べておきます。

```
# 起動   (named.service と書かれている場合もあるが、結果は同じ) 
$ systemctl start named 

# 停止
$ systemctl stop named

# 設定のリロード
$ systemctl reload named

# ステータスの確認
$ systemctl status named

# 自動起動
$ systemctl enable named

# 自動起動設定確認
$ systemctl is-enabled named

# named.conf の書式確認 (書いた設定ファイルにエラーが無いか確認するコマンド）
$ named-checkconf -z /etc/named.conf
```

# 4.設定作業

ここでは、Zone を一つだけ作成します。ローカルだけで使用される Zone の名前は「example.localdomain」です。
はじめは、.local を使用しようとしたのですが、検索してみると.local 基本的に使用しないほうが良いようなので、localdomain を使用しました。

BINDの設定作業は、設定ファイルを書く事が作業の殆どを占めます。
1つめは、/etc/named.conf 
2つめは、/etc/named.conf  から参照される Zone の定義を記述した  /etc/<ゾーン名>.zone です（このファイル名は何でも良い）

##4.1.named.conf の編集

/etc/named.conf を編集します。

```/etc/named.conf
//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//
//変更箇所1：このBINDにアクセスしても OKなネットワークを internalnet と言う名前で定義します。ここでは、2つの内部ネットワークを許可のリストに入れています。
acl "internalnet"{192.168.124.0/24; 172.16.0.0/24;};
options {
        //変更箇所2：以下2行はとりあえず、コメントアウト（ Listen する IPを固定するために使用する）
        // listen-on port 53 { 127.0.0.1; };
        // listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        secroots-file   "/var/named/data/named.secroots";
        recursing-file  "/var/named/data/named.recursing";
        // allow-query     { localhost; };
        // 変更箇所3: allow-query　に internalnet を追加します。デフォルトだと localhost なので、外からDNS Query を受け付けません。
        allow-query     {internalnet; localhost; };

        /*
         - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
         - If you are building a RECURSIVE (caching) DNS server, you need to enable
           recursion.
         - If your recursive DNS server has a public IP address, you MUST enable access
           control to limit queries to your legitimate users. Failing to do so will
           cause your server to become part of large scale DNS amplification
           attacks. Implementing BCP38 within your network would greatly
           reduce such attack surface
        */
        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;

        managed-keys-directory "/var/named/dynamic";

        pid-file "/run/named/named.pid";
        session-keyfile "/run/named/session.key";

        /* https://fedoraproject.org/wiki/Changes/CryptoPolicy */
        include "/etc/crypto-policies/back-ends/bind.config";

        // 変更箇所4. 追加Forwarder
        // この BINDサーバーで解決できないドメイン名の解決をお願いする別のDNSサーバーのIPアドレス。
        forwarders {192.168.124.10;};

};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
        type hint;
        file "named.ca";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

//変更箇所5:今回、管理したい Zone名についての記述。
// 実際の定義は、file "..." の部分で行うので、ここで指定したフィル名のファイルを別途作成する。
zone "example.localdomain" {
      type master;
      file "/etc/named/named.example.localdomain.zone";
};

```
##4.2.Zoneの定義ファイルの作成

Zone を定義したファイル(`/etc/named/named.example.localdomain.zone`) を作成します。
前述の named.conf の中に記述したファイル名です。
ファイル名に決まりは無いはずですが、管理している Zone 名を入れるのが一般的だと思います。

```/etc/named/named.example.localdomain.zone
$ORIGIN example.localdomain.
$TTL 3600
@       IN      SOA     ns1.example.localdomain. root.example.localdomain.(
                                2000091801      ; Serial
                                3600            ; Refresh
                                900             ; Retry
                                3600000         ; Expire
                                3600 )          ; Minimum
        IN      NS      ns1.example.localdomain.
ns1     IN      A       192.168.124.101
bastion IN      A       192.168.124.102
ldap    IN      A       192.168.124.103
lb1     IN      A       192.168.124.110
lb2     IN      A       192.168.124.111
```
※(.) 等を書き落とすと、エラーになるので注意します。

SOA レコード（SOAと書いてある行) の `ns1.example.localdomain.` は、Primary の Name Serverの FQDN名です。
`root.example.localcomain.` は、この Zoneの管理者のメールアドレスで、頭のroot.の(.)部分は、@に読み替えて、root@ と読み替えて理解します。実際には存在していなくても動作上は問題ありません。

##4.3.設定の反映

`named.conf` や、そこから参照される zone の定義ファイルは、良く書き間違えします。実際に BINDに食べさせる前に、エラーが無いかを確認します。

```
# named.conf の書式確認 (書いた設定ファイルにエラーが無いか確認するコマンド）
$ named-checkconf -z /etc/named.conf
```

**BINDの起動**
設定ファイルにエラーがなければ、以下のコマンドで起動します。

```
# 起動   (named.service と書かれている場合もあるが、結果は同じ) 
$ systemctl start named 
```

**BIND起動の確認**
起動の確認コマンドです。もし起動に失敗している場合は、エラーログも確認できます。

```
# ステータスの確認
$ systemctl status named
```
設定ファイルが上手く書けていても、起動時にポートが使われている等で起動しないケースがあります。

**実際に名前解決を行って確認**

Zone ファイルに記載された ns1 というドメイン名が解決できるか、実際に試して見ます。

```
 # +short は出力を簡略化するためのオプション
$ dig @localhost ns1.example.localdomain +short  
192.168.124.101   # Zone ファイルに定義した IPが返ってくるはずです。
```

また、このBINDサーバーでは、`www.yahoo.co.j` 等のドメインの情報は持っていないため、自分では解決できません。
`named.conf` の中に、`forwarders` という記述で、自分の守備範囲でないドメインの解決先を指定しました。
その指定が上手く行ってるか確認します。

````
$ dig @localhost www.yahoo.co.jp +short
edge12.g.yimg.jp.   # +short を外すとわかりますが、一旦このドメイン名に CNAME（別のドメイン名に変換）されています。
182.22.25.252       # CNAMEされた先のドメイン名のIPアドレス
````

#5.Firewall への穴あけ

`RHEL 8.2` では、デフォルトで `firewalld` サービスが稼働していて dns のポートが塞がれています。
そのため、外部からの dns Query リクエストに応えられません。
以下のコマンドで穴あけをします。

```
# dns というサービス名で許可/不許可ができるように事前に dns という名前が `firewalld` に登録されています。
# DNS を許可されたサービスに追加します。
$ firewall-cmd --add-service=dns
success

# 新しい設定を永続化させます。
$ firewall-cmd --runtime-to-permanent
success
$
```

#6.逆引きの設定
逆引きの設定は以下のように行います

##6.1.named.conf の編集

ここでは、逆引き用の設定ファイルとして、`/etc/named/0.16.172.in-addr.arpa.zone` というファイルを作成する事にします。
`named.conf`内で、このファイルを参照するように、以下のように指定します。

```/etc/named.conf
<省略>

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";

// 順引き用ファイルの指定
zone "example.localdomain" {
      type master;
      file "/etc/named/named.example.localdomain.zone";
};

// 逆引き用のファイルの指定 (書式はこういうものだと覚える) 
zone "0.16.172.in-addr.arpa" in {
     type master;
    file "/etc/named/0.16.172.in-addr.arpa.zone";
};

```

##6.2.逆引き用ファイルの作成

逆引き用のファイルは以下のように書きます。

```
$TTL 3600
@       IN      SOA     ns1.example.localdomain. root.example.localdomain.(
                                2000091803      ; Serial
                                3600            ; Refresh
                                900             ; Retry
                                3600000         ; Expire
                                3600 )          ; Minimum
      IN          NS      ns1.example.localdomain.
;
101   IN  PTR ns1.example.localdomain.
102   IN  PTR bastion.ocp45.example.localdomain.
103   IN  PTR ldap.ocp45.example.localdomain.
110   IN  PTR lb1.ocp45.example.localdomain.
111   IN  PTR lb2.ocp45.example.localdomain.
```

##6.3.設定の反映

**ファイルの書式チェック**

```
named-checkconf -z /etc/named.conf
```

**リロード**

```
systemctl reload named
```

**動作確認**

```
$ dig +norec -x 172.16.0.102 +short
bastion.ocp45.example.localdomain.
$ 
```
`+norec` 非再帰的 Queryを実行。キャッシュサーバーの立場[^1]と同じ形式で問い合わせを行う。
`-x`　逆引き
`+short` 出力を短く

[^1]: <a href="https://www.atmarkit.co.jp/ait/articles/1412/19/news015.html">digコマンドやdrillコマンドの使い方を教えてください