bind9でDNSSECの全自動ゾーン署名を使ってみようと思った時のメモ

# はじめに

クラウドやレンタルDNSなどを利用する場合でも署名に関する設定は外部で行わなければならないケースが多いです。その場合、署名に関する仕組みを理解しておいた方が良いと思います。このドキュメントではbindに実装されている自動署名の仕組みをちょっとだけひも解いてみます。

# テスト環境のまとめ

もう自分でコンパイルする元気もないので以下のディストリビューションの環境をそのまま利用しています。bindの9.11はちょっと古いですが、一応長期サポート版なのでそんなに問題にならないのではないかと思います。

<dl>
<dt>OS</dt>
<dd>Debian 10</dd>
<dt>bind</dt>
<dd>9.11+debian patch</dd>
</dl>

検索してもわからないことが多かったので、ソースを読んで処理内容を把握しています。人間のやることなので読み違いあるかもしれません。その辺りを加味して読んでください。

2021年9月の追記
Debian 11がリリースされたので入れ替えました。ソースの再確認はしていないですが、ログをざっと見た感じだと同じと考えて良いようです(iscの人もそんなに大がかりな修正入れないですよね)。Debian 11では以下のようになります。
<dl>
<dt>OS</dt>
<dd>Debian 11</dd>
<dt>bind</dt>
<dd>9.16+debian patch</dd>
</dl>

2023年7月の追記
Debian 12がリリースされたので入れ替えました。やはりソースの再確認はしていないですが、rndc signing -listでキーの認識状況を確認すると、これまでと同じと考えて良さそうです。Debian 12では以下のようになります。
<dl>
<dt>OS</dt>
<dd>Debian 12</dd>
<dt>bind</dt>
<dd>9.18+debian patch</dd>
</dl>

bindのベースバージョンが9.18に上がったので、設定ファイルにdnssec-enableの設定があると起動しなくなります。そこだけはまりました。ちょうど入れ替えタイミングが月末だったのでキーの入れ替えも確認しています。引数の追加などなく2022年2月のスクリプトをそのまま使用できます。

# 最初の署名方法

ゾーンが非署名状態から署名状態に遷移するとき以下のような仕組みで、有効開始日と有効終了日が設定されます。

![最初の署名期間の決定方法](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555574/1021668c-4240-91d9-b33c-d06348e5c051.png "最初の署名期間の決定方法")

この署名期間の決定処理は、sig-signing-signaturesで指定されるノード数がひとまとまりとなります。以下の表に実際に処理を行った場合の有効開始日と終了日、ノード数をまとめました。

| 有効開始日          | 有効終了日          | ノード数 |
|:-------------------:|:-------------------:|---------:|
| 2019/11/29 01:16:34 | 2019/12/29 02:16:34 | 1        |
| 2019/11/29 01:16:35 | 2019/12/12 00:34:00 | 8        |
| 2019/11/29 01:16:35 | 2019/12/18 14:42:34 | 8        |
| 2019/11/29 01:16:35 | 2019/12/20 18:58:31 | 8        |
| 2019/11/29 01:16:35 | 2019/12/22 04:44:55 | 8        |
| 2019/11/29 01:16:35 | 2019/12/23 20:18:34 | 8        |
| 2019/11/29 01:16:35 | 2019/12/28 10:10:10 | 6        |
| 2019/11/29 01:16:35 | 2019/12/29 02:16:35 | 1        |

表の多くのノード数が8となっているのは、sig-signing-signaturesの値がデフォルトの10となっているからです。署名処理時ではシリアルを上げる関係上SOAも一緒に更新されます。残りの2つはこの分です。

sig-signing-signaturesのカウントはゾーン中に定義したノードだけでなく、DNSKEYやNSECなど実行時に動的に追加される分も含めてカウントアップされます。ノード数が8の場合、NSEC分も含むため定義したノードという意味では4ノードが一度に署名されていることになります。

sig-signing-signaturesのカウントがブレークすると10ms後に再度署名期間の決定処理が開始されます。終了日の決定にはランダム要素が含まれるので、sig-signing-signaturesの単位でノードの有効終了日が分散されます。

デフォルトの状態ではvalidityは30日、re-signはvalidityの1/4に設定されます。このためre-signは7日程度となり、ランダムで決められる終了日の範囲は30-7で23日程度となります。デフォルトの状態でvalidityの指定通りに終了日が設定されることを期待しても、期待通りになることはまれだと思われます。唯一の例外はSOAとDNSKEYでこの有効日はre-signの影響を受けず、validityの値がそのまま使用されます。

