要約

  • HTTP/2では、名前解決と証明書の検証から妥当と判断できれば、永続的で多重化された接続を、異なるURIオーソリティーを持つ要求にも再利用できる。ただし、その証拠が示すのは試行の合理性であって、最初の握手で選ばれた内部サービスが全オリジンを受け持つという事実ではない。
  • 421 Misdirected Requestが拒否するのは、オリジンと接続の組み合わせである。URIの移転、要求の構文エラー、TLSの失敗を意味しない。クライアントは同じ操作を別の接続で再試行でき、メソッドが冪等でない場合も対象になる。一方、通常のプロキシーは421を生成できない。
  • RFC 8336はHTTP/2のORIGINフレームで接続のOrigin Setを事前に伝え、対応クライアントに421後の集合更新を求めた。QUIC上のHTTP/3も421を残したため、問題の本体はTCPではなく、共有接続の効率とオリジン権威の境界にある。

同じ入口に着いたことは、同じ窓口を選んだことではない

クライアントは、あるサイトのために暗号化接続をすでに確立している。次に必要になった資源は別の名前を持つが、その名前は同じIPアドレスへ解決され、接続相手の証明書にも含まれている。新しい接続を作らず、既存のものへ要求を載せる判断には十分な根拠がある。

HTTP/2なら一本の接続上で複数のストリームを同時に進められる。新たなTCPとTLSの確立を省くだけでなく、接続を共有すること自体が設計上の利点だった。

しかし、外から見える入口と、内部で選ばれた窓口は同じではない。最初のTLS握手で送られたSNIが、特定のテナント、ポート方針、TLS終端装置、あるいはバックエンド群を選んでいることがある。証明書は二つの名前を正しく認証できても、最初の名前で開いた接続が第二の名前のサービスへ配線されているとは限らない。

第二のオリジンは、自分の名前をSNIにした新しい接続なら正常に応答できるかもしれない。壊れているのは接続でもオリジンでもなく、両者を結んだ推論である。421は、その一本の辺だけを拒否するために生まれた。

Hostは要求先を明示したが、応答者を任命しなかった

HTTPは以前から、ネットワークの宛先と名前付き資源空間を区別してきた。多数のウェブサイトが同じIPアドレスを共有すると、TCPの宛先だけではどのサイトを求めているか分からない。HTTP/1.1はHostを必須にし、HTTP/2とHTTP/3では通常:authorityが同じ意図を運ぶ。

これでクライアントは「どのオリジンを求めるか」を明示できた。だが、受信側が答えるべき別の問いは残った。「このオリジンは、このサービスと、この接続の文脈で構成されているか」である。

現行のHTTPセマンティクス、RFC 9110は両方を要求する。対象URIのホストとポートは、サーバーが管理し得る複数の名前空間を区別する。サーバーは対象を特定した後も、自ら処理するか、転送するか、リダイレクトするか、拒否するかを決め、スキーム固有の条件と接続コンテキストを検査しなければならない。

Hostはクライアントの意図を伝える。ソケットの向こう側にいるすべてのプロセスへ、その名前を代表する権限を与えるものではない。

HTTP/2は再利用の価値と推論の幅を広げた

2015年5月に公開された初代HTTP/2仕様のRFC 7540は、持続接続と多重化を中心に据えた。オリジンサーバーが権威を持つと判断できるなら、一つの接続を、URIのオーソリティー部分が異なる要求にも再利用できた。

TLSを使わないTCPでは、新しいホストが同じIPアドレスに解決されることが条件になった。HTTPSではさらに、そのホストについて新規接続時に行うはずの検査を、提示済み証明書が通過する必要があった。複数のsubjectAltNameや適用可能なワイルドカードによって、一枚の証明書が複数オリジンの認証根拠になり得た。

これは無差別な共有ではない。クライアントが観測できる名前解決と暗号学的身元を用いた、合理的な境界である。ただし、受信設備の内部選択までは観測できない。

RFC 7540は、TLS終端装置がSNIに基づいてオリジンサーバーを選ぶ例を挙げた。同じ証明書に含まれる別名への要求を既存接続で送ると、設備全体としてはその名前を扱えても、当初選ばれた内部コンテキストは扱えない場合がある。

