mod_setenvif を使って Apache のログを軽量化

Amazon Search とか不特定多数のユーザ向けにサービスを公開していると、外部からの画像のアクセスがログの 60〜70% を占めていましてログ解析とかする際に、ログサイズが大きくて時間がかかるばかりでなく、ムダにサーバの disk も占有してしまいます。最近では、1週間でログサイズが 2Gbyte 超えをしてしまうので、ログ削除だけでも大変です。

そこで、Apache のログ出力を mod_setenvif でカスタマイズすることでのログ軽量化を設定する事にしました。mod_setenvif は、Base モジュールに属するためデフォルトで include されるので普通は使用可能状態だと思いますが、意図的に --disable-module している場合は再コンパイルする必要があります。

- スポンサーリンク -

Apache モジュール mod_setenvif とは?

mod_setenvif モジュールは、リクエストのある側面が指定された正規表現 に合うかどうかによって環境変数を設定する機能を提供します。 これらの環境変数を使用して、サーバの他の部分がどのような動作をするかを 決定することができます。

このモジュールが提供するディレクティブは、 設定ファイルに現れる順番に適用されます。 それを使って、次の例のようにより複雑な設定をすることができます。

mod_setenvif で使用可能なディレクティブとその説明

BrowserMatch ディレクティブ
・説明: HTTP User-Agent に基づいて環境変数を設定する ・構文: BrowserMatch regex [!]env-variable[=value] [[!]env-variable[=value]] ... ・コンテキスト: サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccess
BrowserMatch は SetEnvIf ディレクティブの 特例で、User-Agent HTTP リクエストヘッダに基づいて 環境変数を設定します。以下の 2 行の効果は同じになります。

BrowserMatchNoCase ディレクティブ

・説明: BrowserMatch の大文字小文字を区別なしバージョン

SetEnvIf ディレクティブ

・説明: リクエストの属性に基づいて環境変数を設定する
・構文: SetEnvIf attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
・コンテキスト: サーバ設定ファイル, バーチャルホスト, ディレクトリ, .htaccess

SetEnvIf ディレクティブは、リクエストの属性に基づいて環境変数を定義します。 最初の引数で指定する attribute は以下の3つです。

第1引数
HTTPリクエストヘッダ内のフィールド名。例えば Host, User-Agent, Referer, Accept-Language など。名前の大小文字は区別しません。正規表現を使うこともできます(正規表現内の大小文字は区別)。

定義済ラベル。大小文字区別なし。
・Remote_Host - リクエストを行なっているクライアントのホスト名(もしあれば)
・Remote_Addr - リクエストを行なっているクライアントの IP アドレス
・Remote_User - 認証されたユーザ名(もしあれば)
・Request_Method - 使用されているメソッド名(GET, POST など)
・Request_Protocol - リクエストが行なわれたプロトコルの名前とバージョン
 (例えば、"HTTP/0.9", "HTTP/1.1" など)
・Request_URI - URL のドメイン名部より後の部分

上記のどれにも当てはまらなければ、環境変数。ただし正規表現が使われていない場合のみ。

第2引数
Perl5 互換の正規表現を指定します。大小文字は区別されます。空白や特殊記号を含む場合はクォートで囲むのが必須です。

第3引数以降
環境変数の設定を指定します。これには「変数名のみ」「!変数名」「変数名=設定値」という3の記述方法があります。最初のものは値を TRUE にセットします。2番目はその変数を FALSE にセットします。

※設定した環境変数は、リクエスト処理の終了とともに全て初期状態に戻されます。

SetEnvIfNoCase ディレクティブ

・説明: SetEnvIf の大文字小文字を区別なしバージョン

mod_setenvif の設定方法の例

mod_setenvif の説明が終わったところで、実際の設定方法の例についていくつか例を示します。これだけ設定していれば、かなり良い感じの軽量化アクセスログになるだけでなく、悪質なアクセスもかなり除外できて良い感じになります。

gif, jpg 等の画像へのアクセスログを残さない設定

SetEnvIfNoCase Request_URI "\.(jpg|mpg|mpeg|jpeg|rm|avi|mov|aif|aiff|png|gif|swf)$" no_image
CustomLog logs/access_log combined env=!no_image

ローカル環境からのアクセスログを残さない設定

SetEnvIfNoCase REMOTE_ADDR "^(127\.0\.0\.1|10\.*\.*\.*|192\.168\.*\.*)$" no_local
CustomLog logs/access_log combined env=!no_local

悪質?な robot からのアクセスを拒否する設定

BrowserMatchNoCase (nabot|dloader|digext|openbot|archiver|crawler|spider|scooter|zyborg) bad_bot
deny from env=bad_bot

悪質な ワーム(Worm) からのアクセスを拒否する設定

SetEnvIf Request_URI "^/(mem_bin|_mem_bin|vti_bin|_vti_bin|c|d|msadc|MSADC|scripts|default\.ida|NULL\.IDA|cmd\.exe|root\.exe)" worm
deny from env=worm

- スポンサーリンク -