X-Forwarded-Forヘッダ、略してXFFってありますよね。リバースプロキシなどWebアクセスを中継するサーバーが、本当のアクセス元IPをバックエンドのWebサーバーへ渡すためのHTTPリクエストヘッダです。
その仕組みと「正しい」運用の仕方については以前職場のテックブログにまとめたものがありますので、興味のある方は読んでみてくださいませ。
こんばんは、X-Forwarded-For警察です - エムスリーテックブログ
問題は、どの記述を信用していいのか
上でリンクした記事にも書いたとおりですが、XFFを解釈するときの問題はどのサーバーが付けてきたXFF記述を信用するかです。誰が書いたものでも信用してしまうと容易にアクセス元偽装ができてしまうから。
それで、上の記事にもある通り「信用できるサーバーのIPアドレスはこれとこれ」みたいに、解釈する側で信用できる人たちリストを保守していくことが必要になっています。
あれ、信用を担保するには署名って道具があったのでは?
でも、IPアドレス単位でサーバーの信用を判断するというのは、いろいろとおかしいです。
まず、運用上大変。サーバーのIPアドレスが変わってしまうことはいろいろな理由でありえて、そのたびにXFF信用リスト持ってるすべてWebサーバーで信用リストを漏れなく間違いなく更新するのはたぶん回りません。漏れれば、あっという間にセキュリティホールです。
そして、堅さ。同じサーバー内にもいろんなプロセスが走ってます。当然、悪意あるプロセスが立ち上がってしまったときのことを考えないといけません。IPアドレス単位ですべてのプロセスを信用してしまうというのは、普通にセキュリティの穴ってことです。
そして、記述の信用を担保する道具はもっと一般的なものがありましたよね。電子署名です。
つまり、XFFではなくて、こんなヘッダが定義されていれば運用も簡単、セキュリティも堅牢だったはずなのです。
X-Real-Ip-Signed: 10.1.1.1; signature=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
リバースプロキシ(プロセス)やLB(プロセス)はもってる公開鍵で署名を付けて、リクエストを受け取るWebサーバ側が秘密鍵を持って署名を検証するという枠組み。多段プロキシだと、X-Real-Ip-Signedが付いていてそれが署名OKなら何も付け加えません(署名NGなら自分でX-Real-Ip-Signedを上書き)。