クライアントの判断が不注意だったのではない。利用できる証拠だけでは、最後の一段を知れなかったのである。

421は対象ではなく組み合わせを退けた

RFC 7540が導入した421 Misdirected Requestの現行定義は、HTTP/2固有文書ではなくRFC 9110に置かれている。サーバーが対象URIについて権威ある応答を生成できない、または生成する意思がないことを示す。

対象がサーバーに設定されたオリジンと一致しない場合もあれば、要求を受け取った接続コンテキストと一致しない場合もある。

421は資源の消滅を告げない。別URIへ移ったとも言わない。要求が不正な文法だとも言わない。その接続から、そのオリジンを代表して答えることを拒否する。

この判断を出せるのはオリジンサーバー、またはオリジンを代表して動作するゲートウェイである。RFC 9110は、プロキシーが421を生成することを禁じる。途中の転送者が同じ判断を作れるなら、クライアントはオリジンの権威境界による拒否と、単なる経路上の都合を区別できない。

否定的証拠にも出所が必要である。

到達性、資格証明、文脈受容を分ける

421が必要になるのは、三つの命題を一つに短絡しやすいからだ。

第一は到達性。この接続はあるエンドポイントに着いている。第二は資格証明の範囲。そのエンドポイントは、対象オリジンについてクライアントが受け入れる証明書を提示した。第三は文脈受容。受信側の構成が、この特定接続上でそのオリジンの権威ある応答を生成でき、そうする意思がある。

第一と第二は再利用を試す根拠になる。第三を強制する根拠にはならない。証明書は、受け入れ可能な秘密鍵と名前の関係を示す。すべての名前が同じテナント、アプリケーション、ポート、バックエンド、運用主体を共有するとは証明しない。

逆に421を受けても、第一と第二が偽になったわけではない。同じ接続が別のオリジンへ使え、同じ証明書が新しい専用接続で有効なこともある。

421は、各証拠をその証明範囲にとどめる小さな拒否権である。

再試行は要求の意味ではなく配達経路を変えた

RFC 9110は、421を受けたクライアントが別の接続で要求を再試行できると定める。対象オリジン専用の新しい接続でも、適切な代替サービスでもよい。メソッドが冪等かどうかを問わない。

ここから「非冪等要求は障害後にいつでも再送できる」と一般化してはならない。421は、応答者が現在の文脈で対象オリジンの権威ある応答を生成することを拒否した、型の付いた結果である。別接続は、不明な実行結果の後で業務操作を繰り返すためではなく、正しいサービス文脈へ配達し直すために選ばれる。

それでも規定は義務ではない。要求本文を再現できない、資格情報が接続に束縛されている、危険な操作には確認が必要、といった理由でクライアントは停止できる。

重要なのは条件が変わることだ。同じ共有接続で上限なく送り直しても修復にはならない。新しい接続は、同じIPと同じ証明書に到達する場合でも、対象名をSNIに載せ、別の前段規則やバックエンドを選び得る。

URIと操作は保ち、接続コンテキストだけを再評価する。

リダイレクトとは異なる

リダイレクトは別の対象を提案し、通常はLocationによって次のURIを変える。421は代替URIを提示しない。資源が移動したとも主張しない。

421をリダイレクトのように扱うと、資格情報の送信範囲、キャッシュキー、監査上の対象を勝手に変えてしまう。内部経路の不一致を、技術的な別名への移転で隠すことにもなる。

また、構文が正しい要求でも421になり得るので400 Bad Requestではない。利用者の資源アクセス権が中心ではないので403 Forbiddenでもない。TLSの証明書検証が成功したからこそ接続が再利用された可能性があり、TLSエラーとも限らない。

狭い状態コードは、問題の所在を狭く保つ。

ORIGINは失敗前に意図を伝えた

421による反応的な修正には遅延がある。要求を送り、拒否を受け、別接続を選ぶからだ。2018年3月のRFC 8336は、サーバーが接続を利用できるオリジンを事前に示すHTTP/2のORIGINフレームを定義した。

接続ごとの集合はOrigin Setと呼ばれる。集合が初期化されると、対応クライアントは、そこにないオリジンについて接続が権威を持つと考えてはならない。ORIGINの項目にはワイルドカードが使えない。ワイルドカード証明書の範囲が、そのまま無制限の運用宣言になることはない。

