技林TOP > 自宅サーバ構築メモ > Webサーバログについて


≫ログとは

Webサーバは、どういうアクセスがあって、どういう返答をしたかということをログに残します。

Apacheの残すログには以下の2つがあります。
  • アクセスログ
  • エラーログ
他にも様々なログ(モジュールの動作を記録するログなど)を記録するように設定することも可能ですが代表的なものはこの2つです。

≫ログの設定

いずれも、ログの設定は httpd.conf で行います。

# アクセスログ
CustomLog /var/log/httpd/axs_log combined


# エラーログ
ErrorLog /var/log/httpd/error_log


/var/log/httpd/axs_log/var/log/httpd/error_log がログを保存する場所を示しています。

アクセスログの方は combined という引数は、ログの形式を示しています。
ログの形式は以下の様に指定します。

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common


combined形式とcommon形式は代表的なWebサーバログのフォーマットです。

# ログを記録するレベル
LogLevel warn


エラーログに記録するレベルを設定します。
程度の低いものから debug, info, notice, warn, error, crit, alert, emerg という段階があります。
デフォルトは warn です。

≫logrotate

ログはそのままにしておくと、どんどん肥大化していきます。
そこで、ログを一定期間で世代分け(ローテート)させることにします。

世代分けを行ってくれるのは、logrotate です。
定期的に logrotate を実行するために cron と組み合わせます。

logrotate の設定は /etc/logrotate.conf で行います。


/etc/logrotate.conf の中身は以下の感じ
# 詳しくは "man logrotate"

# グローバルな設定
# ローテートの間隔(monthly,weekly,daily)
daily

# 何世代まで保存するか
rotate 7

# エラーがあれば root 宛てにメールする
errors root

# ローテート処理後すぐに同名のログファイルを作成する
create

# ログファイルを圧縮(する:compress しない:nocompress)
#compress

# logrotateの設定ファイルの位置 
include /etc/logrotate.d

# /var/log/wtmp をローテートする設定
/var/log/wtmp {
    monthly
    create 0664 root utmp
    rotate 1
}


Apache ログの設定ファイル(/etc/logrotate.d/apache)の中身は
/var/log/httpd/axs_log {
    postrotate
	/bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
    endscript
}
/var/log/httpd/error_log {
    postrotate
	/bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true
    endscript
}
/var/log/httpd/axs_log はローテートさせるログの場所を指します。

postrotate はローテート後にコマンドを行うということを示しており、次の行の

/bin/kill -HUP `cat /var/run/httpd.pid 2>/dev/null` 2> /dev/null || true

が実行されます。
/var/run/httpd.pid は httpd の pidファイルの位置です。
ログを世代分けした後にログファイルを見失ってログ取得に失敗しないよう再起動をかけています。

■ cron と組み合わせる

loglotate には定期的に実行する機能がありません。設定ファイルにある daily や monthly は期間が過ぎているかを判断するだけで、自身の実行サイクルを指すものではありません。

そこで、logrotate を定期的に実行するために cron を利用します。

とは言っても、/etc/cron.daily/logrotate を見ると最初から毎日実行してくれるように設定されていたりします。変更するのは実行時間くらいでしょうか。
cron の設定は webmin なんかでやると楽チンです(いや、コマンドラインが一番早いですけど)。

