apacheの設定

Configuration File

apaheの設定ファイルはhttpd.confに書かれている。しかし、これにサイト固有の設定を書いる場合、updateしたりして設定ファイルが変更になったりすると、自分の設定にまた書き直すなど面倒な作業が出てくる。

幸い、apacheにはInclude文があり、個別のファイルに設定を記述して取り込むことが出来るので、これを使うことにする。今回は、サイト固有の設定をhttpd-site.confに記述し、httpd.confの中で、次のように取り込む事にする

#
# Site Configuration File
#
Include conf/httpd-site.conf	

アクセスログの設定

内部と外部のアクセスログを別に記録する

ネット上でググって見ると、内部からのログは記録しない方法は、沢山探し当てることが出来るが、内部と外部のアクセスログを別に記録する方法はなかなか見つからない。

自分の場合、webアプリケーションの開発なんかもやっているので、内部のログもデバッグなどに使用するので残しておきたい。うーーーんと小一時間程考えたら、SetEnvIfで簡単に出来ることがわかりました。

# 最初は、全てのアクセスを外部からのアクセス(inter-net=1)と定義します。
SetEnvIf Remote_Addr "[0-9]*" inter-net=1	
# Remote_Addrが192.168.0.*の場合は、内部からのアクセス(local-net)を定義し、
# 外部アクセス(inter-net)を未定義にします。
SetEnvIf Remote_Addr "192\.168\.0\.*" local-net=1 !inter-net	
# 外部アクセス(inter-net)が定義されていればlogs/access_logに記録し、
# 内部アクセス(local-net)が定義されていればlogs/access_local_logに記録します。
CustomLog logs/access_log       combined env=inter-net
CustomLog logs/access_local_log combined env=local-net      

このようにすることで、ログファイルを分けることが出来ました。

最初、下記のように設定していたのですがうまく動かなくてハマってしまいました。

# ダメな例
SetEnv inter-net 1
SetEnvIf Remote_Addr "192\.168\.0\.*" local-net=1 !inter-net

CustomLog logs/access_log       combined env=inter-net
CustomLog logs/access_local_log combined env=local-net 	

これだと、内部からのアクセスの場合local-netは定義されるのですが、inter-netの定義が消えてくれず、結果としてaccess_logとaccess_local_logの両方に内部からのアクセスログが記録されてしまいました。どうやら、SetEnvで定義した値は、SetEnvIfでは認識してくれないようです。

画像のログは記録しない

画像のログを記録しておくと、ファイルサイズが直ぐに大きくなってしまうので、記録しないようにします。
#拡張子が画像だった場合、nologを定義します。
SetEnvIfNoCase Request_URI "\.(gif)|(jpg)|(png)|(css)|(js)|(ico)$" nolog=1	
#nologが1の場合、外部アクセス(inter-net)と内部アクセス(local-net)の定義を消します。
SetEnvIf nolog 1 !inter-net !local-net	

このようにすれば、access_logにもaccess_local_log記録されません。

Wormを弾き出せ!

ログを記録してしばらくすると、あるはずのない「dafault.ida」や「NULL.IDA」といった名前のファイルにアクセスがあることがわかります。これがいわゆるワームで、そのまま記録しておくとウザイので別ファイルに記録することにします。

こいつらは、RefererとUser-Agentが無いと言う特徴があるので、RefererとUser-Agentが空白なものはワームとする、と言うちょっと強引な方法で設定しています。

#最初は、全てのアクセスはwormと定義します。
SetEnvIf Remote_Addr "[0-9]*" worm=1	
#RefererまたはUser-Agentが空でない場合は、wormじゃない。
SetEnvIf Referer    "[[:graph:]]{1,}" !worm
SetEnvIf User-Agent "[[:graph:]]{1,}" !worm	
#なかには、RefererまたはUser-Agentを付けるワームも居るようなので、拡張子が(.ida,.dll,.exe,.bat)が含まれるものはwormとします。
SetEnvIfNoCase Request_URI "\.ida" worm=1
SetEnvIfNoCase Request_URI "\.dll" worm=1
SetEnvIfNoCase Request_URI "\.exe" worm=1
SetEnvIfNoCase Request_URI "\.bat" worm=1	
#wormが定義されている場合、inter-netとlocal-netを未定義にして、access_logやaccess_local_logに記録しないようします
SetEnvIf worm 1 !inter-net !local-net	
#wormが定義されていたら、worm_logと言うファイルに記録させます。
CustomLog logs/worm_log  combined env=worm	

