動的生成時の .htaccess ファイルを見直す
今回は、ちょっと難しいよ! でも、Movable Type で動的生成(ダイナミック・パブリッシング)を利用している人は必見です。
MT で動的生成を利用する設定にすると .htaccess が自動的に作成されます。初期状態のままだと、思いっきりサーバに負担がかかるかも知れない──ということを発見しました。特に Perl 版ダイナミック・パブリッシングを使っている人は、とんでもないことになっているかも。──悪いのは、みんな spammer ですが……。
具体的には、.htaccess ファイルにこんな設定を施す、という提案です。
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 下の三行を追記
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jp*g|png)$
RewriteCond %{REQUEST_URI} !^/mt/cm/.*$
RewriteCond %{REQUEST_URI} !^/mt/tb/.*$
RewriteRule ^(.*)$ /mt-dynamic.php [L,QSA]
では、順を追って解説してみます。
まずはおさらい
MT3.2 で動的生成を使う設定にすると、ブログのルートディレクトリに下記の内容が書かれた .htaccess ファイルが作成されます。一部、抜粋しました。
RewriteEngine on
# don't serve mt-dynamic.php if the request is for a real directory
# (allows the DirectoryIndex lookup to function)
RewriteCond %{REQUEST_FILENAME} !-d
# don't serve mt-dynamic.php if the request is for a real file
# (allows the actual file to be served)
RewriteCond %{REQUEST_FILENAME} !-f
# anything else is handed to mt-dynamic.php for resolution
RewriteRule ^(.*)$ /mtview.php [L,QSA]
コメント部分(行頭が # から始まる行)を眺めて、重大なことに気がつきました。簡単なので一行ずつ見ていきます。
まず、RewriteEngine on
は Apache module mod_rewrite を使う、という宣言です。
コメント部分を飛ばして、次の RewriteCond %{REQUEST_FILENAME} !-d
は「ディレクトリが存在しない場合」という意味です。-d
が「ディレクトリ」で !
が否定ですね。
この場合の「ディレクトリ」というのがちょっとややこしいです。このブログでいうとトップページは http://asiamoth.com/mt/ ですが、実際のアドレスは http://asiamoth.com/mt/index.php です。こういう具合に「ディレクトリのインデックスファイル」を含めて存在チェックをしています。ということで、正確には「リクエストがディレクトリの場合は、そのディレクトリにインデックスファイルが存在しない場合」ですかね(長っ)。
さらに、次の RewriteCond %{REQUEST_FILENAME} !-f
を見てみます。-f
が「ファイル」、!
が否定なので、「ファイルが存在しない場合」ですね。
ということで、リクエストされたディレクトリ、またはファイルが存在しなければ、mtview.php に渡して、処理してもらうわけです。
──ここで何が重大なことか気がついた方は鋭い。そう──ということは、デタラメな URL や(ワケあって)削除したファイルにアクセスがあった場合でも、わざわざ mtview.php にアクセスしに行きます!
Perl版ダイナミック・パブリッシングの場合
Perl 版ダイナミック・パブリッシング を利用している場合、上記の mtview.php
を mt-dynamic.php
に書き換えます。
──ということは、存在しないディレクトリやファイルのリクエストがあった場合、mt-dynamic.php が処理を開始します。そして、その度に mt-dynamic.php はデータベース(各種 SQL)にアクセスして、どのような処理を行うか、確認しに行きます──。
ちゃんと、「動的生成する」と決めたテンプレートから生成される URL であれば、そのまま動的生成を行います。しかし、例えば、延々と「無効な URL」にアクセスがあった場合は……?
ガクブル モノですが、その度に mt-dynamic.php くんはデータベースに問い合わせに行くわけです……。お、恐ろしい。というか、ずっっっっと、このブログではそうなっていました。何度「MySQL へのアクセス大杉」というメッセージを見たことか……。
とりあえずの解決策
さて、サクッと解決、といきたいところ。妥協案の一つはこんな感じ。
# @asiamoth
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jpe?g|png)$
RewriteCond %{REQUEST_URI} !^/mt/cm/.*$
RewriteCond %{REQUEST_URI} !^/mt/tb/.*$
2007-01-12T13:01:31+09:00 追記
はい、また嘘コード書いてました(コメント欄参照 : あんちもん2 さんに感謝!)ので修正しました
こんな感じで RewriteRule ^(.*)$ /mtview.php [L,QSA]
の直前に書きました(Perl 版~の場合は mt-dynamic.php
に読み替えて)。
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jp*g|png)$
というのは、.cgi で終わる CGI ファイルや画像ファイルなど、「動的生成することが アリエナイ ファイル」ではない(!
)という条件です(ややこしい)。要するに、CGI や画像ファイルは動的生成しないよ、ということ。
このブログでは真説・対spam最終兵器 CGIリネーム烈伝 : 亜細亜ノ蛾 で書いたようにコメント・トラックバック CGI をリネームしていますが、いまだにリネーム前の CGI にアクセスがあります。──その度に負荷が……。画像ファイルの指定はおまけです。その他、みなさんの方で思いつく拡張子をぶっこみングするヨロシ(何語?)。
RewriteCond %{REQUEST_URI} !^/mt/cm/.*$
の部分は、リネームしたコメント CGI の URL です。これも「動的生成しない」と指定しています。ここはみなさんの環境に合わせ、「動的生成するファイルが存在しないディレクトリ」を指定してください。
導入した結果
ということで、上記の数行を入れただけで、半日で 500 アクセス(!)釣れました。みんな、リネーム前のコメント CGI へのアクセスですた。──一体、どんだけサーバに負担かけていたんだろう……。というか、いまはみんな「404」を返していますが、なんか仕返ししたいなー。ファッ●! スパマーめ!
まぁ、それでもぜんぜん「負荷率」が減らないのが、Xrea.com クオリティ ☆
今後
さて、上の方法は .htaccess ファイルをブログのルートディレクトリに設置して「指定した条件に当てはまらなければ、動的生成を試みる」という方法ですが──
──書いているうちに、もっと賢い方法を思いつきました。
要するに、「動的生成するかどうかの条件」を書いた .htaccess はブログのルートディレクトリに置かず、動的生成したいファイルがある場所だけに設置する。
-
http://example.com/mt/
-
ブログ・ルート・ディレクトリ
-
ここの .htaccess には動的生成のルールは書かない
-
-
http://example.com/mt/archives/
-
ブログの記事がある場所
-
動的生成するファイルがあるので、ここの .htaccess ファイルに動的生成のルールを書く
-
-
http://example.com/mt/tag/
-
タグのページがある場所
-
タグは動的生成ではなく Tagwire Plugin などでタグを生成する
-
よって、ここも動的生成のルールは不要
-
こんな感じ。これがベターですかね。
──こうして考えていくと、つくづく URL の設計って重要だなー。Web デザインというモノは、色や形だけではなく、URL も含めて考える必要がありますね。
この記事のタグ(偽)
[この世で最もお馬鹿な人種は?][spammer]
コメント
お久しぶりです、こにゃにゃちば(=゜ω゜)ノ
私のブログではダイナミック・パブリッシングは使ってませんが
同じXREAなので、似たようなスパム撃退法は使ってます(笑)
CGIリネーム究極版の副産物で出来たモノで、スパマーに
ギャフン!と言わせる事は出来ませんが、スパム送った奴の
情報を集めて.htaccessで完全に封鎖する様にしています。
ポイントは…スパマーの動きをする奴には403を喰らわせる!
って感じです。これでスパマーの情報だけを集める事が(笑)
初めてコメントします。1点指摘。
RewriteCond %{REQUEST_FILENAME} !\.(cgi|css|gif|jp*g|png)$
の「jp*g」の部分は、「jg」「jpg」「jppg」「jppppg」等にマッチしちゃいます。特に、「jpeg」にはマッチしません。
正しくは「jpe?g」もしくは「jp.?g」であないかと。
前者なら「jpg」と「jpeg」のみ、後者なら「jpg」「jpag」「jpbg」「jpeg」「jp0g」等にマッチします。
たねちゃん さん:
どもども。なるほど、エラーログを見るだけでスパマの情報が得られるのですね(合ってる?)。ちょっと真似してみます。
あんちもん2 さん:
あちゃー、「──ダメ出し」をダメ出しですな。ありがたいです! たぶん、記事を書いたときに wild card と勘違いしてました。記事を修正しておきます。
3.4時間くらい掛かりましたが、スパマーに403喰らわせる方法を
なんとか書いてみました。また参考にして頂ければ幸いです。
XREAでエラーログって見れるんですか?もし出るならそっちの
方が多分(おそらく(間違いなく))そっちを見た方が楽ですね。
私はちと分からなかったので.htaccessに
ErrorDocument 403 /403.cgi
を設定して、CGIでIPとUserAgentを記録する様にしました。
エントリーの方で書きましたが、この記録したログが見れます(笑)
おお、かなりまとまった記事ですね。じっくり読みました。
「XREAでエラーログ」を見るには、おそらく「生ログ」を見る必要があります。一度、じっくりと確認しなければ、と思いながらまだ未確認です。エラーログ用のCGI を使う、というのは素晴らしいですね。自分でもちょっと確認してみます。
いつか、スパム対策に悩まされることがなくなるといいですね(それはそれで寂しい?)。