## sig-validity-intervalの設定方法

sig-validity-intervalの設定方法は少し特殊なので解説しておきます。validityは日数で指定しますが、re-signの方はvalidityの値により以下のように単位が変化します。

| validity      | re-sign    | 例       |
|:--------------|:-----------|:---------|
| 7日以上に設定 | 日数で設定 | 2は2日   | 
| 7日以下に設定 | 時間で設定 | 3は3時間 |

起動引数に-sigvalinsecsを指定した場合、表の設定は無効になり、validity、re-signともに秒での指定と解釈されます。常用しても良いと思いますが、署名サイクルなどのデバッグ用に用意されている機能ではないかと思われます。

# 再署名の方法

最初の署名が終わると各ノードは再署名のサイクルに入ります。再署名の対象は終了日が一番近いノードから行われますが、その際sig-validity-intervalのre-signの値が参照されます。以下の図にあるように、re-siginは終了日からマイナスされ、この日付が処理日より過去になった場合、再署名の対象となります。

![再署名対象の検索方法](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555574/7ff41c9c-7968-9030-fec9-aba66fb49b68.png "再署名対象の検索方法")

ゾーンの再署名に関する情報はrndcコマンドのzonestatusで確認可能です。以下の`next resign`の表示が再署名関連の情報です。

```Bash
# rndc zonestatus exsample.jp
name: exsample.jp
type: master
files: /var/cache/bind/db.exsample.jp
serial: 1
signed serial: 8
nodes: 22
last loaded: Fri, 29 Nov 2019 02:12:45 GMT
secure: yes
inline signing: yes
key maintenance: automatic
next key event: Mon, 02 Dec 2019 02:16:35 GMT
next resign node: node12.exsample.jp/NSEC
next resign time: Wed, 04 Dec 2019 12:34:00 GMT
dynamic: yes
frozen: no
reconfigurable via modzone: no
#
```

この例では、node12のNSECが再署名の対象`(next resign node)`となっています。この12/4`(next resign time)`という日付は、先の表(最初の署名期間の実行例)で終了日が12/12となったノードの再署名日時です。例のre-signの値はデフォルトのままですので7日となっています(12/12-7日)。ぴったり7日となっていないのは、内部表現は秒で、計算は秒で行われるためです。

## 再署名期間の決定方法

再署名時の署名期間の決定は、以下の図の方法で決定されます。

![再署名期間の決定方法](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555574/c68b4d8a-adce-5de1-d5fe-1199d8bd8729.png "再署名期間の決定方法")

最初の署名時との大きな違いはre-signを参照しなくなり、ランダムの終了日の決定範囲が固定され、かつ短いということです。再署名期間はランダム要素が短くなるため、validityに近い期間設定となります。

再署名処理も最初の署名処理と同様にsig-signing-signaturesよるカウント処理が実行されます。処理内容は最初の署名時とほぼ同じなので再署名によりまとまりが大きく変わるといったことは起きません。

再署名の前にsig-signing-signaturesを変更するという運用が可能です。しかしこの方法をとってもまとまりが大きく変わることはありません。

例えば、再署名前にsig-signing-signaturesを減らした場合(10→5など)、最初の署名より少ない再署名処理しか動きません(5個分)が次の再署名対象ノードは同じ終了日のものとなるなずです。このためすぐに再署名処理が再実行(残りの5個)され、終了日が大きく変わることはありません。

逆にsig-signing-signaturesを増やした場合(10→20など)でも最初のsig-signing-signaturesより大きいノード(11以上)の終了日は最初の署名で異なる終了日となっています。またその終了日は処理日時+re-signより未来になるので、同じタイミングでは再署名されません。

このように一度決まったまとまりは再署名時にもほぼ変わらないため、まとまりは最初の署名時のsig-signing-signaturesの値でほぼ固定されると考えた方が良さそうです。

# 鍵ファイルの処理サイクル

key-directoryに配置する鍵ファイルは定期的に状態の確認が行われます。この確認タイミングを制御する設定がdnssec-loadkeys-intervalです。デフォルトでは1時間毎に確認処理が実行されます。

