検証用にDockerでbindを動かす

Docker上でbindを動かしたかったのでやってみる。

### 実行環境
自分の実行を確認、、、とりあえず動くので今回はこれで（古すぎる）
今回はDockerに関する初期設定は割愛。いい記事たくさんあるので。

```
$ cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
```
```
$ sudo docker version
Client:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-common-1.12.6-16.el7.centos.x86_64
 Go version:      go1.7.4
 Git commit:      3a094bd/1.12.6
 Built:           Fri Apr 14 13:46:13 2017
 OS/Arch:         linux/amd64

Server:
 Version:         1.12.6
 API version:     1.24
 Package version: docker-common-1.12.6-16.el7.centos.x86_64
 Go version:      go1.7.4
 Git commit:      3a094bd/1.12.6
 Built:           Fri Apr 14 13:46:13 2017
 OS/Arch:         linux/amd64
```

### Dockerfileの用意

```text:Dockerfile
FROM centos:7

RUN yum -y update
RUN yum install -y bind bind-chroot bind-utils
RUN groupadd bind
RUN useradd -m bind -g bind -s /sbin/nologin

RUN /usr/sbin/rndc-confgen -a  -t /var/named/chroot -u bind -r /dev/urandom

EXPOSE 53/UDP
EXPOSE 53/TCP

COPY named.conf /var/named/chroot/etc/
COPY sample.com.zone /var/named/chroot/var/named/
COPY localhost.rev /var/named/chroot/var/named/
COPY named.root /var/named/chroot/var/named/
RUN chown -R bind:bind /var/named/chroot/

CMD ["/usr/sbin/named", "-u", "bind", "-t", "/var/named/chroot", "-c", "/etc/named.conf", "-g"]
```

### 解説
・パッケージ
bindはyumに上がっているものを使用。最新バージョンを利用したい場合は自分でビルドすること（bindは脆弱性報告が多いので）
bind-chrootはchroot化するためのパッケージ。入れなくても全然動く。
bind-utilsはdigなどのコマンドのために入れているが、bindを動かすためには不要。

・rndcの鍵生成
bind操作用にrndcを使用するため、`rndc-confgen`コマンドで鍵を生成する。
デフォルトでは`/etc/rndc.key`に生成されるが、-t オプションでchroot化している。

・EXPOSE
DNSはudpとtcpの53を利用するため、EXPOSEで設定する。

・設定ファイルのCOPY
bindの設定に必要な設定ファルを指定。
COPY元のファイルはDockerファイルと同じディレクトリにある状態。
chroot化するため、`/var/named/chroot/`配下を指定する。

・bindの起動
Dockerではsystemctlは使用できない（回避方法はある）ので、`/usr/sbin/named`を直接指定して起動する。
-t はchroot用のパスを指定。

## 配置ファイル
### named.conf
bindの設定ファイル。
今回は権威とキャッシュの両方の機能を動かしている。
なお、globalIPを持っている環境では外部から参照されるリスクがあるため、必ずaclを設定すること。
今回はlocalhostとDockerで割り当てられるprivateIPに絞っている。

```vim:named.conf
logging {
    channel "query-log" {
        file "/var/log/query.log" versions 6 size 1024M;
        severity dynamic;
        print-time yes;
        print-category yes;
    };
    category queries { "query-log"; };
    category lame-servers { null; };
    category resolver { null; };
};

include "/etc/rndc.key";
controls {
    inet 127.0.0.1 allow { 127.0.0.1; } keys { "rndc-key"; };
};

acl "access-list" {
    127.0.0.1;
    172.17.0.0/16;
};

options {
    directory "/var/named/";
    pid-file "/run/named/";
    dump-file "/var/named/named_dump.db";
    statistics-file "/var/named/named.stats.log";

    zone-statistics yes;
    version "";
    masterfile-format text;
    recursive-clients 10000;
    tcp-clients 10000;

    allow-recursion { access-list; };
    allow-query { access-list; };
    allow-query-cache { access-list; };
};

view "internal" {
    recursion yes;

    zone "." {
        type hint;
        file "named.root";
    };

    zone "0.0.127.in-addr.arpa" {
        type master;
        file "localhost.rev";
    };

    zone "sample.com" {
        type master;
        file "sample.com.zone";
    };
};
```

