Amazon Provided DNS フォワーダーの BIND サーバ構築

# 目的
VPCの構築と、オンプレミス環境との Direct Connect の設定を行ったのち、オンプレ環境での名前解決を AWS 側で行いたい。
オンプレから直接の Amazon Provided DNS （VPC の CIDR .2）の名前解決は2-Hop となり行えないので、VPC 上に BIND を構築し、Foward 設定を行う。オンプレサーバからは構築した BIND-Server を DNS 参照先として設定する。

# 環境
- VPC
    - CIDR : 10.0.0.0/16
    - Subnet : 10.0.0.0/24
    - Amazon Private DNS Server : 10.0.0.2
- DNS-Server
    - Amazon Linux 2 (ami-c2680fa4)
    - 10.0.0.4
-  オンプレミス側
    - 172.16.0.0/12

※本来は複数AZに複数台構築し、DNS 参照先として複数設定することが望ましいが検証として実施するので省略

# 構築
## Bind インストール
```bash:console
$ sudo yum install bind
$ /usr/sbin/named  -v
BIND 9.9.4-RedHat-9.9.4-51.amzn2 (Extended Support Version)
```

## 自動起動設定
```bash:console
$ sudo systemctl enable named
Created symlink from /etc/systemd/system/multi-user.target.wants/named.service to /usr/lib/systemd/system/named.service.
```
```bash:console
$ systemctl list-unit-files | grep named
named-setup-rndc.service                      static  
named.service                                 enabled 
systemd-hostnamed.service                     static  
```

## BIND設定ファイル(named.conf)の更新
```bash:console
$ sudo cp /etc/named.conf /etc/named.conf.bk
$ sudo vi  /etc/named.conf
```

```conf:/etc/named.conf
//// internalnet というACLでオンプレのCIDRを定義
//// 追加
acl "internalnet" {
    172.16.0.0/12;
    127.0.0.1;
};

options {
    /* Listen元IPを制限 */
    /* コメントアウト */
    // listen-on port 53 { 127.0.0.1; };
    // listen-on-v6 port 53 { ::1; };
    listen-on port 53 { internalnet; localhost; };
    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";

    /* 転送のみ許可し、転送先を Amazon Provided DNS Server に変更 */
    /* コメントアウト */
    // allow-query { localhost; };
    /* 追加 */
    allow-transfer { none; };
    allow-query { internalnet; localhost; };
    allow-query-cache { internalnet; localhost; };
    forward only;
    forwarders { 10.0.0.2; };

    /* 
     - 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;

    /* Provided DNS が DNSSsec 非対応のため NO に変更 */
    /* コメントアウト */
    // dnssec-enable yes;
    // dnssec-validation yes;
    // 追加
    dnssec-enable no;
    dnssec-validation no;

    /* Path to ISC DLV key */
    bindkeys-file "/etc/named.iscdlv.key";

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

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

/* ログローテーションをするよう変更 */
/* コメントアウト */
//logging {
//    channel default_debug {
//        file "data/named.run";
//        severity dynamic;
//    };
//};
/* 追加 */
logging {
    channel "default-log" {
        file "data/named.run" versions 5 size 10M;
        severity info;
        print-time yes;
        print-severity yes;
        print-category yes;
    };
    category default { "default-log"; };
    category general { "default-log"; };
    category security { "default-log"; };
    category client { "default-log"; };
    category queries { "default-log"; };
     category unmatched { "null"; };
};

/* ゾーン構築しない */
/* コメントアウト */
// zone "." IN {
//    type hint;
//    file "named.ca";
//};

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

## サービス再起動してログ確認、名前引けること確認
```bash:console
$ sudo systemctl restart named.service
$ dig @localhost qiita.com
...
;; ANSWER SECTION:
qiita.com.              60      IN      A       54.178.162.126
qiita.com.              60      IN      A       54.92.52.111
qiita.com.              60      IN      A       54.95.21.121

