PowerDNS でゾーン転送をしてみた with TSIG

プライマリサーバ: `192.168.182.10`は以下の手順で構築されたと仮定します。

https://qiita.com/ahra_/items/77155e008869b72309e6

セカンダリサーバー: `192.168.182.11`の環境は以下の通りです。
Rocky Linux 9.5
PostgreSQL 16.8
PowerDNS 権威サーバー 4.9.5
SELinux 有効

:::note warn
PowerDNS 本体は IXFR に対応していません。
本体が送出する AXFR を IXFR に変換してセカンダリサーバーに送る [ixfrdist](https://doc.powerdns.com/authoritative/manpages/ixfrdist.1.html) は TSIG に対応していません。
:::
:::note info
PowerDNS では外部 DB を用いるため、AXFR 以外に DB のレプリケーション機能を使った同期も可能です。
:::
## プライマリサーバーの設定
以下を追加します。
```/etc/pdns/pdns.conf
primary=yes
```
pdns を再起動します。
```
# systemctl restart pdns
```
セカンダリサーバーの NS レコード、A レコード/PTR レコードを追加します。
PowerDNS では`pdns.conf` の `only-notify` や `also-notify` に何も指定していない場合、ゾーンの NS レコードに指定されているサーバーに対して notify を送出するようになっています。
![スクリーンショット 2025-05-01 163815.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/db9a9745-1865-4943-ab4b-4824e3e99606.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/8fbf3a8d-3915-44b8-a9bd-0c08b67930ab.png)
TSIG 鍵を生成し、各ゾーンでの使用を強制させます。
これにより、TSIG 鍵を持つサーバーからの AXFR 要求が許可されます。（特定の IP アドレスとの AND は現時点では実行できないようです）
なお、生成した TSIG 鍵はセカンダリサーバーにインポートさせる必要があるので、メモしておきましょう。
（`pdnsutil generate-tsig-key` コマンドの結果の `Create new TSIG key ddns hmac-sha512 <この文字列>` が TSIG 鍵です）
```
# pdnsutil generate-tsig-key axfr_notify hmac-sha512
# pdnsutil activate-tsig-key example.com. axfr_notify primary
# pdnsutil activate-tsig-key 182.168.192.in-addr.arpa. axfr_notify primary
```
## セカンダリサーバーの設定
PowerDNS のみ構築します。
構築手順はプライマリサーバーと同一です。
定義ファイルには以下を使用します。
```/etc/pdns/pdns.conf
version-string=anonymous

allow-notify-from=192.168.182.10
secondary=yes
allow-unsigned-notify=no

daemon=no
guardian=no

launch=gpgsql
gpgsql-host=127.0.0.1
gpgsql-port=5432
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=<パスワード>

setgid=pdns
setuid=pdns

loglevel=6
log-dns-details=yes
```
構築後以下のコマンドを実行し、空のセカンダリゾーンの作成、TSIG 鍵のインポート、TSIG 鍵利用の有効化、AXFR のリクエスト先の指定を行います。
```
# pdnsutil create-secondary-zone example.com. 192.168.182.10
# pdnsutil create-secondary-zone 182.168.192.in-addr.arpa. 192.168.182.10
# pdnsutil import-tsig-key axfr_notify hmac-sha512 <TSIG 鍵>
# pdnsutil activate-tsig-key example.com. axfr_notify secondary
# pdnsutil activate-tsig-key 182.168.192.in-addr.arpa. axfr_notify secondary
# pdnsutil set-meta example.com. AXFR-SOURCE 192.168.182.11
# pdnsutil set-meta 182.168.192.in-addr.arpa. AXFR-SOURCE 192.168.182.11
```
## 確認
セカンダリサーバーを起動して AXFR 要求の契機とします。
AXFR によってゾーン転送が実行されることが確認できます。
```
May 02 09:08:45 Rocky pdns_server[2938]: Received serial number updates for 2 zones
May 02 09:08:45 Rocky pdns_server[2938]: Domain 'example.com' is empty, primary 192.168.182.10 serial 2025050201
May 02 09:08:45 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', initiating transfer
May 02 09:08:45 Rocky pdns_server[2938]: Domain '182.168.192.in-addr.arpa' is empty, primary 192.168.182.10 serial 2025050201
May 02 09:08:45 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', initiating transfer
May 02 09:08:45 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', starting AXFR
May 02 09:08:45 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', starting AXFR
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone '182.168.192.in-addr.arpa', primary '192.168.182.10', retrieval started
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone 'example.com', primary '192.168.182.10', retrieval started
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', retrieval finished
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', retrieval finished
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', storage transaction started
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', storage transaction started
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', zone committed with serial 2025050201
May 02 09:08:45 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', zone committed with serial 2025050201
```
プライマリサーバー同様の応答が返ってきます。
```
Resolve-DnsName dns1.example.com. -server 192.168.182.11

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
dns1.example.com                               A      86400 Answer     192.168.182.10


Resolve-DnsName example.com. -server 192.168.182.11

Name                        Type TTL   Section    PrimaryServer               NameAdministrator           SerialNumber
----                        ---- ---   -------    -------------               -----------------           ------------
example.com                 SOA  86400 Authority  dns1.example.com            hostmaster.example.com      2025050201


Resolve-DnsName example.com. -server 192.168.182.11 -type NS

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
example.com                    NS     86400 Answer     dns2.example.com
example.com                    NS     86400 Answer     dns1.example.com

Name       : dns2.example.com
QueryType  : A
TTL        : 86400
Section    : Additional
IP4Address : 192.168.182.11


Name       : dns1.example.com
QueryType  : A
TTL        : 86400
Section    : Additional
IP4Address : 192.168.182.10


Resolve-DnsName 192.168.182.10 -server 192.168.182.11

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
10.182.168.192.in-addr.arpa    PTR    86400 Answer     dns1.example.com
```
## ACL、TSIG の確認
セカンダリサーバーから TSIG 鍵無しの AXFR 要求を送ると失敗しますが、
```
# dig example.com. @192.168.182.10 axfr

; <<>> DiG 9.16.23-RH <<>> example.com. @192.168.182.10 axfr
;; global options: +cmd
; Transfer failed.
```
TSIG 鍵を付与すればゾーンが転送されます。
```
# dig example.com. -y hmac-sha512:axfr_notify:<TSIG 鍵> @192.168.182.10 axfr

; <<>> DiG 9.16.23-RH <<>> example.com. -y hmac-sha512:axfr_notify:<TSIG 鍵> @192.168.182.10 axfr
;; global options: +cmd
example.com.            86400   IN      SOA     dns1.example.com. hostmaster.example.com. 2025050201 28800 7200 604800 86400
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145230 300 64 x9PD7okW3rxEyEXBzMfAF2KndYVcI8j1WXDBRyjjj0EopQgqZortiH8L rorqOPEhFrTuGn2CgoNxcXnHNCFE9Q== 40371 NOERROR 0
dhcp-mac.example.com.   28800   IN      A       192.168.182.20
dhcp-mac.example.com.   28800   IN      DHCID   <DHCID>
dhcp-test.example.com.  28800   IN      A       192.168.182.16
dhcp-test.example.com.  28800   IN      DHCID   <DHCID>
dns-r.example.com.      86400   IN      A       192.168.182.12
dns1.example.com.       86400   IN      A       192.168.182.10
dns2.example.com.       86400   IN      A       192.168.182.11
example.com.            86400   IN      NS      dns1.example.com.
example.com.            86400   IN      NS      dns2.example.com.
test.example.com.       3600    IN      A       192.168.182.21
test2.example.com.      3600    IN      A       192.168.182.22
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145230 300 64 LB9MvyxgV8KXhK7BmRPKkHztIFJoKnZmxkNl7lE/odn5DTFYYaytc0xn YHdBmIE8Q6l21neC3I+bgjmmqbw9Sw== 40371 NOERROR 0
example.com.            86400   IN      SOA     dns1.example.com. hostmaster.example.com. 2025050201 28800 7200 604800 86400
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145230 300 64 jX3a+hUAlN0rcM4I7aCcQaHINVzOeWLJWJMS8Y8XDsjulNzNfyiyx+JL 3uEtHydDvZaa54Bo7AOyhMVVJpp5oQ== 40371 NOERROR 0
;; Query time: 39 msec
;; SERVER: 192.168.182.10#53(192.168.182.10)
;; WHEN: Fri May 02 09:20:31 JST 2025
;; XFR size: 13 records (messages 3, bytes 852)
```
PowerDNS では、要求元 IP アドレスでの制限と TSIG 鍵での制限が両立できないので、TSIG 鍵さえあればセカンダリサーバー以外から AXFR 要求してもゾーン転送が実行されます。（`192.168.207.132`上 Ubuntu から実行の例）
```
# dig example.com. -y hmac-sha512:axfr_notify:<TSIG 鍵> @192.168.182.10 axfr

; <<>> DiG 9.18.30-0ubuntu0.22.04.2-Ubuntu <<>> example.com. -y hmac-sha512:axfr_notify:<TSIG 鍵> @192.168.182.10 axfr
;; global options: +cmd
example.com.            86400   IN      SOA     dns1.example.com. hostmaster.example.com. 2025050201 28800 7200 604800 86400
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145402 300 64 xRtYC5oggGoMmhxNa85wGwGEH2b5sl7pdqc/zoc/TuNlFVUgvRlwsCAF dbjoGlbrhcbqCayhnyQFfTYAUdov8w== 50395 NOERROR 0
dhcp-mac.example.com.   28800   IN      A       192.168.182.20
dhcp-mac.example.com.   28800   IN      DHCID   <DHCID>
dhcp-test.example.com.  28800   IN      A       192.168.182.16
dhcp-test.example.com.  28800   IN      DHCID   <DHCID>
dns-r.example.com.      86400   IN      A       192.168.182.12
dns1.example.com.       86400   IN      A       192.168.182.10
dns2.example.com.       86400   IN      A       192.168.182.11
example.com.            86400   IN      NS      dns1.example.com.
example.com.            86400   IN      NS      dns2.example.com.
test.example.com.       3600    IN      A       192.168.182.21
test2.example.com.      3600    IN      A       192.168.182.22
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145402 300 64 I2+CUe0udG1hNcuQ8KDAzIcTrCUCI+RSZ0WtbPpSOzPTM4zfO9eJ9obm Uzr2Fy0OkN09ATZSdocYfZ9vqgaXCA== 50395 NOERROR 0
example.com.            86400   IN      SOA     dns1.example.com. hostmaster.example.com. 2025050201 28800 7200 604800 86400
axfr_notify.            0       ANY     TSIG    hmac-sha512. 1746145402 300 64 Y7k/l800DRkLAA6ClwyKpz2QDqmwgmm+yy8db7hYjrJ+7sR+2pcxq6jU Fv8tq0hzCv9aqgyD6J0XzCWgCnTYRg== 50395 NOERROR 0
;; Query time: 39 msec
;; SERVER: 192.168.182.10#53(192.168.182.10) (TCP)
;; WHEN: Fri May 02 09:23:22 JST 2025
;; XFR size: 13 records (messages 3, bytes 852)
```
## ゾーンを更新してみる(手動)
Poweradmin で A、PTR レコードを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/eb641280-8842-4bf9-b4b1-cffd334e19f5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/9f15e5ec-fc74-471a-99ad-ccc7d7bde24e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/f24ba905-041a-40e9-aab9-6709eec37be2.png)
notify と AXFR によってゾーン転送が実行されています。
```
May 02 09:27:00 Rocky pdns_server[2938]: Received secure NOTIFY for 182.168.192.in-addr.arpa from 192.168.182.10, with TSIG key 'axfr_notify'
May 02 09:27:00 Rocky pdns_server[2938]: Received secure NOTIFY for example.com from 192.168.182.10, with TSIG key 'axfr_notify'
May 02 09:27:00 Rocky pdns_server[2938]: Received NOTIFY for 182.168.192.in-addr.arpa from 192.168.182.10 - queueing check
May 02 09:27:00 Rocky pdns_server[2938]: Received NOTIFY for example.com from 192.168.182.10 - queueing check
May 02 09:27:00 Rocky pdns_server[2938]: Freshness check source (AXFR-SOURCE) for domain '182.168.192.in-addr.arpa' set to 192.168.182.11
May 02 09:27:00 Rocky pdns_server[2938]: 2 secondary domains need checking, 0 queued for AXFR
May 02 09:27:00 Rocky pdns_server[2938]: Received serial number updates for 2 zones
May 02 09:27:00 Rocky pdns_server[2938]: Domain '182.168.192.in-addr.arpa' is stale, primary 192.168.182.10 serial 2025050202, our serial 2025050201
May 02 09:27:00 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', initiating transfer
May 02 09:27:00 Rocky pdns_server[2938]: Domain 'example.com' is stale, primary 192.168.182.10 serial 2025050202, our serial 2025050201
May 02 09:27:00 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', initiating transfer
May 02 09:27:00 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', xfr source set to 192.168.182.11
May 02 09:27:00 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', starting AXFR
May 02 09:27:00 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', starting AXFR
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone '182.168.192.in-addr.arpa', primary '192.168.182.10', retrieval started
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone 'example.com', primary '192.168.182.10', retrieval started
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', retrieval finished
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', storage transaction started
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', retrieval finished
May 02 09:27:00 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', storage transaction started
May 02 09:27:01 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', zone committed with serial 2025050202
May 02 09:27:01 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', zone committed with serial 2025050202
```
追加したレコードも以下の通り解決できます。
シリアルナンバーの増加も確認できます。
```
Resolve-DnsName test3.example.com. -server 192.168.182.11

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
test3.example.com                              A      86400 Answer     192.168.182.23


Resolve-DnsName example.com. -server 192.168.182.11

Name                        Type TTL   Section    PrimaryServer               NameAdministrator           SerialNumber
----                        ---- ---   -------    -------------               -----------------           ------------
example.com                 SOA  86400 Authority  dns1.example.com            hostmaster.example.com      2025050202


Resolve-DnsName 192.168.182.23 -server 192.168.182.11

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
23.182.168.192.in-addr.arpa    PTR    86400 Answer     test3.example.com


Resolve-DnsName 182.168.192.in-addr.arpa. -server 192.168.182.11

Name                        Type TTL   Section    PrimaryServer               NameAdministrator           SerialNumber
----                        ---- ---   -------    -------------               -----------------           ------------
182.168.192.in-addr.arpa    SOA  86400 Authority  dns1.example.com            hostmaster.example.com      2025050202
```
## ゾーンを更新してみる(DDNS)