晴れてローテーションされるようになると、axs_log.1, axs_log.2, axs_log.3......という風に設定した世代までログを保存しつつ古くなったログは捨てられていきます。
必要なログはバックアップを取りましょう。ログの保存はサーバ管理者の基本です(と言って私もあんまりやってませんが…(´ー`))

logrotate は Apache のログに限らず、ログファイル全般に設定できる(/logrotate.d/にファイルを作るだけ)ので、なかなか重宝します。

≫Apacheのログを分ける

Apacheのログを汚すアクセスは一杯来ます。
なかでも CodeRed や Nimda はリクエストの文字列が長いのもさることながら、リクエスト数も半端ではありません。

そこで、これらウィルスのアクセスを通常のアクセスログとは別のファイルに保存するようにしましょう。

設定は httpd.conf で行います。

まず、別のログにしたいウィルスのログは以下の様なものです。
212.XXX.XXX.194 - - [13/Mar/2002:19:04:50 +0900] "GET /default.ida?NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090%u6858%ucbd3%u7801%u9090%u9090%u8190%u00c3%u0003%u8b00%u531b%u53ff%u0078%u0000%u00=a HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:18 +0900] "GET /scripts/root.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:18 +0900] "GET /MSADC/root.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:19 +0900] "GET /c/winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:19 +0900] "GET /d/winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:20 +0900] "GET /scripts/..%255c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:21 +0900] "GET /_vti_bin/..%255c../..%255c../..%255c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:25 +0900] "GET /_mem_bin/..%255c../..%255c../..%255c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:25 +0900] "GET /msadc/..%255c../..%255c../..%255c/..%c1%1c../..%c1%1c../..%c1%1c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"
212.XXX.XXX.194 - - [16/Dec/2001:06:34:26 +0900] "GET /scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir HTTP/1.0" 400 317 "-" "-"


リクエストに特徴がありますので、その条件で判断します。
SetEnvIf Request_URI "\.(ida|IDA|exe|printer|asp|dll)" no
SetEnvIf で環境変数を設定します。
この場合は Request_URI が "\.(ida|IDA|exe|printer|asp|dll)" にマッチすれば no という環境変数を設定します。

CustomLog /var/log/httpd/axs_log combined env=!no
CustomLog /var/log/httpd/no_log combined env=no
こうすることで、no という環境変数が設定されていなければ(env=!no)通常のログと判断して /var/log/httpd/axs_log に記録し、no という環境変数が設定されたログは /var/log/httpd/no_log に記録します。

ついでに、
SetEnvIf Request_URI "\.(gif|jpg|png|css|ico)$" no
という行を追加すれば、画像ファイルへのリクエストも分けられます。

SetEnvIf Remote_Addr "^192\.168\.[0-9]+\.[0-9]+$" no
というふうに、LAN内からのアクセスも分けるようにすることもできます。

ログの設定をまとめると、
#----- エラーを記録するレベル
LogLevel worn
#----- ログ形式
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
#----- 環境変数の設定
SetEnvIf Request_URI "\.(ida|IDA|exe|printer|asp|dll)" no
SetEnvIf Request_URI "\.(gif|jpg|png|css|ico)$" no
SetEnvIf Remote_Addr "^192\.168\.[0-9]+\.[0-9]+$" no
#----- ログファイルの位置
CustomLog /var/log/httpd/axs_log combined env=!no
CustomLog /var/log/httpd/no_log combined env=no
ErrorLog /var/log/httpd/error_log


こうしておくと、/var/log/httpd/axs_log がほとんどPVを示すログになって便利です。

不正なアクセスをチェックしたいときは、/var/log/httpd/error_log や /var/log/httpd/no_log をチェックすることになると思います。

諸々、設定ファイルを更新したらApacheを再起動しましょう。

≫W32.HLLW.Gaobot.gen

いちアクセスで 32KB! という恐ろしく長大なログを残すウザイ君のご紹介(´ー`)


218.XXX.XXX.79 - - [01/Apr/2004:09:56:17 +0900] "SEARCH /\x90\x02\xb1\x02\xb1\x02\xb1\x02\xb1\x02 ...(中略)... \x90\x90\x90\x90" 414 271 "-" "-"


こういうログなんですが、結構な回数飛んでくるので、ログファイルが膨大になってしまう上、ログ解析ツールもエラーにおとしいれてくれます。
W32.HLLW.Gaobot.gen という名の言ってみりゃウィルス。IIS サーバによる WebDAV の脆弱性を狙ったアクセスで、ワームのファミリー(^_^;)だそうです。

サーバのステータスコードも“リクエスト長すぎ!”という意味の 414 だからかどうかはよくわかりませんが、このログは前述した SetEnvIf でログを分ける方法が通用しません。

では、どうやってログファイルから退治するかというと、方法は2つ。
  • W32.HLLW.Gaobot.genのアクセスログを取り除くシェルスクリプトを用意
  • ダミーのバーチャルサーバを用意して釣る
シェルスクリプトは書くのも面倒だし、cron で定期的に回さないといけないので今回は不採用。

2番目のダミーのバーチャルサーバを用意して釣る方法は簡単で効果的。

httpd.conf で
NameVirtualHost XXX.XXX.XXX.XXX:80

#===== 釣り用ダミーバーチャルホスト
<VirtualHost XXX.XXX.XXX.XXX:80>
	ServerName worm
	DocumentRoot /home/httpd/worm
</VirtualHost>

#===== 以下に通常のバーチャルホスト
<VirtualHost XXX.XXX.XXX.XXX:80>
	ServerName www.sample.com
            :
            :


という風に、ダミーのバーチャルホストを用意します。/home/httpd/worm は空のディレクトリを用意しておきます。

なぜ、こうしてW32.HLLW.Gaobot.genを避けられるかと言うと、W32.HLLW.Gaobot.genのアクセスにはヘッダ部分に Host: がありません。そこで、ホスト名ではなく、IPアドレスでアクセスしてくるものをダミーのバーチャルホストに振り分けることで退治しているわけです。

この方法では、数は少ないものの一部ロボットや通常のアクセスであっても、ホスト名ではなくIPでアクセスしてくるものを避けてしまうので注意が必要です(ちなみにGoogleはちゃんとホスト名でアクセスしてきます)。

≫参考サイト


技林TOP > 自宅サーバ構築メモ > Webサーバログについて
(C) bayashi.net