次の確認処理がいつ実行されるかは、rndcコマンドのzonestatusで確認可能です。先の例にある`next key event`が確認処理の実行時間を表しています。以降では確認処理または実行タイミングをkey eventと表現します。

## key eventの処理内容

key eventでは、鍵ファイルが保持している生存期間に関する情報の把握、鍵ファイルの追加、削除の認識などが行われます。生存期間に関する情報とは、dnssec-keygenやdnssec-settimeでの設定する期間のことです。

key eventで鍵ファイルの確認を行った結果、鍵のInactive時間がdnssec-loadkeys-intervalで設定される時間より早いといった状態になる可能性があります。そのような場合は次のkey eventは、dnssec-loadkeys-intervalで決めた時間ではなく鍵ファイルに設定した時間に変更されます。これはInactive時間に限らず、他の生存時間に関しても同様です。

key eventにおいて鍵が無効になった場合、該当鍵による署名の削除が行われます。鍵が無効になるケースとしては鍵ファイルが削除される、Delete時間になるといった場合があります。

一方、鍵の追加に関しては追加されたことは認識されますがゾーン全体の署名処理は行われません。key eventおける処理はDNSKEYレコードの追加とSOA,DNSKEYの署名のみです。追加分の鍵で署名を行うには、rndcのsignコマンドを実行する必要があります。このコマンドを受信するとkey eventの処理に加え、<a href="#最初の署名方法">最初の署名方法</a>による署名処理が実行されます。

鍵サイクル関連のコマンドとしてもう一つ、rndcにはloadkeysコマンドが存在します。このコマンドはkey eventを強制的に発生させます。

dnssec-loadkeys-intervalで決定される次のkey eventの時間は基準時間はkey eventが発生した処理時間になります(rndcのloadkeysコマンドの実行も含めて)。dnssec-loadkeys-intervalが1時間の場合、自動実行していれば、毎時同じ分(minute)で実行されますが、rndcコマンド実行や鍵ファイルの生存時間の関係でkey evnet時間がずれた場合は、その時間から1時間後に変更となります。

## key eventと鍵の生存期間

key eventと鍵が持つ生存期間情報は仕組み的な関連はないため、適切に認識させるには双方の値を考慮してコマンド実行を行う必要があります。

以下の表はdnssec-settimeによりInactive時間などを設定した場合の対処方法です。次のkey event時間より前の時間を設定したか後の時間を設定したかによりコマンド実行を判断する必要があります。

| 設定時間(InactiveやDeleteなど) | 対処                               |
|:-------------------------------|:-----------------------------------|
| 次のkey event以降              | 対応不要。自動認識に任せる         |
| 次のkey event前                | rndcのloadkeysを実行する必要がある |

以下の表は鍵を追加した場合の対処方法です。鍵追加の場合は、rndcのsignコマンドを実行が必須となりますが、Active時間前にこのコマンドを実行しても署名は行われません。このため追加鍵のActive時間がどうなっているかが重要になります。

| Active時間       | 対処                                       |
|:-----------------|:-------------------------------------------|
| 処理日時         | rndcのsignコマンドを即実行                 |
| 処理日時より未来 | actvie時間を待ってrndcのsignコマンドを実行 |

## 鍵の生存期間と署名期間

key eventと同様に鍵が持つ生存期間情報と署名期間には仕組み的な関連はありません。このため、鍵のInactiveまたはDelete日を設定しても、署名の有効終了日がInactiveまたはDelete日付になることはありません。署名期間の方はこれまで説明してきたようにsig-validity-intervalなどのパラメタから決定されます。このためInactiveまたはDelete日以降の有効終了日が設定される場合もあります。

# Private Typeレコード

ゾーンの鍵毎の署名状態を保持するためPrivate Typeの資源レコードを使用しています。どのPrivate値を使用するかはsig-signing-typeで設定しデフォルトは65534です。以下は追加されたPrivate Typeレコードの参照の抜粋です。

```Bash
# dig @localhost exsample.jp TYPE65534
...
;; ANSWER SECTION:
exsample.jp.            0       IN      TYPE65534 \# 5 0871730001
exsample.jp.            0       IN      TYPE65534 \# 5 088A9C0001
....	    
#
```

この例は、5オクテットのレコードですがNSEC3の署名処理にも使用され、この場合は10オクテットとなります。最初の署名処理の説明で10ms毎に署名を行うと説明しましたがノード数が多い場合は、NSEC3の署名にも時間がかかるため数分程度10オクテットの状態になることがあります。どちらにしても完全に署名が終了すると例のよう5オクテットとなり最後の1オクテットが01に変更されます。

