要約

  • RFC 9520 は、解決失敗を最低 1 秒、最長 5 分キャッシュするよう求める。該当エントリーは上流への処理を止めるが、NXDOMAIN や NODATA を証明しない。
  • 利用可能なサーバーとトランスポートのいずれからも、データ、下位ゾーンへの参照、有効な否定応答が得られなかった時だけ、解決失敗が成立する。
  • 検証可能な記録には、試した経路、再送回数、束ねたクライアント、キャッシュキーと範囲、バックオフ、抑止した親・祖先問い合わせ、資源圧力、復旧確認プローブが必要である。

到達不能になった三つの名前と、90 万件の問い合わせ

2021 年 10 月 4 日、Facebook の保守コマンドが誤ってデータセンターをグローバルバックボーンから切り離した。Meta の技術報告によると、権威 DNS 拠点はデータセンターへ到達できなくなったため、自らを不健全と判断して BGP 広告を撤回した。DNS サーバーは動作していたが、インターネットから届く経路が消えた。

影響は Facebook の境界にとどまらなかった。Verisign の観測では、facebook.com、instagram.com、whatsapp.net に対する .com と .net の通常トラフィックは合計毎秒約 7,000 問い合わせだった。約 6 時間の障害中、その値は毎秒 900,000 を超えた。Google と Cloudflare のうち最も活発なリゾルバー送信元では、それぞれ平常時の約 7,000 倍と 2,000 倍に達した。

親側の委任情報は変わっていない。それを何度聞き直しても、子側が撤回した経路は戻らない。それでも再試行は、一つの到達不能ゾーンの費用を健全な上位層へ移した。最初の障害原因は Facebook にあったが、その後の負荷の大きさはリゾルバーの振る舞いにも左右された。

RFC 9520 は、ここに限定的なブレーキを置く。利用可能なすべての経路が有用な情報を返さなければ、リゾルバーは解決失敗をキャッシュしなければならない。後続要求が未期限切れの失敗に一致する間、対応する上流問い合わせを送ってはならない。

その意味は「直前に失敗した作業を、今は繰り返さない」である。「この名前は存在しない」ではない。NXDOMAIN と NODATA は不在に関する有用な DNS 情報だが、解決失敗は存在を判断できる情報が得られなかった状態である。前者は内容の証拠、後者は局所的な処理抑制の根拠にすぎない。

どこか一経路が生きている限り、全体失敗ではない

反復リゾルバーは通常、複数の NS 名、各 NS の複数アドレス、場合によっては同じアドレスへの複数トランスポートを持つ。一つの timeout、SERVFAIL、REFUSED、TLS 失敗だけでは、全選択肢を使い切ったことにならない。

RFC 9520 がいう有用な応答は、要求データ、下位ゾーンへの参照、または問い合わせ名にデータがないことを示す有効な応答である。どれか一つの利用可能サーバーが返せば、解決失敗ではない。したがって失敗エントリーの前に、候補アドレスとトランスポート、各試行の開始・終了・結果を示せなければならない。

同じ問い合わせを同じサーバーアドレスへ同じトランスポートで送る場合、最初の送信後に許される再試行は 2 回まで、合計 3 回である。利用可能と分かっている別トランスポートが安全方針に合えば、同じアドレスでも試せる。RFC は一律の timeout を決めず、一般的な値としておよそ 3~30 秒を挙げる。

経路遅延、ハンドシェイク、anycast、顧客への約束が異なる以上、時間をローカルに決めるのは妥当だ。ただし値と結果は可視でなければならない。残った経路と時系列を欠いた server failed は、監査可能な結論ではない。

SERVFAIL は原因の名前ではない

権威サーバーは有効なゾーンデータを持てない時に SERVFAIL を返すことがある。再帰サーバーは上流経路を使い切った時や DNSSEC 検証に失敗した時にも同じ RCODE を返す。REFUSED はしばしば方針や権限範囲を表す。timeout は局所期限まで応答がなかったことだけを示し、ICMP、TCP、TLS のエラーはより早くトランスポートを終わらせる。

委任ループ、CNAME/DNAME ループ、FORMERR、DNSSEC の署名・鍵・不存在証明の問題は、それぞれ別の機構を持つ。キャッシュは原因を区別してよいが、共通の効果は限定的である。対応する上流作業を一定時間止めるだけだ。REFUSED を SERVFAIL に、bogus データを検証済みに、沈黙を不存在に変換してはならない。

RFC 8914 の Extended DNS Error は、Cached Error、No Reachable Authority、DNSSEC Bogus などの背景を付けられる。しかし EDE は RCODE の処理を変えない。説明が詳しくても、署名された証拠や新たな権威にはならない。

多数の利用者を一つの上流処理に束ねる

人気名の権威が応答しない間、数百のクライアントが同じ QNAME、QTYPE、QCLASS を送ることがある。query joining を行うリゾルバーは、それらを一つの進行中解決へ結び付ける。行わなければ、利用者ごとに上流問い合わせと再試行が生まれる。

RFC 9520 が参照する DNS-OARC 35 の実験では、botnet ドメインの権威が正常な時は毎秒約 50 問い合わせだった。すべての権威が SERVFAIL を返すと、約 60,000 に達し、委任が変わっていない root と TLD にも追加トラフィックが生じた。