### named.root
rootゾーン情報が書いてあるファイル
named.rootはInterNICで公開されているものを使用
https://www.internic.net/domain/named.root

```
$ wget https://www.internic.net/domain/named.root
```

### localhost.rev
自ホストの逆引きゾーンファイル

```
$TTL    86400
@   IN  SOA localhost.  root.localhost. (
        2020062101  ; Serial
        28800       ; Refresh
        14400       ; Retry
        3600000     ; Expiry
        86400 )     ; Minimum

@   IN  NS  localhost.
1   IN  PTR localhost.
```

### sample.com.zone
テスト用のゾーンファイル。
sample.comについて権威を定義。

```
$TTL 900
@   IN  SOA sample.com. postmaster.sample.com. (
        2020062101      ; Serial Number
        1800            ; Refresh
        900             ; Retry
        1209600         ; expire
        900             ; minimum
        )
@
    IN  NS  sample.com.
    IN  A  127.0.0.1
www IN  A   127.0.0.1
text    IN  TXT "sample.com.zone text"
cname   IN  CNAME   www.sample.com.
```

## Dockerfileのbuild
bindのimageをbuildする。
cacheが残っていて困ったことがあるので、あえて--no-cacheオプションを付けてる。
 
```shell
$ sudo docker build . -t bind --no-cache
```
成功するとコマンドでimageが確認できる。

```shell
$ sudo docker images bind
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
bind                latest              00b75189b7d1        2 hours ago         492.3 MB
```

## Dockerの起動
-p オプションでサーバの53ポートとdocker上の53をバインドする。
udpをバインドする場合は、`53:53/udp`でudpを指定する。

```
$ sudo docker run -it -d -p 53:53 -p 53:53/udp --name bind bind:latest
f269bd4ee38ecd22ae209420a7b1df26099de7da60f2bf675dce69c1e451a61a
```
起動の確認

```
$ sudo docker ps | grep bind
f269bd4ee38e　bind:latest　"/usr/sbin/named -u b"　43 seconds ago　Up 42 seconds　0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp　bind
```

## 動作確認
digはdockerを起動しているサーバから実行。

・定義したsample.comドメイン

```shell

-bash-4.2$ dig @localhost www.sample.com +nostats

; <<>> DiG 9.9.4-RedHat-9.9.4-38.el7_3.3 <<>> @localhost www.sample.com +nostats
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29686
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.sample.com.			IN	A

;; ANSWER SECTION:
www.sample.com.		900	IN	A	127.0.0.1

;; AUTHORITY SECTION:
sample.com.		900	IN	NS	sample.com.

;; ADDITIONAL SECTION:
sample.com.		900	IN	A	127.0.0.1
```

・未定義のドメイン

```shell
$ dig @localhost www.yahoo.co.jp +nostats

; <<>> DiG 9.9.4-RedHat-9.9.4-38.el7_3.3 <<>> @localhost www.yahoo.co.jp +nostats
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13134
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.yahoo.co.jp.		IN	A

;; ANSWER SECTION:
www.yahoo.co.jp.	900	IN	CNAME	edge12.g.yimg.jp.
edge12.g.yimg.jp.	60	IN	A	182.22.25.252

;; AUTHORITY SECTION:
g.yimg.jp.		900	IN	NS	gns02.yahoo.co.jp.
g.yimg.jp.		900	IN	NS	gns12.yahoo.co.jp.

;; ADDITIONAL SECTION:
gns12.yahoo.co.jp.	900	IN	A	124.83.255.100
gns02.yahoo.co.jp.	900	IN	A	118.151.254.148
```

うまく権威とキャッシュの機能がそれぞれ動作している。