rndcのsigning -listコマンドはこのPrivate Typeの状態を返しています。

自動署名対応のゾーンを初期設定する場合、非署名のマスターファイルを用意しkey-directoryにKSKはZSKなどを事前に配置するのではないかと思います。この方法で署名処理は行われるのですが、再起動を行うとPrivate Typeレコードがゾーンから削除されてしまう場合があります。このような状態になると、rndcのsigning -listコマンドの処理結果が`No signing records found`を返すようになります。

このような状態に陥った場合は、起動中にkey-directoryにZSKを追加してください。Activeは処理日時とします。そのうえで、rndcのsignコマンドを実行するとすべてPrivate Typeレコードの追加が行われると思います。この動作、ソースを追ったのですが原因はよくわかりませんでした。回避方法だけわかったので記述しておきます。

# ゾーンの更新と署名

ゾーンへノードを追加したり削除したりする方法は2つあります。一つは動的更新でもう一つはマスターファイルの編集です。

自動署名の設定を行った場合、非署名のゾーンと署名ゾーンの2つのゾーンDBが保持されます。非署名ゾーンのDBはzoneステートメントのfileサブステートメントで指定したマスターファイルとなります。一方署名ゾーンはマスターファイル.signedという名前でDBが作成されます。

マスターファイルは編集対象となるのでテキスト形式ですが、署名ゾーンはRBTDB(Red Black Tree Database)といわれる内部形式になっています。このため署名ゾーンのファイルを直接編集することはできません。また、稼働中に発生するDBに対する更新は差分形式で管理されており、更新結果は.jnlというファイル名のジャーナルとして保持されます。.jbkファイルも同時に作成される場合がありますが、これは.jnlのバックアップファイルです。いずれにしてもテキスト形式以外のファイルに関しては直接更新する手段はありません。

```Bash
# ls -l *exsample.jp*
-rw-r--r-- 1 bind bind  1250 Dec  9 14:16 db.exsample.jp
-rw-r--r-- 1 bind bind   512 Dec  9 11:09 db.exsample.jp.jbk
-rw-r--r-- 1 bind bind  1413 Dec  9 14:03 db.exsample.jp.jnl
-rw-r--r-- 1 bind bind 27705 Dec 11 00:49 db.exsample.jp.signed
-rw-r--r-- 1 bind bind 24075 Dec 11 00:35 db.exsample.jp.signed.jnl
#
```

## 動的更新による更新

動的更新でノード追加を行った場合、最初に非署名ゾーン対して追加処理が実行されます。その後、署名ゾーン側にノード追加が通知されますが、この通知方法はほぼ動的更新処理と同じ処理が動作します。つまり動的更新でのノード追加では、非署名ゾーンへの動的追加、署名ゾーンへの動的追加という2段階の動的更新でノードの追加が行われます。

署名ゾーンへの動的追加が行われると該当ノードへの署名が開始されます。更新時の署名期間の決定は、以下の図の方法で決定されます。

![更新時の署名期間の決定方法](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555574/0339f24c-59e2-9195-381d-a2b76a6b6a7b.png "更新時の署名期間の決定方法")

期間の決定はsig-validity-intervalのvalidityのみで決定されます。またランダム要素がなくなるため、同じ処理時間であればすべて同じ終了日が設定されます。

動的更新の署名処理もsig-signing-signaturesによるカウントブレーク処理は動作しています。しかし、更新時の署名期間の決定ではランダム要素が無いためまとまりの発生要素は処理日時のみとなります。CPU性能によりますが、数十個程度の追加ではすべてのノードが同じ開始日、終了日になります。

## マスターファイル編集による更新

マスターファイルを編集して更新する方法では、非署名ゾーンのマスターファイルを編集します。稼働中のマスターファイルはジャーナルで管理されているため3つの手順を踏む必要があります。

rndcのfreezeコマンドは、非署名ゾーンに対するジャーナル処理を停止します。非署名ゾーンの場合、更新される経路は動的更新しかないため、事実上、動的更新を停止するコマンドということになります。

freeze状態となったゾーンに対して動的更新を行うと、クライアント側でエラーになります。更新要求自体がサーバーに送信できなくなるので、動的更新に依存した処理がある場合は注意が必要です。