;; Query time: 72 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Jan 00 00:00:00 JST 2000
;; MSG SIZE  rcvd: 86

$ dig @10.0.0.4 qiita.com
...
;; ANSWER SECTION:
qiita.com.              32      IN      A       54.178.162.126
qiita.com.              32      IN      A       54.95.21.121
qiita.com.              32      IN      A       54.92.52.111

;; Query time: 0 msec
;; SERVER: 10.0.0.4#53(10.0.0.4)
;; WHEN: Wed Jan 00 00:00:00 JST 2000
;; MSG SIZE  rcvd: 86
```

ちなみにnamedのログは以下

```bash:console@onpre
$ sudo tail /var/named/data/named.run
00-Jan-2000 00:00:00.000 general: notice: running
00-Jan-2000 00:00:00.000 queries: info: client 10.0.0.4#22557 (qiita.com): query: qiita.com IN A + (10.0.0.4)
00-Jan-2000 00:00:00.000 queries: info: client 172.16.0.123#38738 (qiita.com): query: qiita.com IN A + (10.0.0.4)
```

# オンプレ側での確認
## DNSサーバ、ドメイン名の設定(Linuxの場合)

```bash:console@onpre
$ vi /etc/resolv.conf 
; generated by /usr/sbin/dhclient-script
options timeout:2 attempts:5
nameserver 10.0.0.4
```

## 上記で設定した Nameserver でオンプレ側も名前引けること確認
```bash:console
$ dig  qiita.com
...
;; ANSWER SECTION:
qiita.com.              32      IN      A       54.178.162.126
qiita.com.              32      IN      A       54.95.21.121
qiita.com.              32      IN      A       54.92.52.111

;; Query time: 0 msec
;; SERVER: 10.0.0.4#53(10.0.0.4)
;; WHEN: Wed Jan 00 00:00:00 JST 2000
;; MSG SIZE  rcvd: 86
```

## おまけ Cloudwatch Logs Agent で named のログを送信するとかっこいい
```conf:/etc/awslogs/awslogs.conf
[/var/named/data/named.run]
datetime_format = %d-%b-%Y %H:%M:%S
file = /var/named/data/named.run
buffer_duration = 5000
log_stream_name = {instance_id}
initial_position = start_of_file
log_group_name = /var/named/data/named.run
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/130874/2780d643-9e4d-473c-5a4a-feb33dba4ffb.png)

## その他
BIND 9.9.2 で、Linux がクライアントだと問題なく名前解決できるが、Windows がクライアントの場合のみBINDサービスが異常終了するという謎事態が発生、BIND 9.8.2 にダウングレードしたらなんか治った。原因不明。

```text:named.run
08-Mar-2018 19:28:22.038 queries: info: client 172.62.11.7#52061: query: twitter.com IN A + (172.74.11.134)
08-Mar-2018 19:28:22.040 general: critical: mem.c:1323: REQUIRE(ptr != ((void *)0)) failed, back trace
08-Mar-2018 19:28:22.040 general: critical: #0 0x8f233b086f in ??
08-Mar-2018 19:28:22.040 general: critical: #1 0x8f23380b1a in ??
08-Mar-2018 19:28:22.040 general: critical: #2 0x8f23392794 in ??
08-Mar-2018 19:28:22.040 general: critical: #3 0x8f23392eab in ??
08-Mar-2018 19:28:22.040 general: critical: #4 0x8f233b2925 in ??
08-Mar-2018 19:28:22.040 general: critical: #5 0x8f233d5275 in ??
08-Mar-2018 19:28:22.040 general: critical: #6 0x8f233d6878 in ??
08-Mar-2018 19:28:22.040 general: critical: #7 0x8f2339f439 in ??
08-Mar-2018 19:28:22.040 general: critical: #8 0x8f233848ca in ??
08-Mar-2018 19:28:22.040 general: critical: #9 0x8f2338c9a92d in ??
08-Mar-2018 19:28:22.040 general: critical: exiting (due to assertion failure)

```