Dockerで権威DNSサーバーのPowerDNSを動かす

# 背景
DNSの実装と言えば古くからBINDが使われていますが、昨今では脆弱性が度々発覚してセキュリティ的に運用が難しい状況にあります。
BINDに代わるDNSの実装が他にもあり主要なLinuxディストリビューションでも公式パッケージ化されて最新バージョンにも追随しています。
Dockerでコンテナ化もし易い状況なのでサービス例として記録しておきます。

# 権威DNSサーバー PowerDNS Authoritative Server
コンテンツサーバーとも呼ばれる自組織や他組織のゾーンを管理しているDNSサーバーです。
一般の利用者がドメイン検索で使用するキャッシュDNSサーバーと呼ばれるフルリゾルバーのDNSサーバーが権威DNSサーバーのルートサーバーから順繰りに問い合わせてドメイン検索する仕組みがDNSです。
今回はBINDではなく[PowerDNS Authoritative Server](https://www.powerdns.com/auth.html)を使用します。一部TLDでも採用されています。
ゾーンの管理にMySQLなどのRDBを利用して、WebインターフェースによるGUI操作が出来ます。

https://www.powerdns.com/

# マスターサーバー(プライマリ)
権威DNSサーバーはマスター(プライマリ)とスレーブ(セカンダリ)の2つ以上で構成されます。
マスターはゾーン編集をフロントエンドに出しやすいPowerDNSにして、NSDはスレーブとして運用するのが良いかと思います。
DNSでは多様性も言われてますので、マスターとスレーブで異なる環境と実装を組み合わせましょう。

スレーブ・セカンダリ側でNSDの場合は以下の投稿で紹介しています。

[Dockerで権威DNSサーバーのNSDを動かす](http://qiita.com/ohhara_shiojiri/items/39cb9c3a632676c7b33d)

# Docker環境
ホストOSには、CentOS 7を使用、Docker CEとDocker-composeでコンテナを作成します。
インストール方法は公式ガイドを参照下さい。一例も記録しておきます。

Docker CE インストール
https://docs.docker.com/engine/installation/linux/centos/

````
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum-config-manager --enable docker-ce-edge
$ sudo yum makecache fast
$ sudo yum install -y docker-ce
$ sudo systemctl start docker
$ sudo systemctl enable docker
$ sudo docker run hello-world
````

Docker Compose インストール
https://docs.docker.com/compose/install/

````
$ sudo -i
# curl -L https://github.com/docker/compose/releases/download/1.25.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# exit
$ docker-compose --version
````

# Docker Image
Docker Hubを検索するとPowerDNSのDocker Imageもあります。ただし中にはバージョンの古いものもあるので、PowerDNSの最新バージョンに追随しているDocker Imageを選びましょう。
またバックエンドにはSQLとAPIのどちらを使用するかで構成のバリエーションが変わります。
SQLの場合はRDBの種類にも複数選択があり、Webインターフェースのフロントエンドにも複数の選択があります。
下記のページが参考になります。

[久しぶりにPowerDNSをさわる](http://qiita.com/hondam/items/2f9a9ae0223d40af22f6)

今回はバックエンドにSQLのRDB MySQLとフロントエンドにPoweradminの構成を選択しました。
個人的に慣れているのと、フロントエンドが日本語化されているのが決め手です。
で、色々試して中々思うように動作するDocker Imageが無かった為、GitHubから修正してビルドする事になりました。

https://github.com/obi12341/docker-pdns

# PowerDNSコンテナイメージの作成
GitHubからソースを落としてきます。

````
$ yum install git
$ git clone https://github.com/obi12341/docker-pdns.git
````

日本語に対応する為にロケーションを修正します。

````
$ cd docker-pdns
$ vi Dockerfile
````


```:Dockerfile
RUN locale-gen ja_JP.UTF-8  
ENV LANG ja_JP.UTF-8  
ENV LANGUAGE ja_JP:en  
ENV LC_ALL ja_JP.UTF-8  
```

ビルドしてDocker Imageを作成します。

````
$ docker build -t pdns-ja .
$ docker images
````

# PowerDNSコンテナの作成
適当なディレクトリにDocker-composeファイルを作成します。
サンプルがGitHubから落とした先程のソースファイル群の中にもあります。

https://github.com/obi12341/docker-pdns/blob/master/docker-compose.yml

````
$ mkdir pdns-ja
$ cd pdns-ja
$ vi docker-compose.yml
````

```yml:docker-compose.yml
version: "2"
services:
  pdns:
    image: pdns-ja
    ports:
    - "53:53"
    - "53:53/udp"
    - "8080:80"
    environment:
    - PDNS_ALLOW_AXFR_IPS=127.0.0.1,192.168.254.1
    - PDNS_DISTRIBUTOR_THREADS=3
    - PDNS_CACHE_TTL=20
    - PDNS_RECURSIVE_CACHE_TTL=10
    - DB_ENV_MYSQL_ROOT_PASSWORD=aPYsB84zdNZNmn64sjy
  db:
    image: mysql
    environment:
    - MYSQL_ROOT_PASSWORD=aPYsB84zdNZNmn64sjy
    volumes:
    - ./mysql_conf:/etc/mysql/conf.d
    - ./mysql_data:/var/lib/mysql
```

サンプルから変更する箇所は、Docker Imageの指定が先程ビルドしたものに変更。
スレーブゾーン転送先のIPアドレスを変更。
MySQLのパスワードも適当に変更しておきます。
ボリュームの場所はホスト側の適当な所にします。
設定ファイルをコンテナの外側に配置して可用性を図ります。
これでコンテナを入れ替えても設定ファイルやゾーンのデータベースファイルが再利用出来ます。
MySQLの設定ファイルを作成します。

````
$ mkdir mysql_conf
$ cd mysql_conf
$ vi custom.cnf
````

```cnf:custom.cnf
[mysqld]
character-set-server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION
```

標準ではSTRICTモードでNULL値が使用出来ない。NULL値を許容する設定に変更する。
Poweradminでゾーンテーブルを追加した時のエラー対策。

#PowerDNSコンテナの起動と操作
それでは、Docker-composeでPowerDNSのコンテナを起動させてみます。

````
$ cd ..
$ docker-compose up -d
````

エラーが表示されなければ正常に起動しているはずです。
構成ファイルを変更した場合、restartでは再ビルドされないので、コマンドは「docker-compose up -d」にて再実行します。

フロントエンドはWebインターフェースなので、8080番ポートを指定すればPoweradminのログイン画面が表示されます。

http://127.0.0.1:8080

DNSのツールをインストールして動作確認してみましょう。

````
$ sudo yum -y install bind-utils
$ dig @localhost chaos version.bind txt
````

DNSはTCP/53 UDP/53を使用しますので、ファイヤーウォールを適切に設定しましょう。
ただし権威DNSサーバーは外部公開する必要がある為、フルリゾルバーの様に制限しないように。
また、ubuntuなどでローカルのdnsmasqとかに競合して起動しない場合もあります。