rndcのfreezeコマンドでfreeze状態にできるのは非署名ゾーンのみです。コマンド実行後も署名ゾーンのジャーナル処理は停止しません。このためkey eventなどにより鍵の追加や削除などの処理は行われ、ジャーナルファイルの更新も従来通り行われます。自動署名の設定を行った場合、署名ゾーンをfreeze状態にする方法はありません。

rndcのsync -clearコマンドは非署名ゾーンと署名ゾーンのジャーナルの内容をマスターファイルに反映し、ジャーナルファイルを削除します。freezeは、非署名ゾーンにしか有効ではありませんが、このコマンドは署名ゾーンに対しても有効です。

このコマンドを実行することにより動的更新で追加や削除されたノードがマスターファイルに反映されます。マスターファイルを編集する場合は、必ずこのコマンドを実行してください。もし実行せずにマスターファイルを更新すると、非署名ゾーンと署名ゾーンの間に矛盾が発生し、編集内容の反映が行えなくなります。もし、そのような状態になった場合は、rndcのsync -clearコマンドを実行後、再起動を行ってください。大抵の問題はこの手順で直るはずです。もし、この方法でも同期が取れない場合は、諦めて非署名ゾーン関連のファイルを削除して、最初から署名しなおしてください。

マスターファイルの編集が終了したら、freeze状態を解除するため、rndcのthawコマンドを実行します。このコマンドを受信するとジャーナルの停止が解除されマスターファイルの更新内容のチェックが行われます。

マスターファイルの編集は非署名ゾーンに対してのみ行いますが更新結果は差分として把握されます。この差分情報を署名ゾーンに通知し、署名ゾーンにも更新内容が反映されます。この処理は、内部的には動的更新で行っているものと同じです。つまりマスターファイルによる更新でも署名ゾーン側は動的更新が行われていることになります。マスターファイルの編集は動的更新のコマンドを一括生成する方式と言い換えることができます。

署名ゾーン側の処理は動的更新と同じですので、署名処理も動的更新と同じです。<a href="#動的更新による更新">動的更新による更新</a>で説明した方法で署名期間が決定されます。

## 非署名シリアルと署名シリアル

ゾーン更新では触れませんでしたがマスターファイルを更新する場合はシリアルを変更する必要があります。自動署名のシリアルは非署名ゾーンと署名ゾーンでそれぞれ独立して動作します。

自動署名対応のゾーンを初期設定する場合、マスターファイルは非署名ゾーン分のみ用意します。この時に設定するシリアルが署名ゾーンのシリアルのベースとなります。

初期状態は非署名ゾーンと署名ゾーンは同じシリアルになりますが、署名ゾーンはDNSKEYレコードの追加などキャッシュクリアが必要な更新が署名処理で発生します。このような更新が入った場合、署名ゾーンのシリアルはカウントアップされます。この時点で非署名ゾーンと署名ゾーンのシリアルに差が発生します。

対外的な公式なシリアルは署名ゾーン側のシリアルです。キャッシュサーバーもセカンダリもこのシリアルを認識しています。

従来のシリアル設定の指針ではシリアルをYYYYMMDD+連番というような形で管理した方が良いという考え方がありました。また最近ではこのような形式ではなくunixtimeにした方が良いという話もあります。しかし先の説明のように自動署名では署名処理が発生するとシリアルのカウントアップが行われます。この時のカウントアップ処理にはunixtimeの考慮などはなく単純なカウントアップ行われます。このためカウントアップ処理が動作した段階でシルアルの意味付けは意味が無くなります。自動署名を行う場合はシリアルに意味付けすること自体があまり意味がないと言えます。

マスターファイルの更新を行う場合、非署名ゾーンと署名ゾーンのシリアルの関係は、以下のようになっています。

* 非署名ゾーン<=署名ゾーン

非署名ゾーンのシリアルをこの関係を維持したままカウントアップした場合、署名ゾーンは現在のシリアルからカウントアップされます。例えば非署名ゾーンのシリアルが10で署名ゾーンのシリアルが20だった場合、マスターファイルの更新でシリアルを11にした場合は、署名ゾーンは21にカウントアップされます。

