複数のIPがチェーンされているときにX-Forwarded-Forの問題を解決する鍵は、最近導入された構成オプションreal_ip_recursive
(nginx 1.2.1および1.3.0で追加)であると思います。nginxのrealipドキュメント:
再帰検索が有効になっている場合、信頼できるアドレスの1つと一致する元のクライアントアドレスは、要求ヘッダーフィールドで送信された最後の信頼できないアドレスに置き換えられます。
デフォルトでは、nginxはチェーン内の最後のIPアドレスを取得していました。これは信頼できると想定された唯一のIPアドレスだったからです。ただし、新しいオプションをreal_ip_recursive
有効にして複数のset_real_ip_from
オプションを使用すると、複数の信頼されたプロキシを定義でき、最後の信頼されていないIPを取得します。
たとえば、この設定では:
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
X-Forwarded-Forヘッダーにより、次の結果が得られます。
X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1
nginxは、クライアントのIPアドレスとして123.123.123.123を選択します。
nginxが左端のIPアドレスを選択するだけでなく、信頼できるプロキシを明示的に定義する必要があるのは、簡単なIPスプーフィングを防ぐためです。
クライアントの実際のIPアドレスがであるとしましょう123.123.123.123
。また、クライアントは役に立たず、IPアドレスを偽装しようとしているとします11.11.11.11
。彼らは、このヘッダーを既に配置した状態でサーバーにリクエストを送信します。
X-Forwarded-For: 11.11.11.11
リバースプロキシはこのX-Forwarded-Forチェーンに単にIPを追加するだけなので、nginxが到達すると、次のようになります。
X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1
一番左のアドレスを取得するだけで、クライアントはIPアドレスを簡単にスプーフィングできます。しかし、上記の例のnginx configでは、nginxは最後の2つのアドレスのみをプロキシとして信頼します。これは123.123.123.123
、その偽装されたIPが実際に一番左にあるにもかかわらず、nginxがIPアドレスとして正しく選択することを意味します。