代表的な面接トピック

バックエンド面接:プロキシチェーン全体でHTTP 407をどのように処理するか?

バックエンド難しい
Offer.cc 編集チーム公開日 更新日

質問

リクエストがエンタープライズプロキシ、リージョナルゲートウェイ、エグレスプロキシを経由する際、407を返すものと401を返すものがあります。認証情報の漏洩や副作用の重複を起こさずに、どのホップがチャレンジを返しているかを特定し、リトライするにはどうすればよいですか?

プロンプトとスコープ

サービスクライアントが複数の明示的プロキシを経由して外部APIにアクセスしています。一部のリクエストは407を返し、他のリクエストは401を返します。両者の境界、ホップバイホップのプロキシチャレンジ、CONNECTトンネル、認証情報の保存、リトライ、可観測性について説明してください。

これはバックエンドのネットワーキングおよびセキュリティに関する質問です。プロキシの数と失敗率は演習のための前提条件であり、市場の主張ではありません。

面接官がテストしていること

  • リソースサーバー認証と次ホッププロキシ認証を区別できているか。
  • Proxy-AuthenticateProxy-Authorization がどこで消費されるかを説明できるか。
  • マルチホップ、CONNECT、コネクションプール、認証情報のローテーションを処理できるか。
  • プロキシの認証情報がオリジンやログから隔離されているか。

行うべき確認のための質問

  1. クライアントは明示的プロキシと透過的プロキシのどちらを使用していますか?また、CONNECTは関与していますか?
  2. 各プロキシはどのスキームを使用しており、接続は再利用されますか?
  3. クライアントとゲートウェイは元の401および407ヘッダーを保持できますか?
  4. リクエストは安全な読み取りですか、それとも状態の作成、課金、変更を伴いますか?
  5. 誰が認証情報をローテーションし、バックアップのエグレスは利用可能ですか?

30秒での回答

「407は次ホッププロキシからのチャレンジであり、401はターゲットリソースからのものです。私はホップ識別子とリクエスト識別子を記録し、Proxy-Authenticate を読み取って、一致する Proxy-Authorization をそのプロキシにのみ送信します。これは次のインバウンドプロキシによって消費され、オリジンに到達してはなりません。CONNECTの場合、トンネルを作成する前にプロキシを認証し、トンネルレベルの401はオリジン認証として処理します。リプレイしても安全なリクエストのみをリトライし、プロキシ、スキーム、認証情報のバージョンごとに407を測定します。」

ステップバイステップの設計

1. 401と407の分離

401内の WWW-Authenticate はターゲットリソースのチャレンジを示し、通常は Authorization で応答されます。407内の Proxy-Authenticate は次ホッププロキシからのチャレンジを示し、Proxy-Authorization で応答されます。ステータス番号が類似しているからといって、共有キャッシュや単一のエラーハンドラーを使用するべきではありません。

2. 1ホップずつの認証

各プロキシは、自身が要求した認証情報のみを受信します。RFC 9110は、それを要求した次のインバウンドプロキシ向けに Proxy-Authorization を定義しています。チェーン内では、認証情報を要求した最初のプロキシがそのフィールドを消費します。クライアントはプロキシまたは接続ごとに認証情報を分離し、プロキシヘッダーをオリジンに転送することはありません。

http
GET https://api.example/report HTTP/1.1
Host: api.example
Proxy-Authorization: Basic <proxy-credential>

3. CONNECTトンネルの処理

HTTPSターゲットの場合、クライアントはまずプロキシにCONNECTを送信します。プロキシ認証が成功し、プロキシが2xxを返した後に、クライアントはTLSトンネルを作成します。トンネル内のリクエストはオリジンに属します。オリジンの401は Authorization を使用し、プロキシの407と混同されません。失敗したプロキシチャレンジは、依然としてCONNECTホップに属します。

4. プールと認証情報の分離

プールキーには、プロキシアドレス、認証スキーム、テナント、認証情報バージョンを含めます。ローテーション中は、古い接続の再利用を停止するか、プロキシの要求に応じて再認証します。Proxy-Authorization をリクエスト間で共有されるヘッダーテンプレートに配置したり、その値をトレーシングシステムに記録したりしないでください。

5. リトライと副作用の制限

407の後は、元に戻せないボディが送信されていない場合、または操作が安全にリプレイ可能な場合にのみリトライします。POST、課金、リソース作成の場合は、ビジネスの冪等性キーを使用し、サーバーがその試行をすでに処理したかどうかを確認します。チャレンジ処理、認証情報の更新、リプレイは、際限のないループではなく、観測可能なイベントにする必要があります。

6. 診断と安全性の計測

ホップごとに、プロキシ識別情報、CONNECTフェーズ、スキーム、認証情報バージョン、407カウント、リトライ結果、最終ステータスを記録し、秘匿化(マスキング)されたサマリーのみを保持します。401、407、TLS障害、プールの再利用、バックアップエグレスへの切り替えを比較して、ターゲット、プロキシポリシー、またはローテーションの障害を特定します。障害を注入して、仲介者がオリジンの認可ヘッダーを漏洩したり書き換えたりできないことを証明します。

質の高い模範回答

「私はパスをプロキシ層とリソース層に分割します。次のプロキシは407でチャレンジし、オリジンは401でチャレンジします。これらにはそれぞれ Proxy-AuthorizationAuthorization を使用します。認証情報はプロキシ識別情報によって分離されます。プロキシフィールドを要求する最初のインバウンドプロキシがそれを消費し、オリジンに到達することはありません。HTTPSでは、トンネルトラフィックの前にCONNECT中にプロキシを認証します。プールはプロキシと認証情報バージョンごとに分離され、ローテーションによって古い接続は破棄されます。407の後にリプレイされるのは安全なリクエストのみです。副作用は冪等性とステータスクエリによって回復します。ホップレベルのメトリクスによって障害を特定します。」

よくある間違い

  • 407を401として扱う → 認証情報が誤った境界を越える → プロキシとリソースのチャレンジを個別に処理する。
  • プロキシの認証情報をオリジンに転送する → シークレットが漏洩する → 次のインバウンドプロキシに消費および削除させる。
  • CONNECTが成功する前にトンネルトラフィックを送信する → プロトコル状態が不正になる → プロキシ認証を完了し、まず2xx CONNECTを受信する。
  • すべての接続認証状態を共有する → テナントまたは認証情報バージョンが混同する → プロキシ、テナント、バージョンごとに分離する。
  • 407を無限にリトライする → 障害と副作用が増幅する → 試行回数を制限し、リプレイの安全性をテストし、状態をクエリする。

フォローアップの質問と回答

複数のプロキシに対して複数のProxy-Authorizationの値を送信できますか?

そのフィールドを汎用的な認証情報リストとして扱ってはいけません。現在のインバウンドプロキシが期待するものを送信してください。そのプロキシがフィールドを消費した後は、そのホップのスキームに従って以降のチャレンジを処理し、実装が安全な転送を許可していることを確認してください。

最後の407だけで診断してはいけない理由は?

ゲートウェイが中間のレスポンスを書き換えたり握りつぶしたりする可能性があり、接続の再利用によってチャレンジが誤ったリクエストに関連付けられることがあります。実際の発行者を特定するために、ホップログ、接続識別子、および元のチャレンジを保持してください。

プロキシ認証は成功したがトンネルが401を返した場合はどうなりますか?

プロキシ認証状態を維持し、オリジンの WWW-Authenticate チャレンジに対して Authorization で応答します。プロキシ認証情報を再送信したり、リソース認証情報をプロキシ認証キャッシュに配置したりしないでください。

公開情報ソース

関連する質問