非署名ゾーンのシリアルを署名ゾーンのシリアルと同じ値にした場合、署名ゾーンはシリアルは非署名ゾーンが値からカウントアップされます。非署名ゾーンのシリアルを署名ゾーンより大きくした場合でも同様に動作します。例えば先と同じ例で非署名ゾーンを30とした場合は署名ゾーンは30から始まり31へとカウントアップされます。この処理は以下の表のように動作します。

| シリアルの状態           | 署名シリアル   |
|:-------------------------|:---------------|
| 非署名ゾーン<=署名ゾーン | 署名シリアル+1 |
| 非署名ゾーン>署名ゾーン  | 非署名シリアル |


動的更新の場合は、ずれが発生しているならそのままそれぞれのシリアルがカウントアップされます。再び先の例で例えれば、非署名ゾーンは11になり、署名ゾーンは21となります。マスターファイル更新時の上の表のような処理が特殊な処理で基本的には非署名ゾーン、署名ゾーンは独立してシリアルが動ていると考えた方が良さそうです。

# どう使うか

署名を自動で行ってくれる。私はこの言葉を聞いて、鍵を勝手に作って署名をしてくれるものだと思っていました。設定があるとしても、鍵の切り替えサイクルを月一回にするくらいで、詳細は何も考えなくて良いという認識です。

しかし実際に調べてみると鍵の生存期間を自分で設定しないといけないことが分かり。なんか面倒だなと思いました。また鍵の追加は自動ではやってくれないことに気づき、やっぱり面倒だなと思いました(cronの処理を排除できない)。

文句ばかり言ってもしょうがないので、実際の動作確認を行ったところ、署名の終了日が鍵のInactive日になりません。この辺りの調査から今回のドキュメントの作成が始まりました。

動作を確認した今現在の感想は、私の感覚では自動化とは言えないということと、対象としているのは大規模なノードを持っているゾーンなんだなということです。ノード数が多いと、署名処理に使われる負荷が大きくなります。それをできるだけ分散したいんだろうなぁと今は思っています。

私の管理しているゾーンはノード数も多くなく、これまでは外部の署名で対応していました。自動署名対象としては明らかに外れるケースのような気がしますが運用してみようと今は思っています。理由はいろいろあるのですが、簡単に言うと考えるのが面倒になったということです。

今現在、外部ツールとしてcronのshellなどを公開してくれているサイトは多々ありますが、将来的にこれらの機能が使えるかどうかは開発がどのように進むかによると思います。そしてそれを判断するためには、今回行ったような調査を毎回行う必要があります。そういった調査は私には重荷となるので、できるだけ手を入れず、そのまま使っていくのが無難かなと考えています。以下に私の設定方針をまとめます。

1. パラメタを別途設定は行わずデフォルトのまま使用する
2. 鍵の生存期限は以下の表の設定とする
3. 鍵の追加はcronを使用し月末に実施する
4. 鍵の追加時に同時にcronでrndcのsignコマンドも実行する

| 設定     | 値               |
|:---------|:-----------------|
| Publish  | 未設定(処理日時) | 
| Activate | 未設定(処理日時) |
| Inactive | +33日            |
| Delete   | +34日            |

1.は先の開発の進み方に左右されないための方針です。提供されるものをできるだけそのまま使用するのを基本とします。

2.は1.と矛盾するのですが、sig-validity-intervalのデフォルトが30日になっているので鍵の有効期限を一か月とします。設定値に左右されるのはあまり本意ではないのですが有効期限はsig-validity-intervalと合っていた方が良いと思うのでしょうがなくです。

3.は鍵の追加方法です。結局cronに頼ります。追加タイミングはsig-validity-intervalに合わせ月一回とします。

4.は追加鍵の署名タイミングです。追加と同時とします。鍵の運用方針として、以下みたいな図を見かけます。仕組み上は、図の通り鍵の生存期間を設定可能ですが、<a href="#key-eventと鍵の生存期間">key eventと鍵の生存期間</a>で説明したように署名を行うためにコマンド発行が必要となるのでそのような設定をしてもあまり意味がありません。鍵追加と同時にコマンドを発行し鍵の署名を行う運用とします。

![鍵のロールオーバー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555574/ac8f28e0-ca6e-e4bc-7bf6-280dfa965c43.png "鍵のロールオーバー")

# その後(追記)

決まった方針に従って環境を整えました。間違って認識中の鍵を削除して署名をリセットしたりいろいろとありましたが、以下のようなshellスクリプトで運用を開始しました。

<details><summary>bind-sign-support</summary><div>

