要約

  • TTL失効は、データが即座に誤りになる瞬間ではなく、通常の再利用権限が終わり、情報源へ再照会しなければならない瞬間である。RFC 8767の例外は、その権威更新が完了できない場合にだけ始まる。
  • Client response、query resolution、failure recheck、maximum staleの四つのtimerは別の仕事をする。設定画面の一つのenabled表示から、待ち時間、再試行、保持期間、実際の応答を推定してはならない。
  • 古いRRset、更新失敗、RRSIGの時刻、短い応答TTL、EDE、継続するrefresh、アプリケーション結果を一つの「DNS成功」に潰すと、resolverの判断が権威運用者の現在の発言に見えてしまう。

災害用の名前が古い否定に阻まれた

ある自治体が平常時には存在しない災害情報用ホスト名を持っているとする。平時の問い合わせには権威DNSがNXDOMAINを返し、recursive resolverはその否定をcacheした。大規模障害が起き、自治体は名前を作成して新しい配信基盤を公開した。しかし同じ障害で一部resolverから権威サーバーへの経路が失われていた。cache内のNXDOMAINは普通のTTLを過ぎている。

Resolverが失敗を返せば、利用者は明確な障害を見る。Stale NXDOMAINを返せば、応答は速く、DNSメッセージとして整っているが、新設された緊急入口は存在しないままになる。前日の不在が、今日の復旧計画を止める。

Serve-staleはしばしば古いAレコードでサービスを救う機能として説明される。だが、cacheには存在の証拠だけでなく、不存在の証拠もある。権限設計は「何か返せたか」ではなく、どの過去の主張を、どの失敗証拠に基づいて、いつまで実行させたかを扱わなければならない。

TTLは二つの期間を分ける

RFC 1035のTTLは、cacheしたRRについて情報源を再び参照すべき時点と、通常は破棄すべき時点を示した。RFC 2181は最大生存時間として整理した。RFC 8767はこれらを更新し、TTLが終われば情報源へ再照会する義務を保ちながら、authoritative refreshができない例外状況では期限切れデータを未失効のように使えるとした。

ここで生まれるのは二つの期間である。第一はpublisherが与えた通常cache期間。第二はresolver operatorが自分の責任で与えるstale保持・応答期間である。第二の期間を第一の延長と記録すると、誰の判断だったかが消える。

TTL 0は例外に入らない。現在のtransactionだけに使われ、cacheしてはならないデータは、後でstale候補にもできない。また、受信TTLを約7日にclampする勧告と、失効後に何日保持するかというmaximum staleは別の上限である。前者は通常cacheの入力制御、後者は非常時権限の寿命を表す。

四つのtimerが一つの応答を作る

RFC 8767はformal algorithmを一つに固定していない。Local processingは相互運用のために同じ値を持つ必要がないからである。しかし、例示された四timerは監査の最小単位になる。

Client response timerは、待っているclientにまだ価値があるうちに返す期限である。例示値は約1.8秒。短すぎれば、到達可能だが遅いauthorityより古いcacheを優先する。長すぎれば、freshnessを守ろうとして利用者のtimeoutを越える。

Query resolution timerは、上流探索全体の作業予算である。RFCの議論では10~30秒程度が一般的とされる。Staleをclientへ返した後も、このtimerまではrefreshを続けることが重要だ。応答したことは修復を終えたことではない。

Failure recheck timerは、直近に失敗したauthorityを各client queryが再び叩くことを防ぐ。例示は30秒より頻繁に試さないこと、上限の文脈は5分である。RFC 9520はresolution failure自体のcacheを必須化し、1秒以上5分以下、持続障害へのbackoffを求める。これはold answerのTTLではない。

Maximum stale timerは、通常expiry後にcache memoryへ残す最大期間である。提案例は1~3日。長くすれば長時間障害に強いが、旧address、旧delegation、旧NXDOMAINが動き続ける時間とmemory使用も増える。

運用上は、四値に加えて、それぞれがいつ開始・停止したかを記録する。Failure cacheが生きている間に即時stale応答したのか、client deadlineまで新規refreshを待ったのか、background fetchが終了したのか。同じresponse bytesでもauthority chainは異なる。