さらに、下記のように定義して、アクセス禁止にしてしまいましょう。

<Files *>
  order allow,deny
  allow from all
  deny  from env=worm
</Files>	

無礼なrobot はおことわり

インターネット上には数多くのコンテンツ収集robotが存在しますが、中には一度にゴッソリコンテンツを持っていくrobotや、一日に何回もアクセスしてくる傍若無人な奴等もいます。このような無礼なrobotは出入り禁止にしてしまいましょう。

robotの種類と解説は望月明夜さんのrobotはぢきについてに詳しく書かれているので、これを参考にサーバーに訪れる無礼なrobotを見つけ出します。

家のサーバーに来る、ウザイrobotは次の通り。

  1. NaverBot-1.0:毎日何回も来て鬱陶しい、以前はとても行儀が悪かったらしいので出入り禁止
  2. msnbot:毎日訪れて、ゴッソリ持って帰る。MSは嫌いだし出入り禁止(笑)
  3. yahoo! Slurp:これも毎日来ます。
  4. Internet-Html-Searcher:アクセスフィルターを販売している会社だとか。ページ上に「大量破壊兵器」と書いただけで有害サイトフィルターにサイトが登録されてしまうとかの噂もある。特にUser Agentを偽装してくる点で極悪。

1〜3についてはDocumentRootにrobots.txtと言うファイルを作成して、次のように書いておけば収集は行いません。

User-Agent: msnbot
Disallow: /

User-agent: NaverBot*
Disallow: /

User-agent: Slurp
Disallow: /	

4のInternet-Html-Searcherですが、これはUser Agentを偽装してくるので、robots.txt書いても無駄です(と言うか、robots.txtを見ていない。)ので、IPで禁止するしかありません。

私は、httpd-site.confに次のように書いています。

<Files *>
  order allow,deny
  allow from all
  deny  from env=worm
  deny  from 61.115.195.180
  deny  from 61.115.195.181
  deny  from 61.115.195.182
</Files>	

別のアドレスからアクセスがあった場合は、これに追加していきます。そしてrobotとの戦いは続く....

ログのローテーション

apacheで出力するログをそのままにしておくと巨大なログファイルとなってしまいます。巨大ファイルでは、ログをちょっと見たい時や、stats等でアクセス解析する時に効率が悪いので、ある一定のサイズや時間になった場合、ログを分割させる設定を行うことにします。

apache付属のrotatelogsを使う方法

apacheにはログのローテーションを行うためのコマンドrotatelogsが付属しています。これを使えばapacheを停止させずにログのローテーションを行うことが出来ます。

rotatelogsのコマンド引数は下記のようになっています。

# rotatelogs logfile rotationtime [offset]

rotatelogsを使用してローテーションを行うには、confファイルに次のように記述します。

ErrorLog "|/usr/sbin/rotatelogs /var/www/log/access_log 86400"
ErrorLog "|/usr/sbin/rotatelogs /var/www/log/error_log 86400"	

rotatelogsの場所とログのある場所は、システムによって異なるので書き換えてください。これによって、一日毎にログローテーションが行われます。しかし、rotatelogsによるログローテーションにも下記の欠点はあります。

特に、アクセスの少ないサーバの場合、ファイルサイズによるローテーションが出来ないと小さなファイルが沢山増えてしまい、かえって不便になることもあります。

newsyslogを使う方法

大抵のunixであるならば、ローテーションを行うためのコマンドが用意されている。私が使用しているOpenBSDにはnewsyslogコマンドがあり、これが/var/log以下にあるログのローテーションを管理しています。

apacheのログをnewsyslogコマンドでローテションをさせるためには、/etc/newsyslog.confに下記の設定を追加すればOKです。

# logfile_name       	 owner:group	mode	count	size	when	flags	
/var/www/log/access_log	   www:www	644	12	250	*	Z     /var/www/logs/httpd.pid
/var/www/log/error_log	   www:www	644	12	250	*	Z     /var/www/logs/httpd.pid
/var/www/log/worm_log	   www:www	644	12	250	*	Z     /var/www/logs/httpd.pid	

これで、各ログが250Kbyteになったらローテーションが行われ、ローテーションされたファイルは12個まで保存されます。

Last modified: Thu Dec 20 16:25:45 2007 JST