9

Linux サーバー上の Apache (2.2.14) で実行されている PHP (PHP 5.3.2) アプリケーションがあります。その歴史の中で、ユーザーはブラウザーに次のメッセージを表示し始めました:「要求エンティティが大きすぎます」。最初の Google 検索では、アップロードされたファイルが大きすぎるか、Cookie が大きすぎる場合に発生することが示唆されました。ただし、ファイルのアップロードでは発生せず、ログイン時のみで、常にログインページで発生します。ユーザーは、ページ上の通常の POST フォームからこのページに入ります。CookieにはセッションIDのみが含まれています。

さらに、apache は「Invalid Content-Length」をログに記録しています。これは、コードが実行される前にログに記録されています。$_POST にはデータが含まれているはずですが、空です。次の行を追加したとき:

error_log("Content-Length: ".$_SERVER['CONTENT_LENGTH']);

それは言う

Content-Length: 32, 32

これは実際には無効のようです。ブラウザを変更したり、ユーザーの PC をリセットしたりしても、解決しないようです。翌日、すべてが機能し始めました。

問題はどこにあるのでしょうか? Apache、PHP、ユーザーのネットワーク設定で何か?さらに情報を追加する必要がある場合は、お知らせください。

4

2 に答える 2

5

過去数日間、Apache によって error_log に記録された「Invalid Content-Length」メッセージに遭遇しました。Movistar Argentina: 200.81.44.201 など、いくつかの特定の IP クラスからの一部の訪問者に問題を追跡しました。

ヘッダーの重複、つまり Content-Length と Content-Type

実際の問題は Content-Length にあります。Apache は複数の変数を連結して扱うためです。次に例を示します。

Content-Length: 51
Content-Length: 51

結果は次のようになります。

Content-Length: 51, 51

次に、Apache は文字列 "51, 51" を整数に変換しようとしますが、これは不可能です。新しい Apache > 2.2.17、またはバックポートされたパッチを使用すると、Apache はエラーをログに記録します: 413 要求エンティティが大きすぎます。古い Apache では、多くの CPU 時間を消費してプロセスがハングします。その IP クラスの背後には、より明確なクライアントが表示されます。そのヘッダーが複製されているため、3G ゲートウェイ プロキシ サーバーが正しく構成されていない可能性があります。そこで、1 つの Content-Length ヘッダーと 1 つの Content-Type ヘッダーだけでリクエストを書き換えるように Apache を構成するソリューションを見つけます。

SetEnvIfNoCase Content-Length (.*), MyContentLength=$1
SetEnvIfNoCase Content-Type (.*), MyContentType=$1
RequestHeader set Content-Length: "%{MyContentLength}e" env=MyContentLength
RequestHeader set Content-Type: "%{MyContentType}e" env=MyContentType

重複する Content-Length HTTP ヘッダー変数を除外するために、このコードを自由にテストして使用できます。

于 2013-01-23T13:18:54.887 に答える
2

このような問題を調査する最も簡単な方法は、TCPDump を使用てクライアントとサーバー間で送信されるパケットをファイルにキャプチャし、次にWiresharkを使用してパケットを TCP ストリームとして表示することです。

パケットをキャプチャするコマンドの例は次のとおりです。

tcpdump -vvv -A -i eth0 'ホスト 123.123.10.12 && ポート 80' -w eth0.dat

これはログイン ページであるため、HTTPS の背後にある必要があるため、おそらく TCP ストリームをデコードする必要があります。これはhttp://segfault.in/2010/11/decrypt-https-traffic-using- wireshark-and-key-file/

ただし、Plasmid87 はほぼ確実に正しいです。ヘッダーの 1 つが大量に成長し、最終的に Apache LimitRequestFieldSize よりも大きくなっているようです。

一度にすべてではなくゆっくりと成長している限り、グローバル変数をチェックして調査できます。

function checkVars(){
    $varsToCheck = array($GLOBALS, $_SERVER, $_GET, $_POST, $_FILES, $_REQUEST, $_SESSION, $_ENV, $_COOKIE);

    foreach($varToCheck as $var){
        foreach($var as $key => $value){

            if(count($key) > 1024){
                logToFile("Found ridiculous key: ".$key." value is ".$value);
            }
            if(count($value) > 1024){
                logToFile("Found ridiculous value for key: ".$key." value is ".$value);
            }
        }
    }
}
于 2012-12-10T00:51:05.210 に答える