DNSサーバをPowerDNS(Docker)で構築する

# 概要 
仮想マシンでいろいろサーバ立ててると、IPで接続がめんどくさい。
特にSSL/TLS証明書作るとなおさら。
そのため独自にDNSサーバ(PowerDNS)を立てよう、せっかくなのでDockerでというのが今回の流れ。

:::note warn
おしらせ
Docker HubのPowerDNS公式のレポジトリから、arm版が消えているので現在そのままでは使えません。
非公式のレポジトリのコンテナを使うか、GitHubのソースからbuildするかになると思います。
あと、SQLite3に初期データ流し込む処理忘れてますねこれ
（2022/12/31追記）
:::

# イメージ図とか
![202202102019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214012/63018b41-c4e5-e159-7db3-24402f63bd38.png)


|名称|備考|
|:--|:--|
|OS| ubuntu 20.04 LTS |
|IP| 192.168.10.105 |

●●.lan.local　の問い合わせのみ自分とこで解決して、他のドメインは外部のDNSサーバから拾ってくるイメージ。
PowerDNSの場合、権威サーバとリゾルバサーバの役割がきっちり分けられているのでそれぞれの設定をする。

~~・・・.localは使わない方がいいらしいけど、そのうち考えます。~~


# 設定ファイル等の作成
## 前準備
先人たちは、個別にディレクトリ分けてましたが、一緒に混ぜちゃいます。
構成的には、/home/user0/pdns 内にconfディレクトリを作る。

```  
mkdir -p ~/pdns/conf 
cd ~/pdns/conf
```

## 権威サーバのconfファイル
pdns.confを作ります。
DNSを管理するのはsqlite3でやります。

``` pdns.conf 
api=yes
webserver=yes
include-dir=/etc/powerdns/pdns.d
launch=gsqlite3 
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
local-port=53
security-poll-suffix=
setgid=pdns
setuid=pdns
```

## リゾルバサーバのconfファイル
recursor.confを作ります。
lan.localとexample.com（ゾーン）の問い合わせが来たら権威DNS（Dockerの内部IP指定で）に問い合わせを行い、それ以外は1.1.1.1（CloudFlareのDNS）に問い合わせを行う。
念の為アクセス制限もかけておく。

``` recursor.conf
include-dir=/etc/powerdns/recursor.d
forward-zones= lan.local=172.23.0.3 , example.com=172.23.0.3
forward-zones-recurse=.=1.1.1.1
allow-from=192.168.10.0/24,172.23.0.0/16
```

## docker-composeファイルの作成。
一つ上のディレクトリに戻り ``` cd ../ ```、docker-compose.ymlを作成する。
webGUIもついでに書いてしまう

``` yaml:docker-compose.yml
version: '2.0'
services:
  recursor:
    image: powerdns/pdns-recursor-master
    container_name: pdns_recursor
    restart: always
    ports:
      - "53:53"
      - "53:53/udp"
      - "8082:8082"
    volumes:
      - ./conf/recursor.conf:/etc/powerdns/recursor.d/recursor.conf:ro
    networks:
      powerdns:
        ipv4_address: 172.23.0.2

  auth:
    image: powerdns/pdns-auth-master
    container_name: pdns_auth
    restart: always
    environment:
      - PDNS_AUTH_API_KEY: YourAPI #Webで使用するAPIキー。
    ports:
      - "1053:53"
      - "1053:53/udp"
      - "8081:8081"
    volumes:
      - powerdns_auth:/var/lib/powerdns
      - ./conf/pdns.conf:/etc/powerdns/pdns.d/pdns.conf:ro
    networks:
      powerdns:
        ipv4_address: 172.23.0.3

  webapp:
    image: ngoduykhanh/powerdns-admin:latest
    container_name: powerdns_admin
    restart: always
    ports:
      - "9191:80"
    logging:
      driver: json-file
      options:
        max-size: 50m
    environment:
      - GUNICORN_TIMEOUT=60
      - GUNICORN_WORKERS=2
      - GUNICORN_LOGLEVEL=DEBUG
    volumes:
      - powerdns_web:/data
    networks:
      powerdns:
        ipv4_address: 172.23.0.4

volumes:
  powerdns_auth:
    driver: local
  powerdns_web:
    driver: local

networks:
  powerdns:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.23.0.0/16
          gateway: 172.23.0.1

``` 

#dockercomposeの起動
##事前準備
このyamlファイルでdocker-composeを実行すると、ubuntuの場合既に53番ポートが使われているため失敗する。
しかしこのサービスを止めると名前解決ができない（っぽい？）のでイメージが落とせない。先手でイメージを落としてくる

``` docker-compose pull  ```

イメージを落としたら、ubuntuのサービスを止める。

```
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
```

##起動
前章で作成したyamlファイルを使ってdocker-composeで起動する。
``` docker-compose up -d ```

# DNS動作チェック
## 事前準備
権威サーバに直接サンプルデータ( www.example.com )を流し込む。

```
docker exec pdns_auth pdnsutil create-zone example.com ns1.example.com
docker exec pdns_auth pdnsutil add-record example.com. www A 192.168.10.105
```

## 権威サーバの名前解決確認
クライアント端末（または別のサーバ）から次のコマンドを打ち、正しいアドレスが帰ってくるか確認します。
```dig +short www.example.com @192.168.10.105 -p 1053 ```

## リゾルバサーバの名前解決確認（外部）
同じくクライアント端末から次のコマンドを打ち、名前解決できるか確認します。
```dig +short www.yahoo.com @192.168.10.105 ```

## リゾルバサーバの名前解決確認（内部）
同じくクライアント端末から次のコマンドを打ち、名前解決できるか確認します。
```nslookup www.example.com 192.168.10.105 ```

# WebGUIの設定
## アカウントの作成
(サーバIP):9191（今回の場合```192.168.10.105:9191```）にアクセスします。

![202202102220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214012/d0087184-8a76-faad-37ff-fef7cfb70f97.png)

create an accountをクリックし、必要事項を登録する。
そして最初の画面でログインする。

ログインするとエラーが出ているため次の通りに入力し、updateを押す。
![202202102226.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214012/e4f1b291-aea1-35c5-459e-2a27dfea21da.png)

|名称|入力値|
|:--|:--|
|API URL|http://auth:8081|
|API KEY |yamlファイルのPDNS_AUTH_API_KEYで設定した値|

Dashboardを押して1 domainとなっていれば設定完了。

## ドメインの登録
ようやく本題のドメイン登録。
New Domainを押下して、Create New DomainのEnter a value・・・でゾーン（例：「lan.local」）を入力しSubmitを押下する。
Dashboardに戻り該当するゾーンのManageを押下する
![202202102239.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214012/0321800c-0463-31be-d999-69d0192e74c9.png)

Add Recordを押下し、必要項目を記入しSaveを押す。
登録を終えたらApply Changeを押下し確定させる。
![202202102240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214012/bbaf159c-7673-2705-c8f4-9daac26f20cd.png)

以上で終わり。
ufwで制限かけとくとなおよし

#参考文献
[Dockerで権威DNSサーバーのPowerDNS Authoritative Server+PowerDNS-Adminを動かしてみた 2021年版](https://qiita.com/ohhara_shiojiri/items/d5543afc616c0f117157)
[Power DNSで権威サーバを構築する](https://qiita.com/Shakapon/items/cb99384b82bdc15dd660)