2022年2月の追記で修正を行いました。そちらが最新ですので、入手はそちらからお願いします。ここは最初の投稿時にソースがありました。

</div></details>

仕組みは簡単で、/etc/bind/keysを日付順に並べて一番古いZSKを削除し、新しいZSKを追加するというものです。認識中の鍵が削除されないようにするのは/etc/bind/keysに適当にZSKファイルを追加しておいて認識中のファイルが一番古いファイルとして認識されないようにしています。

KSKに関してはDSの上位への追加連絡が必要なので自動署名の対象としていません。shellスクリプト上の17710の指定はKSKを削除されないようにするためです。

同一サーバーで外部向けと内部向けのゾーンファイルを保持しているのでVIEW機能を使用しています。outsideが外部向けのVIEW名です。

現在の鍵ディレクトリの状態は以下の通りです。実際のファイル名は運用中のドメイン名ですがexsample.jpに書き換えています。

```Bash
root:/etc/bind/keys# ls -lt
total 56
-rw-r--r-- 1 root bind  722 May  1 06:52 Kexsample.jp.+008+12408.key
-rw-r----- 1 root bind 1824 May  1 06:52 Kexsample.jp.+008+12408.private
-rw-r--r-- 1 root bind  722 Apr  1 06:52 Kexsample.jp.+008+35973.key
-rw-r----- 1 root bind 1824 Apr  1 06:52 Kexsample.jp.+008+35973.private
-rw-r--r-- 1 root bind  722 Mar  1 06:52 Kexsample.jp.+008+63171.key
-rw-r----- 1 root bind 1824 Mar  1 06:52 Kexsample.jp.+008+63171.private
-rw-r--r-- 1 root bind  722 Feb  3 17:47 Kexsample.jp.+008+47946.key
-rw-r----- 1 root bind 1824 Feb  3 17:47 Kexsample.jp.+008+47946.private
-rw-r--r-- 1 root bind  722 Feb  3 16:42 Kexsample.jp.+008+65175.key
-rw-r----- 1 root bind 1824 Feb  3 16:42 Kexsample.jp.+008+65175.private
-rw-r--r-- 1 root bind  722 Feb  3 16:42 Kexsample.jp.+008+47055.key
-rw-r----- 1 root bind 1824 Feb  3 16:42 Kexsample.jp.+008+47055.private
-rw-r--r-- 1 root bind  961 Nov 15  2019 Kexsample.jp.+008+17710.key
-rw-r----- 1 root bind 3316 Nov 15  2019 Kexsample.jp.+008+17710.private
root:/etc/bind/keys#
```

ファイルの日付が2/3となっているのが、先に説明した適当に追加したZSKです。現在は3つの無駄ファイルがあり、スクリプトで作成したファイルが削除されるのは9月になります。

4/1段階でスクリプト実行後の鍵認識の状態は以下のようになっています。

```Bash
root:~# rndc signing -list exsample.jp in outside
Done signing with key 17710/RSASHA256
Done signing with key 35973/RSASHA256
Done signing with key 63171/RSASHA256
root:~#
```

35973が4月に追加となった鍵です。63171は3月まで使用していた鍵ですが有効期限が以下のようになっているのでまだ有効です。

```Bash
root:/etc/bind/keys# head -6 *63171*.key
; This is a zone-signing key, keyid 63171, for exsample.jp.
; Created: 20200229215201 (Sun Mar  1 06:52:01 2020)
; Publish: 20200229215201 (Sun Mar  1 06:52:01 2020)
; Activate: 20200229215201 (Sun Mar  1 06:52:01 2020)
; Inactive: 20200402215201 (Fri Apr  3 06:52:01 2020)
; Delete: 20200403215201 (Sat Apr  4 06:52:01 2020)
root:/etc/bind/keys#
```

4/4段階では以下のようになり、Deleteの設定で鍵の認識が外れました。

```Bash
root:~# rndc signing -list exsample.jp in outside
Done signing with key 17710/RSASHA256
Done signing with key 35973/RSASHA256
root:~#
```

syslogには再署名によるシリアルアップ(によるセカンダリへの通知)が記録されています。

```Bash
Apr  4 06:52:01 hostname named[564]: zone exsample.jp/IN/outside (signed): sending notifies (serial 1580709105)
```

同様に5/1段階では以下のようになります。12408が5月分の追加鍵です。