更新を認めるpacket、認めないpacket

RFC 8767では、AA bitを持ち、RCODEがNOERRORまたはNXDOMAINであるauthoritative responseは、以前の状態をrefreshしたものとして扱わなければならない。他のRCODEは通常refresh failureとみなし、old stateを維持する。

この規則により、一時的なSERVFAILが最後の有用なRRsetを消すことを避けられる。一方、新しいauthoritative NXDOMAINはold positive answerを終了できる。削除が誤操作に見えても、resolverにはintentを検証する手段がない。Serve-staleは権威方針を覆す投票ではない。

REFUSEDは複数の意味を持つ。明示的な停止、ACL事故、lame delegationのいずれかもしれない。全authorityがREFUSEDしたときstaleを禁止するかをimplementationが選べるため、製品名ではなくreleaseとtest vectorで意味を確定する必要がある。

Refresh failureのcacheも別に残す。RFC 9520に従うfailure entryはupstream queryを抑制するが、nameの存在やvalueを証明しない。監査画面で「cached」とだけ表示すると、data cacheとfailure cacheという反対のobjectが同じになる。

30秒は新しいsource TTLではない

Expired recordを返すとき、message内TTLは0より大きくなければならず、RFC 8767は30秒を勧告する。これはauthoritative operatorが与えた残り寿命ではない。Resolverが古いprojectionをdownstream cacheへ短時間だけ再配布するための値である。

したがって、packet captureにはoriginal TTL、cache insertion、ordinary expiry、stale age、response TTL、fallback reasonを結び付ける。単独のTTL=30では、失効寸前のfresh responseか、数時間古いstale responseか判別できない。

RFC 8914のEDE code 3はStale Answer、code 19はStale NXDOMAIN Answerを表す。Code 7はSignature Expiredである。EDEは原因を伝えるがRCODE処理を変えない。StubやapplicationがEDEを捨ててもprotocol違反とは限らない。EDEが付いたことを、clientが危険を理解した証拠にしてはいけない。

Forwarding chainではさらに難しい。上流recursiveがEDE付きstaleを返し、中間forwarderがoptionを保存しない場合、最終clientには普通の成功しか見えない。Evidence contractにはEDEの生成、転送、消失を各hopで含める必要がある。

DNSSECはcacheの時計に従わない

RRSIGはinceptionとexpirationを持ち、RFC 4035はvalidatorのcurrent timeがその間にあることを要求する。Maximum staleが3日でも、signatureが1時間後に切れれば暗号学的検証はそこで終わる。保存できることは、認証できることではない。

特にstale NSEC/NSEC3は、新しいDS、TLSA、nameを覆い続ける可能性がある。Availabilityを守る仕組みがsecurity migrationを見えなくする。Signed dataについては、stale-and-secure、stale-but-signature-expired、bogus/failure、insecure local exceptionを別counterにする。

AttackerがauthorityへのDDoSと組み合わせれば、古いaddressやdenialの実行期間を延ばせる。既に所有者が手放したaddressがdomain-validationに使われる危険もRFC 8767は指摘する。Serve-staleは脆弱性を新設しないが、古いbindingが作用できるfailure outcomeを選ぶ。

BINDとUnboundを同じものとして扱わない

現在のBIND文書では、stale cache保持、stale回答、reply TTL、maximum age、refresh間隔、rndc serve-stale runtime overrideが別である。Reply TTLのdefaultは30秒、feature有効時のmaximum retention defaultは1日。Client timeout optionはdefault offで、現在の実装は有効時に0だけをsupportすると記載される。RFC例示の1.8秒を設定名から推測できない。

Unboundはserve-expired-*で、expired age、reply TTL、client timeout、failed refresh後のresetを分ける。Current documentationはimmediate replyとRFC-style waitingを区別する。Version移行でdefault modeも変わる。

Canaryはfast/slow/unreachable authority、SERVFAIL、REFUSED、fresh NXDOMAIN、positive/negative、valid/expired RRSIG、TTL 0、cache pressure、restart、runtime disableを含める。確認するのはcommand受付ではない。Cache object、upstream packet、response、EDE、continued refresh、replacement、application connectionである。

情報源