ソケットのピアか転送ヘッダーか:どのアドレスを信頼すべきか
ソケットのピアと転送ヘッダーは別種の証拠です。それぞれが何を証明するかを比較し、転送ヘッダーは自分が管理するプロキシ経由でのみ信頼してください。
アプリケーションに届くリクエストは、アドレスに関する二種類の証拠を運びます。ネットワーク接続を開いたピアと、以前のクライアントのアドレスを主張する HTTP フィールドです。両者は別の問いに答えます。ソケットのピアは観測される事実であり、ヘッダーはそれを書いた者が主張するものにすぎず、どちらもログやアクセス規則の中で他方を黙って置き換えるべきではありません。以下の比較は両者を切り離し、そのうえでヘッダーが使えるようになる唯一の構成を示します。
何かを比較する前に、経路を記述してください:
Client -> approved reverse proxy -> application originその構成では、オリジンのソケットのピアは通常プロキシであり、転送ヘッダーはプロキシによるクライアントについての主張を運べます。その価値はヘッダーの名前からではなく、そのプロキシとの管理された関係から生まれます。
アドレスに関する二種類の証拠
ソケットのピアは一つの TCP 接続についての事実です。何かがそのアドレスからハンドシェイクを完了しました。それは必ずしもあなたが気にかける人間や端末やアカウントではなく、VPN や Tor の出口がサービスから見える送信元になることも正当にあり得ます。それでもホスト自身が検証した唯一のアドレスであり、価値はそこに尽きます。
転送フィールドは連鎖についてのメタデータです。X-Forwarded-For、X-Real-IP および標準化された Forwarded フィールドは、それらを反映するエンドポイントに到達したどのクライアントでも書けるため、信頼性は誰に設定を許したかに完全に依存します。
両方を要求コンテキストに別々の名前で保持してください。ピアをヘッダーで上書きするアプリケーションは、後から信頼の誤りを再構成する能力を失います。それはまさに必要になる瞬間です。
ヘッダーが接続の経路を変えることはない
転送フィールドにアドレスを書いても、サーバーに届く TCP 接続の送信元は変わらず、経路上のどこでもルーティングは変わりません。通常の VPN ルーティングや 送信元 NAT は HTTP ヘッダーを一切使わずに通信を届けます。同様に、通過ゲートウェイは TLS 端点の構成を変えずに、適切に保護された HTTPS のやり取りを書き換えることはありません。
逆の誤りも同じくらいよくあります。HTTPS はクライアントが提供した転送ヘッダーを真実にはしません。偽の主張の輸送を、真の主張とまったく同じように保護するだけです。
同僚がルーティングの問題を直すためにヘッダーの変更を提案するなら、診断はすでに間違っています。経路を直すか、ヘッダーを書くプロキシの設定を直してください。
主張を許されたプロキシに名前を付ける
転送フィールドを使えるようにする規則は二つあり、どちらもコードではなく設定です。境界は外から届くものを、そのフィールドについての自身の文書化された振る舞いに従って正規化するか破棄します。次にオリジンは、名付けたプロキシ経路からのみ代替アドレスを取ります。二つ目の規則は、クライアントが別の方法でオリジンに到達できない間だけ成り立ちます。直接の要求とプロキシ経由の要求の両方に答えるオリジンは、どちらを扱っているのか分からないからです。
NGINX の実 IP モジュール はその分割を明確に示します。set_real_ip_from は主張が意味を持つ送信者を名指しし、real_ip_header はどのフィールドがそれを運ぶかを示します。前者が信頼を行い、後者はどこを見るかだけを告げます。
set_real_ip_from 10.20.0.0/24;
real_ip_header X-Forwarded-For;
# real_ip_recursive off - take the rightmost value in the field
# real_ip_recursive on - walk the list back past every trusted address
ヘッダー選択の指示だけでは、値を送ったのが誰かについては何も確立しません。
輸送の安全性は、信頼する構成要素の間の全経路で働かなければなりません。正しく正規化する境界も、下流の保護されていない区間が移動中の主張を他人に編集させる瞬間に、その価値を失います。
多段の連鎖を意図的に扱う
複数のプロキシには明示的な連鎖モデルが必要です。ブログ記事がそうしたからといって、カンマ区切りの左端や右端の値を取ってはいけません。自分のプロキシのどれが追加し、どれが置換し、どれが受信フィールドを保存するのかを突き止めてください。たとえば NGINX は、信頼する集合に対して一覧を後ろ向きにたどり、所有しない最初のアドレスで止まることができますが、それはその製品の規則であり、すべてのフレームワークが従う法則ではありません。自分のプロキシの文書を同じ二つの問いで読んでください。どの値を選び、どの送信者を信じるのか。
連鎖を書き留めてください。区間の順序、どの区間がフィールドを設定し、どの区間が受信した複製を削除するかです。そのうえでそのメモを、チケットだけでなくプロキシの設定の隣に置いてください。次に、承認された検証手順を通して偽のヘッダー付きの要求を送り、オリジンがそれを無視することを確認して試験します。
区間を追加したら、その文書を見直してください。信頼するプロキシの前に挿入された新しいロードバランサーは、誰もアプリケーションを編集しないまま、どのアドレスが勝つかを変え得ます。
両方の観測をログに残す
診断が許可されている場所では、接続のピアと正規化されたクライアントアドレスを二つの別々のフィールドとして記録し、目的が本当に必要とする転送メタデータだけを加えてください。次に二つの要求で配備を証明します。両方の値を妥当に記録すべきプロキシ経由の要求と、拒否されるべきオリジンへの直接の試行です。
この対が何を意味するかを忘れないでください。ヘッダーは、信頼すると選んだ構成要素が提供する文脈を加えます。ピアは、あなたのホストが実際に見た唯一のアドレスのままです。どちらも個人の身元の証明ではなく、どちらかを証明として扱う設計は、誰かについて誤ります。