BINDによるDNSサーバ構築 - マスターサーバ編


# BINDのインストール

## インストールパッケージ

### bind
BIND本体。

### bind-chroot
これをインストールすることで /var/named/chroot をルートディレクトリとみなしてBINDが動作する。
必須ではないが、BINDのセキュリティホールから攻撃を受けた場合の影響を低くすることができるのでインストールすることを推奨。
/var/named/chroot配下の設定ファイルは /etc の下にあるものがマウントされるので、通常は /etc 配下の設定ファイルを修正すればよい。

## インストールコマンド
グループインストールする場合。

```bash:Command
sudo yum groupinstall 'DNS Name Server'
```

個別にインストールする場合。
※依存関係で関連するbindのパッケージもまとめてインストールされる。

```bash:Command
sudo yum install bind-chroot
```

# BINDの起動、停止、リロード

```Bash:Command
# 起動
systemctl start named.service
# 停止
systemctl stop named.service
# リロード
systemctl reload named.service
# ステータス確認
systemctl status named.service
```

# ファイアウォールの設定
DNSサービスを公開する。

```bash:Command
# 永続的にDNSサービスを公開
firewall-cmd --permanent --add-service=dns
# 設定をリロードして反映
firewall-cmd --reload
```

# 設定ファイル

## 初期設定ファイル（named.conf）
/etc/named.conf のことを初期設定ファイルと呼ぶ。
namedの基本的な動作を決めるための設定はここに記述する。


## named.rfc1912.zonesファイル
初期設定ファイルでインクルードされている設定ファイル。
RFC1912で定められたDNSサーバとして必要な最小限のDNSレコードを設定するための設定ファイル。
基本的に変更することはない。

## named.root.key
初期設定ファイルでインクルードされている設定ファイル。
rootサーバのDNSSEC鍵情報が記述されている。
これも基本的に変更しない。

# 設定のチェックと設定反映

## 設定のチェック

以下のコマンドを実行することで設定内容が正しいかチェックすることができる。
間違っている設定がある場合は、対象ファイルと行、エラー内容を提示してくれる。

オプション
-z：ゾーンファイルの内容も含めてチェックする。

```bash:Command
named-checkconf -z
```

## 設定反映
設定ファイルを変更した場合はリロード、またはサービス再起動が必要になる。
使用しているパッケージにより若干設定反映のコマンドが異なるので注意。
named-chrootを使用している場合は、chrootのディレクトリに設定ファイル、またはディレクトリをマウントしているため、リロードだけでは反映されず、サービス再起動が必要になることがある（ファイルを直接マウントしていると元ファイルの変更が直に反映されない）。


named-chrootを使用していない場合

```
systemctl reload named.service
```

named-chrootを使用していて/etc/named.confを修正した場合

```
systemctl restart named-chroot.service
```

named-chrootを使用している環境でゾーンファイルを修正した場合

```
systemctl reload named-chroot.service
```

# 外部向けDNSマスターサーバの構築手順

1. listen-onステートメントに問い合わせを受け付けるIPを指定する。
2. allow-queryステートメントで不特定の接続元からの問い合わせを許可するようにanyを指定する。
3. recursionステートメントの再帰問い合わせは、マスタサーバでは不要なのでno設定しておく。
4. zoneステートメントで、正引きと逆引きの設定をそれぞれ追加する。

### 正引きのzoneステートメント

5.  zone の後ろにはドメイン名を記述
6. マスタサーバなので、type を master に設定。
7. file で指定するzoneファイル名はわかりやすく"ドメイン名.db"としておく。
8. allow-update はダイナミックDNSを構築する際に動的にレコードを書き換えることを許容するものなので、ここでは none に設定。
9. allow-transfer はゾーン情報の転送を許可するIPを指定する。
10. notify ではゾーン情報を更新した場合に直ちにスレーブサーバに通知を行い更新するかを設定するもの。特に理由がなければ yes に設定しておく。
  ここで no にした場合はSOAレコードの更新間隔だけ時間を待った上でスレーブが更新されるため、遅延が発生する。
### 逆引きのzoneステートメント

11. 逆引きのzone名、ファイルなどはIPアドレスを後ろのオクテットから順に記載する。サブステートメントは正引きとほぼ同じ。
12. IPv6の逆引きも同様に用意しておく。


