HTTPヘッダーX-Forwarded-For
のウィキペディアの説明は次のとおりです。
X-Forwarded-For:client1、proxy1、proxy2、...
ディレクティブreal_ip_header
のnginxドキュメンテーションは、一部を読み取ります:
このディレクティブは、置換IPアドレスの転送に使用されるヘッダーの名前を設定します。
X-Forwarded-Forの場合、このモジュールはX-Forwarded-Forヘッダーのlast ipを使用して置換します。 【エンファシス鉱山】
これらの2つの説明は互いに矛盾しているように見えます。このシナリオでは、X-Forwarded-For
ヘッダーは説明どおりです-クライアントの「実際の」IPアドレスが左端のエントリです。同様に、nginxの動作はright-most値を使用することです。これは明らかに、プロキシサーバーの1つにすぎません。
X-Real-IP
についての私の理解は、仮定が実際のクライアントIPアドレスを決定するために使用される-プロキシではありません。私は何かが足りないのですか、これはnginxのバグですか?
さらに、X-Real-IP
の定義で示されているように、X-Forwarded-For
ヘッダーにleft-most値を表示させる方法についての提案はありますか?
複数のIPがチェーンされている場合にX-Forwarded-Forの問題を解決するための鍵は、最近導入された構成オプションreal_ip_recursive
(nginx 1.2.1および1.3.0で追加)であると思います。 nginx realip docs から:
再帰検索が有効になっている場合、信頼できるアドレスの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構成では、nginxはプロキシとして最後の2つのアドレスのみを信頼します。つまり、スプーフィングされたIPが実際に一番左にあるにもかかわらず、nginxは123.123.123.123
をIPアドレスとして正しく選択します。
X-Forwarded-For
ヘッダーの解析は、nginx real_ipモジュールに実際に欠陥があります。
len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;
for (p = ip + len - 1; p > ip; p--) {
if (*p == ' ' || *p == ',') {
p++;
len -= p - ip;
ip = p;
break;
}
}
ヘッダー文字列の右端から始まり、スペースまたはカンマが見つかるとすぐに検索を停止し、IP変数のスペースまたはカンマの右側にパーツを貼り付けます。したがって、最新プロキシアドレスを元のクライアントアドレスとして扱います。
仕様によるとニースではありません。これは、RFCで苦痛に明白な用語で綴られていないことの危険です。
余談:Squidによって最初に定義された形式の適切なプライマリソースを見つけることさえ困難です- ドキュメント は注文を確認します。左端は元のクライアント、右端は最新の追加です。そのウィキペディアのページに[引用が必要]を追加したくてたまらない。 1つ anonymous edit は、この件に関するインターネットの権限のようです。
可能であれば、中間プロキシがヘッダーの最後に自分自身を追加するのを止めて、実際のクライアントアドレスのみを残すことができますか?
X-Real-IPは、サーバーが通信している実際のクライアント(サーバーの「実際の」クライアント)のIPアドレスであり、プロキシ接続の場合はプロキシサーバーです。これが、X-Real-IPがX-Forwarded-Forヘッダーの最後のIPを含む理由です。
答えより警告の方が多い...
私のメインサーバー(データソース)が既にローカルで実行されているNginxキャッシュサーバーの背後にあることを認識せずに、複数のマップの場所にいくつかのNginxキャッシュサーバーを追加しようとしました 、ローカルサーバーがApacheを実行するように構成されている場合があり、Nginxがその前に置かれてキャッシュとして機能します。
2つ目の別のNginxキャッシュサーバーを追加すると、キャッシュサーバーが2つになるため、HTTP_X_REAL_IP
またはHTTP_X_FORWARDED_FOR
が正しく表示されず、訪問者のIPではなくサーバーのIPが1つ表示されます。
私の場合、新しいキャッシュサーバーを設定して、ソース/メインサーバーのローカルNginxキャッシュをバイパスし、Apacheポート(私の場合はポート7080)から直接データを取得するように設定しました。
別の解決策は、ローカルキャッシュサーバーでHTTP_X_REAL_IP
を削除することです。
ところでPleskパネルを実行していました。