2026年6月16日

2026年6月16日

EDNS0 の鍵ローテーション手順:DNS Cookie のシークレット更新と DNSSEC 鍵更新時の確認

EDNS0 そのものに鍵はありませんが、EDNS0 の上で動く DNS Cookie にはサーバー側のシークレット(秘密値)があり、これを定期的に入れ替えるのが「EDNS0 の鍵ローテーション」に当たる作業です。また、DNSSEC の鍵を更新するときは応答が大きくなるため、EDNS0 のバッファサイズと TCP へのフォールバックも確認が必要です。この記事では、権威 DNS やキャッシュ DNS を自分で運用している人向けに、この2つの作業を順に説明します。

EDNS0 と「鍵」の関係を整理する

EDNS0(RFC 6891)は、DNS のメッセージに OPT レコードを付けて、512 バイトを超える UDP 応答や追加のオプションを扱えるようにする拡張の仕組みです。それ自体は暗号の機能を持ちません。EDNS0 に関わる鍵は、次の2つの場面で登場します。

  • DNS Cookie(RFC 7873、RFC 9018): EDNS0 のオプションとして送られる Cookie で、送信元アドレスを偽装した問い合わせやキャッシュ汚染への耐性を高めます。サーバーはシークレットを使って Cookie を作るため、このシークレットをローテーションします。
  • DNSSEC の鍵更新: 鍵そのものは DNSSEC の仕組みですが、更新中は DNSKEY の応答が大きくなり、EDNS0 のバッファサイズを超えやすくなります。

なお、ゾーン転送などで使う TSIG の鍵は EDNS0 ではなく別の仕組みです。名前が似た作業と混同しないよう、どの鍵を更新するのかを最初に決めておきます。

DNS Cookie のシークレットを入れ替える考え方

DNS Cookie では、クライアントが Client Cookie を送り、サーバーが「クライアントの Cookie・送信元アドレス・時刻・サーバーのシークレット」から計算した Server Cookie を返します。次回以降の問い合わせにこの Cookie を付けることで、サーバーは「以前やり取りした相手からの正当な問い合わせ」と判断できます。

シークレットを一度に切り替えると、古いシークレットで作った Cookie が一斉に無効になります。DNS Cookie は無効でも致命的な障害にはなりにくい設計ですが、再取得のための往復が増えたり、実装によっては TCP への切り替えが起きたりします。そこで RFC 9018 では、次の順序での入れ替えが推奨されています。

  1. 新しいシークレットを、すべてのサーバーに「検証には使うが、生成には使わない」状態で追加する
  2. 全サーバーに行き渡ったら、新しいシークレットで Cookie を生成するように切り替える
  3. 古い Cookie が使われなくなる時間(RFC 9018 の Cookie の有効期間の目安は1時間程度)を置いてから、古いシークレットを削除する

エニーキャストや複数台の構成では、全サーバーで同じシークレットを使うことが前提です。1台だけ違うシークレットを持っていると、問い合わせ先が切り替わるたびに Cookie が無効と判断されます。

BIND での手順

BIND では options の cookie-secret を複数書けます。最初に書いたものが生成に使われ、すべてが検証に使われます。シークレットはランダムに作ります。

# SipHash-2-4 用の 128 ビット(16進数32桁)のシークレットを作る
openssl rand -hex 16

作業前に named.conf をバックアップします。まず新しいシークレットを2番目に追加し、全サーバーに反映します。

options {
    answer-cookie yes;
    cookie-algorithm siphash24;
    cookie-secret "現在のシークレット";
    cookie-secret "新しいシークレット";
};
sudo named-checkconf
sudo rndc reconfig

全台に行き渡ったら、2行の順番を入れ替えて新しいシークレットを先頭にし、再度 rndc reconfig します。1時間以上たってから古いシークレットの行を削除します。シークレットは設定ファイルに平文で書かれるので、ファイルの権限を絞り、Git などで管理する場合は秘密情報として扱ってください。

Unbound での手順

Unbound は answer-cookie: yes で DNS Cookie に応答します。新しめのバージョンでは、シークレットをファイルで管理し、unbound-control から追加・有効化・削除できるようになっています(2026年10月現在)。利用できる設定項目やコマンドはバージョンによって異なります。使っているバージョンの unbound.conf と unbound-control のマニュアルで、Cookie シークレット関連の項目があるかを先に確認してください。手順の考え方は BIND と同じで、追加 → 生成側の切り替え → 古いシークレットの削除の順に進めます。

Knot DNS の mod-cookies のように、シークレットを一定期間で自動的に作り直す実装もあります。単体運用なら自動更新に任せ、複数台で運用する場合は共通の固定シークレットを設定して、上記の手順で入れ替える、という使い分けになります。

Cookie のローテーションを確認する

dig は既定で Client Cookie を送り、応答の OPT PSEUDOSECTION に Cookie を表示します。ローテーションの前に、受け取った Cookie を控えておきます。

dig @ns1.example.com example.com SOA
; COOKIE: 0123456789abcdef... (good)

新しいシークレットで生成を始めた後、控えておいた Cookie を指定して問い合わせ、まだ (good) と判定されるかを確かめます。

dig @ns1.example.com +cookie=控えておいたCookie全体 example.com SOA

古いシークレットを削除する前にこれが good なら、移行期間中の互換性は保たれています。削除後に同じ確認をすると、新しい Cookie が返されるようになります。

DNSSEC の鍵更新で EDNS0 を確認する

DNSSEC の ZSK や KSK を更新すると、新旧の鍵や署名が一時的に並ぶため、DNSKEY の応答が普段より大きくなります。2020年の DNS Flag Day 以降、EDNS0 の UDP バッファサイズは 1232 バイトを目安にすることが広く推奨されており、これを超える応答は TC フラグ付きで切り詰められ、クライアントは TCP で問い合わせ直します。

鍵の更新の前後で、応答サイズと TCP での応答を確かめます。

dig @ns1.example.com +dnssec +bufsize=1232 example.com DNSKEY
dig @ns1.example.com +dnssec +tcp example.com DNSKEY

1つ目の結果で MSG SIZE rcvd の値と、flags に tc が付いていないかを見ます。tc が付く場合は、2つ目の TCP での問い合わせが正常に返ることが必須です。ファイアウォールで TCP 53 番を閉じていると、鍵の更新中だけ名前解決が失敗する、という分かりにくい障害になります。

応答サイズを抑えたい場合は、RSA より署名が小さい ECDSA P-256(アルゴリズム 13)を使うのが一般的です。アルゴリズムの変更は通常の鍵更新より手順が複雑になるため、検証用のゾーンで一度試してから本番で行ってください。

まとめ

  • EDNS0 自体に鍵はなく、主な対象は DNS Cookie のサーバーシークレットと、DNSSEC 鍵更新時の応答サイズ
  • Cookie のシークレットは「追加 → 生成側の切り替え → 古いものを削除」の順で入れ替え、複数台では同じシークレットを使う
  • BIND は cookie-secret を複数書け、先頭が生成用になる。変更は named-checkconf と rndc reconfig で反映する
  • dig の +cookie で控えた Cookie を再送し、移行期間中も good と判定されるかを確かめる
  • DNSSEC の鍵更新前後は +bufsize=1232 と +tcp で DNSKEY を問い合わせ、TCP 53 番が通ることを確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