```bash:/etc/named.conf
options {
        listen-on port 53 { 127.0.0.1; 
                             <問い合わせを受け付けるインターフェースのIP>; };
        listen-on-v6 port 53 { ::1;
                             <問い合わせを受け付けるインターフェースのIP>; };
        ...
        allow-query     { any; };
        ...
        recursion no;
        ...
        # zoneの名前としてドメイン名を指定
        zone "sample.jp" IN {
            # マスターとして動作させるのでmaster
            type master;
            # zoneファイル名は、"取得したドメイン名.db"とするのが一般的
            file "sample.jp.db";
            # ダイナミックDNSの構築ではないのでsnoneにしておく
            allow-update { none; };
            # ゾーン情報の転送を許可する設定なのでスレーブのIPを許可する
            # スレーブが存在しない場合は none を指定する。
            allow-transfer { <スレーブサーバのIP>; };
            notify yes;
        };
        # IPv4の逆引き
        zone "7.168.192.in-addr.arpa" {
            type master;
            file "7.168.192.in-addr.arpa.db";
            allow-update { none; };
            allow-transfer { <スレーブサーバのIP>; };
            notify yes;
        };
        # IPv6の逆引き
        zone "0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" {
            type master;
            file "0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ipv6.arpha.db";
            allow-update { none; };
            allow-transfer { <スレーブサーバのIP>; };
            notify yes;
        };
};
```

## ゾーンファイルの記述方法

### リソースレコードの書式
リソースレコードは左から順に以下のように指定する。

<リソースの所有者> [TTL] <クラス> <タイプ> <値>

#### リソースの所有者
主にドメイン名、ホスト名が入る。
@を指定した場合はデフォルトのドメイン（$ORIGIN）を指す。
#### TTL
リソースレコードの有効期限（秒）を指定できる（オプション）。
他のサーバが問い合わせ結果をキャッシュした場合、この有効期限の間はキャッシュを使い続ける。
有効期限が切れた後、再度問い合わせを行うといった挙動になる。
キャッシュが使用されている間（有効期限の間）はレコードの変更が反映されないので注意。
#### クラス
インターネットではINが使われる。
#### 値
IPアドレスやドメイン名などが入る。

#### 記述例
```bash:例
@	172800	IN	A	ns1	
```


### ゾーンファイルの記述
ここではドメイン"sample.jp"のゾーンファイルとして例を記述します。

#### ゾーンファイルを記述の際に抑えておくこと

* 初期設定ファイルのzoneステートメントの引数に指定したドメイン名がデフォルトのドメインとして扱われる（$ORIGINに設定される）。
* zoneステートメントの他、ゾーンファイル上に$ORIGINでドメイン名を指定することも出る（$ORIGIN指定が優先される）。
* リソースの所有者に@を指定した場合は$ORIGINを意味する。
* リソースレコードの先頭の所有者を省略した場合は、前の行の所有者を引き継ぐことを意味する。
* ドメイン名やホスト名の末尾に.（ドット）を付けた場合はそのまま記載したドメイン、ホスト名を意味する。
* 逆に末尾に.（ドット）が付かない場合は、$ORIGINのドメインが連結されて解釈されるので注意（例えば、ホスト名が"host"で$ORIGINが"sample.jp"なら"host.sample.jp"として扱われる）。
* CNAMEを使わずに複数のホストのAリソースレコードに同じIPアドレスを割り当てないこと。これをやるとDNSの妥当性が検証された場合に、逆引きが正しく動作しないため、検証エラーとなる。

#### 正引きのマスターファイル