フレームは一本の接続の属性を表すため、ホップごとに処理される。中継者は転送せず、プロキシーを使うクライアントはそのプロキシーからのORIGINを無視する。集合に名前が入っても、証明書検証はなお必要である。ORIGINは意図の信号であって資格証明ではない。

さらに、対応クライアントは421を受けると、当該オリジンをその接続のOrigin Setから削除する。失敗は一回限りの画面表示ではなく、次の経路選択を改善する局所的知識になる。

オリジン全体を無効にすれば学び過ぎ、何も記憶しなければ同じ誤りを繰り返す。正しい範囲はオリジンと接続の組である。

Alt-Svcは別経路を示しても、権威を自己証明しない

Alt-Svcは、別のホスト、ポート、プロトコルのサービスをオリジンの代替として知らせる。421後の再試行先になり得るが、それだけで権威が成立するわけではない。

RFC 8336によれば、代替サービスの広告はOrigin Setを変更しない。DNSは到達先の証拠、証明書は身元の証拠、Alt-Svcは代替候補、ORIGINは接続の利用意図を示す。それぞれの主張は異なる。

一つの信号が他のすべてを証明するなら、運用は循環的な自己承認になる。最終的な組み合わせを受信側が拒否できることが、薄い信号同士の協力を可能にする。

HTTP/3は輸送を変えて421を残した

現行HTTP/2仕様のRFC 9113はRFC 7540を置き換えたが、オリジン間の接続再利用と421を維持した。RFC 9114のHTTP/3も同じ境界をQUIC上へ持ち込んだ。

HTTP/3接続も持続的で、複数のURIオーソリティーに再利用できる。新しいオリジンへ使う前に、クライアントは証明書をそのオリジンについて検証しなければならない。証明書が受け入れられなければ再利用は禁止される。受け入れられても、サーバーは特定オリジンについてその接続の利用を望まない場合、421を返せる。

421はHTTP/2固有のコードとして生まれ、一般HTTPセマンティクスへ移り、HTTP/3でも使われた。これは問題がTCPや一つのフレーム形式に閉じていない証拠である。

複数の名前が効率のために一つのチャネルを共有できる限り、チャネルの成立と応答権威の成立を分ける必要がある。

観測すべきはエラー数ではなく拒否された辺

421の総数だけでは原因を説明できない。対象のスキーム、ホスト、ポート、メソッド、HTTP版、接続とストリームの識別子、遠隔端点、SNI、ALPN、証明書の名前集合、再利用判断に使ったDNS結果、Alt-Svcの出所、Origin Set、選ばれたフロントエンドとバックエンド、421発行者の役割、再試行先と結果を結び付ける必要がある。

共有接続だけが421になり、オリジン専用の新規接続が成功するなら、接続コンテキスト選択が第一の説明になる。両方が421なら、オリジン自体の設定が広く欠けているかもしれない。特定地域だけなら、証明書、広告、バックエンドの反映時刻を比較するべきだ。

一度の421は健全な補正にもなり得る。条件を変えても収束しない反復が警告である。

共有は効率の選択であり、統治権ではない

接続の併合には明確な利益がある。握手と状態を減らし、多数の要求を並行して運べる。421は一オリジン一接続を要求せず、すべての拒否を攻撃と見なさない。

クライアントは手持ちの証拠から暫定的な性能判断を行う。受信側はSNI、テナント、ポート、バックエンドという局所事実から、その判断を限定的に拒否する。要求の意味を変えずに別の文脈を選べるから、両者の知識差が破壊的にならない。

拒否手段がなければ、最初の接続が、証明書に含まれるすべての名前への事実上の支配権を持ちかねない。輸送の節約がサービス権威の集中へ変わる。

現在のIANA HTTPステータスコード登録簿は、421をMisdirected Requestとして登録し、RFC 9110を参照している。登録が固定するのは相互運用可能な名称と参照先であり、利用頻度、全クライアントの再試行、個別運用の正しさを証明するものではない。

接続は実在した。第二のオリジンも実在した。その接続が第二のオリジンを代表するという委任だけが存在しなかった。421は、その不在を正確に記録した。