Dockerで権威DNSサーバーのPowerDNS Authoritative Server+PowerDNS-Adminを動かしてみた 2022年版

# 前書き
2018年に投稿した内容では古くてそのままでは動作しなくなっているので2022年版として改めて検証も兼ねてメモを残しておきます。

https://qiita.com/ohhara_shiojiri/items/ea881867a5421528c6a1

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

# 動作環境

## ホスト側

- OS:Ubuntu Server 22.04.1LTS
- Docker CE version 20.10.18
- docker compose version v2.10.2

# Docker環境の準備

以下のページにて紹介していますので参考にしてみて下さい。

- [Linuxサーバー環境のDockerインストールメモ - Qiita ](https://qiita.com/ohhara_shiojiri/items/486a54ad895d6bb3144e)

## Dockerコンテナ環境で動かす理由

Dockerコンテナの特徴と利点が有用であれば使ってみるのも有りだと思います。

- ホストOS側とコンテナ分離する事でホストOS側への影響が少ない
- 構築したコンテナ環境を他の別環境に移設やバックアップがしやすい
- Kubernetesなどのクラウド・コンテナオーケストレーション環境に展開出来る

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

https://www.powerdns.com/

# ローカルホスト側のリゾルバ設定

ubuntuの場合、systemdでDNSの53番ポートがサービス起動していて、他のDNSサービスとは競合してしまうので、名前解決のローカルリゾルバは動作させたまま53番ポートのListenを無効化させます。

```:/etc/systemd/resolved.conf
[Resolve]
DNSStubListener=no
```

なおnameserverの指定はnetplanの記述に自動修正されます。

```
$ cd /etc
$ sudo ln -sf ../run/systemd/resolve/resolv.conf resolv.conf
$ sudo systemctl restart systemd-resolved
```

## サービスポート変換

クラウドのインスタンス環境などの場合はローカルリゾルバを変更せずに、Dockerコンテナ側の1053番ポートなどの別のサーピスポート番号で動作しているので、クラウド側のセキュリティグループ設定でグルーバルIPアドレス側の53番ポートとNAPT変換させます。

```:pdns/compose.yaml
ports:
  - 1053:53/tcp
  - 1053:53/udp
```

# PowerDNS(pdns)

PowerDNSの公式Dockerが提供されているので利用します。
このPowerDNS(pdns)コンテナには権威DNS(Auth)、フルリゾルバ(Recursor)、ロードバランサ(dnsdist)の３つのサービスが提供されています。
今回は権威DNS(Auth)だけ利用します。

https://github.com/PowerDNS/pdns/blob/master/Docker-README.md

## docker compose設定

適当なディレクトリを作成して「docker compose」設定ファイルを作成します。

```
$ mkdir -p pdns
$ cd pdns
```

```:pdns/compose.yaml
services:
  auth:
    image: powerdns/pdns-auth-master:latest
    container_name: pdns_auth
    environment:
      - PDNS_AUTH_API_KEY
    ports:
      - "53:53"
      - "53:53/udp"
    volumes:
      - powerdns:/var/lib/powerdns
      - ./pdns.d/pdns.conf:/etc/powerdns/pdns.d/pdns.conf

volumes:
  powerdns:
    driver: local
```

Docker Volumeで永続化している「powerdns」はsqlite3のデータベースファイルが保存されるディレクトリなのでバックアップも考慮しておきましょう。

## PowerDNS設定ファイルの作成

各種設定ファイル類はカレントディレクトリ以下に配置してPowerDNS(pdns)コンテナ側にマウントさせています。次に各設定ファイルを作成します。

### 権威DNS(Auth)

適当なディレクトリを作成して設定ファイル「pdns.conf」を作成します。

```
$ mkdir -p pdns.d
```

```:pdns.d/pdns.conf
local-address=0.0.0.0,::
launch=gsqlite3
gsqlite3-dnssec
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
include-dir=/etc/powerdns/pdns.d
primary=no # プライマリの場合=yes
secondary=no # セカンダリの場合=yes
allow-axfr-ips=1.2.3.4 # zoneの転送許可IPアドレス番号
version-string=powerdns
```

権威DNSサーバーは１つのprimaryサーバーと複数のsecondaryサーバーで構成されますが、PowerDNSではこれを明確に設定します。
ドメインのZone転送はsecondaryサーバー側に限定してZone情報が他に漏洩しないようにZone転送許可するIPアドレス番号を記述します。
バージョン表示の応答も詳細を隠しておきます。


### 環境設定

各APIのkeyを設定します。

```:pdns/.env
PDNS_AUTH_API_KEY=[Auth APIのkey文字列]
```

# PowerDNS-Admin

PowerDNS用のフロントエンドのGUIツールでは活発に開発されているのがPowerDNS-Adminです。

https://github.com/ngoduykhanh/PowerDNS-Admin

各種ユーザー認証にも対応していて複数ドメインとユーザー管理が出来るのが特徴です。画面表示はpoweradminと違って日本語には対応していませんが、特に難しい事は無く使えると思います。

## docker compose設定

```:pdns/compose.yml
services:
  admin:
    image: ngoduykhanh/powerdns-admin:latest
    container_name: pdns_admin
    ports:
      - "80:80"
    logging:
      driver: json-file
      options:
        max-size: 50m
    environment:
      - GUNICORN_TIMEOUT=60
      - GUNICORN_WORKERS=2
      - GUNICORN_LOGLEVEL=DEBUG
      - OFFLINE_MODE=True # True for offline, False for external resources
    volumes:
      - powerdnsadmin-data:/data

volumes:
  powerdnsadmin-data:
    driver: local
```

## PowerDNS(pdns_auth)+PowerDNS-Admin(pdns_admin)コンテナ起動

以上で必要な設定ファイルが用意出来たので、docker composeコマンドでコンテナを起動させます。

```
$ docker compose up -d
$ docker compose ps
NAME                COMMAND                  SERVICE             STATUS              PORTS
pdns_admin          "entrypoint.sh gunic…"   admin               running (healthy)   0.0.0.0:80->80/tcp
pdns_auth           "/usr/bin/tini -- /u…"   auth                running             0.0.0.0:53->53/tcp, 0.0.0.0:53->53/udp, 8081/tcp
```

## バージョンの確認方法

設定ファイルでバージョン表示を隠匿した場合はDNSの応答では表示されません。
Dockerコンテナからコマンドを実行しましょう。

```
$ docker exec pdns_auth /usr/local/sbin/pdns_server --version
Sep 26 08:17:06 PowerDNS Authoritative Server 4.8.0-alpha0.272.master.ga31f39c20 (C) 2001-2022 PowerDNS.COM BV
```

### Web設定画面

PowerDNS-AdminのGUI画面はブラウザで指定すれば表示されます。最初はアカウント作成のログイン画面になります。

![操作画面](https://user-images.githubusercontent.com/6447444/44068603-0d2d81f6-9fa5-11e8-83af-14e2ad79e370.png)