joining は RFC 5452 が示す birthday attack の面も小さくする。同等の未完了トランザクションが複数あるほど、偽応答はそのどれかに一致しやすい。必要なのは三つの別々の制御である。同一需要を束ねる。アドレスとトランスポートごとの送信を制限する。全経路を使い切った失敗を保存する。

joining は同時トランザクション数を決め、3 回上限は一経路の仕事量を決め、キャッシュは次の仕事が始まる時を決める。どれか一つの実装だけで、残り二つを証明できない。

1 秒と 5 分の間に復旧負債が生まれる

失敗キャッシュは最低 1 秒、最大 5 分である。最小値は運用者が設定可能であることが望ましい。持続的な失敗には線形または指数バックオフを使えるが、5 分を超えてはならない。

長い時間は継続障害中の上流負荷を減らす一方、修復後の再発見を遅らせる。短い時間は復旧を早く見つける一方、障害中の仕事を増やす。バックオフは負荷を節約すると同時に、復旧負債を積む。

各エントリーには、キー、範囲、原因、挿入時刻、実際の期間、バックオフ段階、期限、設定版が必要だ。期限後は蓄積した全需要ではなく、一つの制御されたプローブを出す。最初の有用応答が得られれば、抑止の根拠は消える。測るべきは、技術的に回答可能になった時から利用者が受け取るまでの遅延である。

キーの設計も影響を変える。DNSSEC 失敗は名前・クラス・タイプ、到達不能は IP 単位にできる。一台の SERVFAIL が全サーバーを止めるとは限らない。RFC 2308 は失敗キャッシュが任意だった時代に、問い合わせとサーバーの具体的範囲を定めた。RFC 9520 は機能を義務化し、内部構造を実装に委ねる。実装者には範囲を文書化する責任がある。

親ゾーンは修理ボタンではない

全権威が無応答になると、親へ NS を何度も聞き直す実装があった。RFC 4697 はその積極的な再問い合わせを禁じた。RFC 9520 は全 query type とすべての祖先に拡張し、失敗ゾーンと同様に制限する。

健全な親は正しい委任を再提示できても、子のネットワークを直せない。問い合わせを抑えることは、委任が誤りだという宣言ではない。現在の失敗期間に同じ質問が新しい有用情報を生まない、という作業判断である。

抑止した親・祖先問い合わせ数を記録すれば、障害がどこへ負荷を移したか分かる。期限後の制御プローブは、委任変更や新アドレスを発見できる。抑止が正当なのは、終わるからである。

DNSSEC の失敗は、信用できない TTL とともに記録する

RFC 4035 は、繰り返す検証失敗を抑える BAD cache を許可していた。検証に失敗したデータの TTL は信用できないため、リゾルバーが短いローカル期間を与え、資源枯渇を防ぐ。

RFC 9520 は任意を義務へ変えた。DNSSEC 検証失敗も保存しなければならない。無効 RRset を安全なデータとして返してよいという意味ではない。直近の試行で受容可能なデータを得られなかった事実だけを保持する。

EDE はキャッシュ済みエラーや bogus を説明できる。それでも信頼連鎖、時刻、範囲、次の試行が必要だ。読みやすい説明は暗号学的証拠の代わりではない。

Serve Stale は古い内容を返し、失敗キャッシュは作業を止める

RFC 8767 は更新に失敗した時、ローカル方針の下で期限切れデータを返すことを認める。失敗中の権威への再確認を、一般に約 30 秒間隔へ制限する。以前は有用だった内容で継続性を保つ仕組みだ。

RFC 9520 は古い内容がなくても働く。初めての名前、新しいタイプ、Serve Stale 無効時も同じである。stale 応答は「以前のデータを一時再利用する」、失敗キャッシュは「有用データが得られず、期限まで作業を繰り返さない」と言う。両者は別の約束だ。

保護キャッシュ自身も攻撃対象になる

攻撃者は大量のランダム名やタイプを失敗させ、メモリと CPU を消費できる。エントリー数、バイト、挿入、追い出し、送信元集中、ランダムラベルを制限し、測定する必要がある。

失敗メッセージは署名済み DNS データでもない。トランザクションに一致する偽応答は、バックオフ中に本物の権威への問い合わせを止め得る。5 分上限は一回の影響を限定するが、反復 spoofing は更新できる。未完了取引を少なくし、トランスポート証拠を保存し、サーバーや観測点を比較しなければならない。

このキャッシュは、証拠義務を伴う circuit breaker である。上限がなければ retry が無意識の攻撃になる。範囲と期限がなければ breaker 自体が拒否になる。

防御可能な失敗判断の最小記録

QNAME、QTYPE、QCLASS、最初の時刻、束ねたクライアント群を保存する。zone cut、NS 集合、アドレス、観測点、トランスポートを列挙する。各試行に開始、終了、再送番号、生結果、有用応答判定を持たせる。

全経路失敗後は、RCODE、トランスポート、DNSSEC、EDE を分離する。キー、範囲、挿入、期間、段階、期限、追い出し優先度を加える。抑止した祖先問い合わせ、stale の有無、クライアントに返した結果も必要だ。

フリート全体では、クライアント要求、joined group、実際の上流問い合わせを比較し、増幅率、遅延、CPU、メモリ、カーディナリティを公開する。期限後はプローブ先、最初の有用応答、利用者から見た復旧遅延を記録する。

この証拠は、費用を負う運用者の手元に判断を置く。親や IETF にローカルタイマーを認証してもらう必要はない。なぜ止め、いつ再開したかは示さなければならない。

出典