PowerDNS と Knot DNS で DNS 権威サーバーを組んでみた話

# 【追記: 2015/12/18】まずは
DNS Advent Calendar 2015 の18日目の記事です。
こういった Advent Calendar には初めて参加するので誤字脱字、いろんな箇所で至らない点がありますが、コメントでのご指摘など頂ければと思います。
もちろんリファレンスなどで書いてあることも含まれていますので「こんなおかしなことしてるんだな」と思いながら見ていただければと思います。

# 事の始まり
* 自分「ここ最近 [VALUE-DOMAIN](http://www.value-domain.com/ "VALUE-DOMAIN バリュードメイン") で障害[^障害]やらなんやらで騒がしいなぁと思い [InterLink](http://www.interlink.or.jp/ "無料体験・即日ID発行のプロバイダ｜インターリンク") の固定 IP もあるし思い切って自前で DNS のサービスを提供するかー」
* 自分「PowerDNS と NSD を用いたページ[^サンプル]はあれど PowerDNS と Knot DNS を用いたページはないし、NSD を Slave で使うとシリアルの値を比較しない[^ダメだった話]というのを(検討当時)見たのでじゃあ Knot DNS でやってみよう」

# ネットワーク構成
<pre>
DB - NS Master - NS Slave -|- The Internet
</pre>
# ソフト構成
<dl>
  <dt>DB</dt>
  <dd>FreeBSD(10.2-RELEASE amd64)</dd>
  <dd>MySQL(5.6.26)</dd>
</dl>
<dl>
  <dt>NS Master</dt>
  <dd>Raspbian(8.0 Jessie)</dd>
  <dd>PowerDNS Authoritative Server(3.4.1)</dd>
</dl>
<dl>
  <dt>NS Slave</dt>
  <dd>FreeBSD(10.1-RELEASE amd64)</dd>
  <dd>Knot DNS(2.0.1)</dd>
  <dd>PF(BB ルーター(NAT 箱)兼用)</dd>
</dl>

# Install
基本的に FreeBSD ports や aptitude でインストールしたため割愛。[^インストール]

# Config
とりあえず関係のある部分だけ。基本的にはリファレンスを見て自分の環境に合わせて書き換えてます(がもしかしたら間違いもあるかもしれません【追記】2015/11/13 20:12)。なお NS Slave は BB ルーターを兼用していて Unbound をインストールしているため PF や ipfw などでポートフォワードしてあげる必要があります。

```bash:pdns.conf
allow-axfr-ips=127.0.0.0/8,172.16.0.0/12
allow-dnsupdate-from=127.0.0.0/8

daemon=yes

master=yes

launch+=gmysql

gmysql-host=<DB_IP>
gmysql-port=
gmysql-dbname=<DB_TABLE>
gmysql-user=<DB_USER>
gmysql-password=<DB_PASSWD>
gmysql-dnssec=yes
```
```bash:knot.conf
server:
    listen: <NS_SLAVE_IP>@10053
    listen: 127.0.0.1@10053

log:
  - target: syslog
    any: debug
    server: info
    zone: info

remote:
  - id: master
    address: <NS_MASTER_IP>@53

acl:
  - id: acl_master
    address: <NS_MASTER_IP>
    action: notify

  - id: lan
    address: 172.16.0.0/12
    action: [transfer, notify]

template:
  - id: default
    storage: "/var/db/knot"

zone:
  - domain: <domain>
    master: master
    acl: [acl_master, lan]
```
```bash:pf.conf
# macros
int_if = "re2"
ext_ifv4 = "ng0"

rdr on $ext_ifv4 proto tcp from any to $ext_ifv4 port 53 -> <NS_SLAVE_IP> port 10053
rdr on $ext_ifv4 proto udp from any to $ext_ifv4 port 53 -> <NS_SLAVE_IP> port 10053
```

# Check
```bash:console
$ drill @<NS_MASTER_IP> <domain>
$ drill @<NS_SLAVE_IP> -p 10053 <domain>
```
権威サーバーで名前が引けていればひとまず OK です。

# Tricky Config
ちなみに自分の場合、VPS を使ってセカンダリ DNS を立てたりせず無料のセカンダリ DNS サービスを使っていることもあって pdns.conf と knot.conf を以下のように書き換えています。

```bash:pdns.conf
allow-axfr-ips=127.0.0.0/8,172.16.0.0/12,<2ndDNS_SRV_IP>/32
allow-dnsupdate-from=127.0.0.0/8

daemon=yes

master=yes

launch+=gmysql

gmysql-host=<DB_IP>
gmysql-port=
gmysql-dbname=<DB_TABLE>
gmysql-user=<DB_USER>
gmysql-password=<DB_PASSWD>
gmysql-dnssec=yes
```
```bash:knot.conf
server:
    listen: <NS_SLAVE_IP>@10053
    listen: 127.0.0.1@10053

log:
  - target: syslog
    any: debug
    server: info
    zone: info

remote:
  - id: master
    address: <NS_MASTER_IP>@53

acl:
  - id: acl_master
    address: <NS_MASTER_IP>
    action: notify

  - id: lan
    address: 172.16.0.0/12
    action: [transfer, notify]

  - id: <2ndDNS_SRV_NAME>
    address: [<2ndDNS_SRV_IP>]
    action: [transfer, notify]

template:
  - id: default
    storage: "/var/db/knot"

zone:
  - domain: <domain>
    master: master
    acl: [acl_master, lan, <2ndDNS_SRV_NAME>]
```

# LINK
* リファレンス
 * [PowerDNS](https://doc.powerdns.com/md/)
 * [Knot DNS](https://www.knot-dns.cz/docs/2.0/html/)
* 出会い
 * [【ぷろじぇくと ぞうさん】　～E-Bananaサーバ 構築日記～ 第61日目：【障害復旧対応】花子救出大作戦 with Mumumu](http://dokuosan.net/zousan/nikki61.html "PowerDNS との出会い")
 * [Knot DNSを使ってみた -権威DNSサーバでのDDoS対策おまけつき](http://dnsops.jp/event/20140627/20140627-dns-summer-knotdns-mikit-3.pdf "Knot DNS との出会い")

# 注釈
[^障害]: [VALUE DOMAINのネームサーバーに障害、通常の50倍程度の攻撃で応答困難に](http://internet.watch.impress.co.jp/docs/news/20141222_681496.html "VALUE DOMAINのネームサーバーに障害、通常の50倍程度の攻撃で応答困難に")
[^サンプル]: [PowerDNS + NSD で DNS を構築する : あかぎメモ](http://blog.akagi.jp/archives/4072.html "PowerDNS + NSD で DNS を構築する : あかぎメモ")
[^ダメだった話]: [slave な NSD は refresh のとき serial を見てくれない : あかぎメモ](http://blog.akagi.jp/archives/4152.html "slave な NSD は refresh のとき serial を見てくれない : あかぎメモ")
[^インストール]: 自分の場合は ports で Knot DNS をインストールする時にオプションを全選択してインストールしました。