```bash:/var/named/sample.jp.db
; コメントの記述は先頭にセミコロンを置く
$TTL	172800 ; この指定では48時間/172800秒が生存時間

; この@はnamed.confのzoneステートメントの引数である"sample.jp"を意味する
; SOAレコードの値には、ホスト名（自分自信）、管理者メールアドレスを指定する
; メールアドレスは以下のroot.ns1.sample.jpのように、ユーザ、ドメインを@で区切らず、.で区切ること
@		IN	SOA		ns1.sample.jp.	root.ns1.sample.jp. (
					2016010101 ; シリアルナンバー - 設定を変更した場合はこの値を更新してより大きい値にする必要がある（作業日+その日の作業回数２桁で記述すればよい）。
					3600       ; リフレッシュ間隔 - スレーブが同期する間隔（秒）を指定する。スレーブはこの値を取得して指定時間間隔で同期を取りに来る。
					300        ; 再試行間隔 - リフレッシュ間隔での同期に失敗した場合の再試行間隔（秒）。
					360000     ; 情報破棄時間 - リフレッシュ不可な場合にゾーン情報を無効にするまでの時間（秒）。前回のリフレッシュからこの時間が経過するとスレーブのゾーン情報は無効となる。
					86400      ; 情報有効時間 - 各リソースレコードに設定できるTTL値の最小値を指定。この値より小さいTTLはこの値に強制される。
					)
			IN	NS		ns1.sample.jp.	 ; NSはネームサーバの指定を意味する。所有者を省略しているので上の行の@を引き継ぎ、"sample.jp"ゾーンのネームサーバを意味する
			IN	NS		ns2.sample.jp.	 ; ２台目のネームサーバを定義
			IN	MX		10 mail1.sample.jp.	; sample.jpゾーンのメールサーバ（SMTPサーバ）を指定。ドメインの前の数値は優先順位を表し、小さい数値のMXに優先して送信される。
			IN	MX		20 mail2.sample.jp.	; ２台目のメールサーバ
ns1			IN	A		192.168.7.2	; ホスト名に対するIPアドレスを定義（IPv4）する
			IN	AAAA	2001:db8::2	; ホスト名に対するIPアドレスを定義（IPv6）する
ns2			IN	A		192.168.7.3
			IN	AAAA	2001:db8::3
pc1			IN	A		192.168.7.101
			IN	AAAA	2001:db8::101
mercury		IN	A		<IPv4>			; 以後値は省略
			IN	AAAA	<IPv6>
venus		IN	A		<IPv4>
			IN	AAAA	<IPv6>
mars		IN	A		<IPv4>
			IN	AAAA	<IPv6>
mx1			IN	CNAME	mercury		; mercury.sample.jpの別名として、mx1.sample.jpを定義
mx2			IN	CNAME	venus		; venus.sample.jpの別名として、mx2.sample.jpを定義
www			IN	CNAME	mars		; mars.sample.jpの別名として、www.sample.jpを定義
```

時間の指定には秒数の他、以下の指定方法がある。

|単位|意味|表記|
|:--|:--|:--|
|M|分|1分 - "1M"|
|H|時|1時間 - "1H"|
|D|日|1日 - "1D"|
|W|週|1週 - "1W"|
※組みわせて、"1D12H"などの表記も可能

#### IPv4の逆引きのマスターファイル
正引きと同じ意味合いの場所は説明を割愛する。

```bash:/var/named/7.168.192.in-addr.arpa.db
$TTL	172800

@		IN	SOA		ns1.sample.jp.	root.ns1.sample.jp. (
					2016010101 ; シリアルナンバー
					3600       ; リフレッシュ間隔
					300        ; 再試行間隔		
					360000     ; 情報破棄時間
					86400      ; 情報有効時間
					)
			IN	NS		ns1.sample.jp.	 ; ネームサーバ１台目
			IN	NS		ns2.sample.jp.	 ; ネームサーバ２台目
			IN	PTR		sample.jp.		; "192.168.7.0"のゾーンがsample.jp.であることを定義。
			IN	A		255.255.255.0	; "192.168.7.0"のサブネットマスクを定義。
2			IN	PTR		ns1.sample.jp. ; IPv4アドレスとns1.sample.jpのマッピング
3			IN	PTR		ns2.sample.jp.	
...
```

#### IPv6の逆引きのマスターファイル

```bash:/var/names/0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.db
$TTL	172800
@			IN	SOA	ns1.sample.jp. root.sample.jp. (
										201601010
										3600
										300
										360000
										86400
									)
									IN	NS	ns1.sample.jp.	
									IN	NS	ns2.sample.jp.
									IN	PTR	sample.jp.
2.0.0.0.0.0.0.0.0.0.0.0				IN	PTR	ns1.sample.jp.	; IPv6アドレスとns1.sample.jpのマッピング
...							
```