https://qiita.com/ahra_/items/7d66c2a84b0b132cabd3

上記記事の通りに DDNS を構成すると、DHCP による IP アドレスのリースにより、ゾーンが更新、notify が送出され AXFR によるゾーン転送が発生していることがわかります。
```/var/log/kea/dhcp-ddns.log
2025-05-02 10:42:09.991 INFO  [kea-dhcp-ddns.d2-to-dns] DHCP_DDNS_ADD_SUCCEEDED DHCP_DDNS Request ID <DHCID>: successfully added the DNS mapping addition for this request: Type: 0 (CHG_ADD)
Forward Change: yes
Reverse Change: yes
FQDN: [dhcp-test2.example.com.]
IP Address: [192.168.182.17]
DHCID: [<DHCID>]
Lease Expires On: 20250502094209
Lease Length: 28800
Conflict Resolution Mode: check-with-dhcid
```
```
May 02 10:43:01 Rocky pdns_server[2938]: Received secure NOTIFY for example.com from 192.168.182.10, with TSIG key 'axfr_notify'
May 02 10:43:01 Rocky pdns_server[2938]: Received secure NOTIFY for 182.168.192.in-addr.arpa from 192.168.182.10, with TSIG key 'axfr_notify'
May 02 10:43:01 Rocky pdns_server[2938]: Received NOTIFY for 182.168.192.in-addr.arpa from 192.168.182.10 - queueing check
May 02 10:43:01 Rocky pdns_server[2938]: Received NOTIFY for example.com from 192.168.182.10 - queueing check
May 02 10:43:01 Rocky pdns_server[2938]: Freshness check source (AXFR-SOURCE) for domain '182.168.192.in-addr.arpa' set to 192.168.182.11
May 02 10:43:01 Rocky pdns_server[2938]: 2 secondary domains need checking, 0 queued for AXFR
May 02 10:43:01 Rocky pdns_server[2938]: Received serial number updates for 2 zones
May 02 10:43:01 Rocky pdns_server[2938]: Domain '182.168.192.in-addr.arpa' is stale, primary 192.168.182.10 serial 2025050203, our serial 2025050202
May 02 10:43:01 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', initiating transfer
May 02 10:43:01 Rocky pdns_server[2938]: Domain 'example.com' is stale, primary 192.168.182.10 serial 2025050203, our serial 2025050202
May 02 10:43:01 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', initiating transfer
May 02 10:43:01 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', xfr source set to 192.168.182.11
May 02 10:43:01 Rocky pdns_server[2938]: XFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', starting AXFR
May 02 10:43:01 Rocky pdns_server[2938]: XFR-in zone: 'example.com', primary: '192.168.182.10', starting AXFR
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone '182.168.192.in-addr.arpa', primary '192.168.182.10', retrieval started
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone 'example.com', primary '192.168.182.10', retrieval started
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', retrieval finished
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', retrieval finished
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', storage transaction started
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', storage transaction started
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: 'example.com', primary: '192.168.182.10', zone committed with serial 2025050203
May 02 10:43:01 Rocky pdns_server[2938]: AXFR-in zone: '182.168.192.in-addr.arpa', primary: '192.168.182.10', zone committed with serial 2025050203
```
DDNS により追加されたレコードも以下の通り解決できます。
```
Resolve-DnsName dhcp-test2.example.com. -server 192.168.182.11

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
dhcp-test2.example.com                         A      28800 Answer     192.168.182.17


Resolve-DnsName 192.168.182.17 -server 192.168.182.11

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
17.182.168.192.in-addr.arpa    PTR    28800 Answer     dhcp-test2.example.com
```