```Bash
root:~# rndc signing -list exsample.jp in outside
Done signing with key 12408/RSASHA256
Done signing with key 17710/RSASHA256
Done signing with key 35973/RSASHA256
root:~#
```

その後、5/6段階では以下の通りです。5/4でないのは単に記録を取るのを忘れていたためで深い意味はありません。

```Bash
root:~# rndc signing -list exsample.jp in outside
Done signing with key 12408/RSASHA256
Done signing with key 17710/RSASHA256
root:~#
```

先に示した鍵ディレクトリの状態は上記処理後の状態です。

shellスクリプトは私の管理組織ではこの程度で十分ですが、エラー処理等ない適当スクリプトなので参考程度にしてください。自動更新がうまく回るようになったので、本格的にDSを上位組織に通知しようかと思っているところです。

# 2022年2月の追記
Debian 11にアップデートして問題無いと2021年9月に書きましたが、問題ありました。参考にされていた方、申し訳ありません。2021年10月のcronの実行結果確認が抜けてました。

dnssec-keygenコマンドの引数から`-r`オプションが削除されたようです。こういうことがあるから、利用するなら最低限の開発動向を追っかけないと危険ですね。以下に修正後のスクリプトを置いておきます。

<details><summary>bind-sign-support</summary><div>

```Bash:bind-sign-support
#! /bin/sh
loginfo() {
         logger -p local0.info -t bind-sign-support $1
}

KEY_DIR=/etc/bind/keys
DOMAIN=exsample.jp
VIEW=outside
EXCLUSVE_FILE='(.*.private$|17710.key)'

rmf=`ls -tr $KEY_DIR/K${DOMAIN}* | egrep -v $EXCLUSVE_FILE | head -1 | sed s/.key$//`
loginfo "remove old key :$rmf"
rm $rmf.*

cd $KEY_DIR

dnssec-keygen -3 -a RSASHA256 -b 2048  -I +33d -D +34d  $DOMAIN

chmod 640 *.private

rndc sign $DOMAIN in $VIEW
```

</div></details>

おかしくなった状態のリカバリですが、認識中のZSKが削除されないように、削除して良いZSKをdnssec-keygenで何個か作ってください。作る数は認識が外れたZSKを何カ月くらい残すかです。その後、スクリプトを実行すれば最新キーで署名がされます。一番古いZSKが一個削除されますがrndc signで認識されていないので問題ありません。

# 2022年3月1日の追記
2022年2月の追記の対応結果の確認をしました。古い未使用キーは削除され、新しいキーが追加できるのを確認でしました。このスクリプトで当面はしのげそうです。2月に追加した認識中のZSKがInActiveされてDeleteされるのは3月6日なので、その時点でまた確認してみようと思います。

ところで、bind 9.16からKey and Signing Policy（KASP）なる仕組みが実装されたそうです。DNSSEC署名の自動化ポリシーを設定する機能らしいです。まさにこのドキュメントで扱っている内容ですね。でもbind開発の人たちって私みたいな凡人から見たら斜め上の考えで開発しているように見えるので、私が期待した通りの動きをするのか分かりません。今現在、時間が取れなくて詳細を調査することができないので興味があるなら、そちらの調査もお勧めします。

# 2022年3月7日の追記
2月に追加した認識中のZSKがDeleteされたのを確認しました。これで今回の修正の確認作業は終了です。スクリプトを直したりしたら、このサイクルでの確認が必要ですね。今後はまた基本ほっとく、お気楽運用に戻ろうと思います。

# 2025年1月11日の追記
2022年3月1日の追記で触れた、KASPについて確認した内容を<a href="https://qiita.com/waiseiningenchokon/items/38fc377d838d10167bcc">ドキュメント<a/>に公開しました。
bind 9.20から全自動ゾーン署名固有の設定は使用不可となるそうです。もしこのドキュメントを読んで全自動ゾーン署名を使ってみようと思った方などいらっしゃいましたら、移行をご検討ください

# あとがき

昔、新世紀エヴァンゲリオンの考察同人誌というのを読んだことがあって、”あとがき”みたいな部分に、”この本を書く上でいろいろなことを調べた(死海文書?とか)。異論や反論があるなら、最低限自分と同じレベルの調査を行ってからじゃないと聞く耳持たない。”というようなことが書いてあって同人誌っていうのは凄い世界だなぁと思いました。