PowerDNS と isc-kea による DHCP-DDNS を構築してみた with TSIG

## 前提
PowerDNS 権威サーバーならびに isc-kea の構築は以下の環境、手順で行われたと仮定します。

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

https://qiita.com/ahra_/items/4c167c235b52c9869be8

PowerDNS サーバーの IP アドレスが `192.168.182.10`、isc-kea DHCP サーバーが `192.168.182.15` です。
DHCP サーバーから `example.com.` および `182.168.192.in-addr.arpa.` ゾーンの名前解決が可能であることを前提とします。
また、DHCP サーバーと DDNS サーバーは同一のマシンで動作するものとします。
# PowerDNS 権威サーバーの設定
以下を追加し、PowerDNS を再起動します。
```/etc/pdns/pdns.conf
dnsupdate=yes
allow-dnsupdate-from=192.168.182.15/32
```
```
# systemctl restart pdns
```
この状態であれば `192.168.182.15` から `nsupdate` 等での更新ができます。
```
# nsupdate
> update add test.example.com. 3600 A 192.168.182.21
> update add 21.182.168.192.in-addr.arpa. 3600 PTR test.example.com.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/f441966a-a083-4291-b60d-19784427183b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/b12312c9-e814-4129-9c0b-37a844a85411.png)
### TSIG の設定
TSIG 鍵を生成し、各ゾーンにメタデータを追加して TSIG 利用を強制させます。
生成した TSIG 鍵は isc-kea DDNS サーバーの設定の際に使用するので、必ずメモしましょう。
（`pdnsutil generate-tsig-key` コマンドの結果の `Create new TSIG key ddns hmac-sha512 <この文字列>` が TSIG 鍵です）
```
# pdnsutil generate-tsig-key ddns hmac-sha512
# pdnsutil add-meta example.com. TSIG-ALLOW-DNSUPDATE ddns
# pdnsutil add-meta 182.168.192.in-addr.arpa. TSIG-ALLOW-DNSUPDATE ddns
```
これで TSIG 鍵無しでの更新ができなくなりました。
```
# nsupdate
> update add test2.example.com. 3600 A 192.168.182.22
update failed: REFUSED
> update add 22.182.168.192.in-addr.arpa. 3600 PTR test2.example.com.
update failed: REFUSED
```
しかし、このように TSIG 鍵を使えば更新が可能です。
```
# nsupdate -y hmac-sha512:ddns:<TSIG 鍵>
> update add test2.example.com. 3600 A 192.168.182.22
> update add 22.182.168.192.in-addr.arpa. 3600 PTR test2.example.com.
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/57be8e0e-207a-4640-94b5-55110198bf53.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/9b3dd159-c75f-4226-9ef9-55fb6c43ebfa.png)
## isc-kea の設定
以下の通り、`ddns-dhcp` サーバーと DDNS の動作についての定義を追加します。
```diff:/etc/kea/kea-dhcp4.conf
{
"Dhcp4": {

    "interfaces-config": {
        "interfaces": [ "ens192" ] //使用するインターフェイス 環境に合わせて変更する
    },
    
    "lease-database": {            // DB 接続設定
        "type": "mysql",
        "name": "dhcp",
        "host": "127.0.0.1",
        "user": "dhcp",
        "password": "<パスワード>",
        "lfc-interval": 3600
    },
    
    "expired-leases-processing": {     // リース回収の設定
        "reclaim-timer-wait-time": 10,
        "flush-reclaimed-timer-wait-time": 25,
        "hold-reclaimed-time": 3600,
        "max-reclaim-leases": 100,
        "max-reclaim-time": 250,
        "unwarned-reclaim-cycles": 5
    },
    
    "valid-lifetime": 86400,       // リース期間
    "calculate-tee-times": true, // T1 T2 の自動計算を設定

    "option-data": [
        {
            "name": "domain-name-servers",
            "data": "192.168.182.12" // 配布する DNS サーバーのアドレス
        },
        {
            "code": 15, 
            "data": "example.com" // 配布するドメイン名
        }
    ],
    
    "reservations-global": false, // DHCP 予約をグローバルでは行わない設定
    "reservations-in-subnet": true, // DHCP 予約をサブネット内でのみ使用する設定
    "reservations-out-of-pool": true, // DHCP 予約をサブネット内かつプール外でのみ使用する設定
    "host-reservation-identifiers": ["hw-address"], // DHCP 予約を MAC アドレスでのみ使用する設定

+    "dhcp-ddns": {
+        "enable-updates": true, // DDNS 更新を有効にする
+        "server-ip": "127.0.0.1",  // DDNS サーバーの IP
+        "server-port":53001, // DDNS サーバーのポート
+        "sender-ip":"", // DDNS サーバーへの送信時に使用する IP
+        "sender-port":0, // DDNS サーバーへの送信時に使用するポート
+        "max-queue-size":1024, 
+        "ncr-protocol":"UDP",
+        "ncr-format":"JSON"
+    },
    
    "subnet4": [
        {
            "id": 1,
            "subnet": "192.168.182.0/24", // サブネット
            "pools": [ { "pool": "192.168.182.16 - 192.168.182.19" } ], // 開始 - 終了アドレス
            "option-data": [
                {
                    "name": "routers",
                    "data": "192.168.182.1" // 配布する GW のアドレス
                }
            ],
            
            "reservations": [

                {
                    "hw-address": "00:50:56:a8:68:5f", // MAC アドレス
                    "ip-address": "192.168.182.20" // 払い出す IP アドレス
                }

-            ]
+            ],
            
+            "ddns-send-updates": true, // nsupdate を送信する
+            "ddns-override-no-update": false, // クライアントが更新を要求しない場合要求しない
+            "ddns-override-client-update": true, // サーバー側で更新要求を生成する
+            "ddns-replace-client-name": "never", // クライアント側ホスト名を使用する
+            "ddns-generated-prefix": "", // プリフィックスは使用しない
+            "ddns-qualifying-suffix": "example.com", // ホスト名.example.com の形式にする
+            "ddns-update-on-renew": false, // リース更新時には更新しない
+            "ddns-conflict-resolution-mode": "check-with-dhcid", // DHCID 一致時のみ上書きする
+            "hostname-char-set": "", // 無効な文字セット
+            "hostname-char-replacement": "", // 無効な文字セットを置き換える文字列
            
        }
        
    ],
    
    "loggers": [
        {
            "name": "kea-dhcp4",
            "output-options": [
                {
                    "output": "/var/log/kea/dhcp4.log",
                    "pattern": "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c] %m\n",
                     "maxsize": 1048576,
                     "maxver": 8
                }
            ],
            "severity": "INFO",
            "debuglevel": 0
        }
    ]
}
}
```
再起動します。
```
# kea-dhcp4 -t /etc/kea/kea-dhcp4.conf
# systemctl restart kea-dhcp4
```
以下の設定を行います。
```/etc/kea/tsig-key.conf
"tsig-keys": [
    {
        "name": "ddns",
        "algorithm": "HMAC-SHA512",
        "secret": "<TSIG鍵>"
    }
],
```
```/etc/kea/kea-dhcp-ddns.conf
{
"DhcpDdns":
    {
        "ip-address": "127.0.0.1",
        "port": 53001,
        "control-socket": {
        "socket-type": "unix",
        "socket-name": "/tmp/kea-ddns-ctrl-socket"
    },
    <?include "/etc/kea/tsig-key.conf"?>
    "forward-ddns" : {    
        "ddns-domains": [
            {
                "name": "example.com.", // DDNS の対象ゾーン名
                "key-name": "ddns",  // TSIG 鍵名称
                "dns-servers": [    // リクエスト送信先
                    {
                        "ip-address": "192.168.182.10",  
                        "port": 53
                    }
                ]
            }
        ]
   },
    "reverse-ddns": {
        "ddns-domains": [
            {
                "name": "182.168.192.in-addr.arpa.",
                "key-name": "ddns",
                "dns-servers": [
                    {
                        "ip-address": "192.168.182.10",
                        "port": 53
                    }
                ]
            }
        ]
    },
    "loggers": [
        {
            "name": "kea-dhcp-ddns",
            "output-options": [
                {
                    "output": "/var/log/kea/dhcp-ddns.log",
                    "pattern": "%D{%Y-%m-%d %H:%M:%S.%q} %-5p [%c] %m\n",
                    "maxsize": 1048576,
                    "maxver": 8
                }
            ],
            "severity": "INFO",
            "debuglevel": 0
        }
      ]
    }
}
```
TSIG 鍵が意図しないユーザーに確認されないよう、所有者とパーミッションを変更します。
その後、定義ファイルのシンタックスをチェックし、`kea-dhcp-ddns` を起動します。
```
# chown kea:kea /etc/kea/tsig-key.conf
# chmod 600 /etc/kea/tsig-key.conf
# kea-dhcp-ddns -t /etc/kea/kea-dhcp-ddns.conf
# systemctl enable kea-dhcp-ddns
# systemctl start kea-dhcp-ddns
```
## 確認
DHCP によるアドレスのリースが発生すると、リースされた IP アドレスとリース先クライアントのホスト名で A レコードと DHCID レコードが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/50fb22b7-6563-4a78-9c27-4c8984e4aea6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/5568549a-f537-41dc-8efc-548448802081.png)
逆引きゾーンでは PTR、DHCID が作成されます。
![スクリーンショット 2025-05-01 162938.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3900965/321494cf-2105-4c2d-a609-98de40e9871b.png)