.htaccess レベルでのアクセス拒否の方法について

切っ掛け

  • .htaccess に書いている deny リストが肥大化したのでちょっとスリムにしたかった 😛
  • 最近またリファラスパムがちょこちょこ出始めた
  • WordPress な人も大分被弾されてるみたいだし

目標

あんまり頭を使わずにアクセスログだけを見て,そこからとり出した文字列を拒否しようという作戦。

方法

おおまかに言って3つ:

  1. アクセス元(IP アドレス,リモートホスト)での拒否
  2. 参照元/Referer での拒否
  3. ブラウザの自称名/UserAgent での拒否

3つに共通する点はどれも .htaccess に書けると言う事。.htaccess ファイル自体に666 のパーミッションを与えておけば WordPress の管理画面からでも書き換えが可能なのでわりとおすすめ。

さて,次からは実際に .htaccess に書いてみましょう

書き方

アクセスの許可/拒否順序

.htaccess にorder allow,deny
allow from all
deny from
と記述します。この場合はアクセスを一旦全部許可します。その後に deny from に記述されたものを拒否します,という意味。門戸は広くノーガードで開けておいて,一旦入ったアクセスを選り分けるといった趣で。…ある意味待ち伏せ?
さて,この deny from その後に以下の記述をしていきます。

アクセス元(IP アドレス,リモートホスト)での拒否

これはなじみがあると思います。deny from 123.456.789のように書いていけばOKです。複数のアクセスも戸からのアクセスを拒否する場合は(なんか日本語がおかしい?)改行して同じようにdeny from 234.567.890と書けばOKです。この辺を半自動化するには Akismet htaccess extentionSpam Management Prevention なんかがおすすめです。

リファラで拒否する場合

例えを挙げて説明した方がよさそうなので。下のリファラは実際に記録されたものなんですけど,面白いですよねー。httpやftpで始まらず,かつドメインも無い。
XXXX:+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
なのでSetEnvIf Referer "^XXXX:" ref_deny
deny from env=ref_deny
と書きます。この場合は IP アドレスでの拒否とは違って直接リファラを拒否する事ができないので(たぶん),一旦,env変数に拒否するリファラを格納して,env変数に名前を付けて(ref_deny) その変数名を拒否するといった感じでしょうか。このリファラでの拒否を簡単にするには RefererKarma なんかがおすすめ。後,拒否する文字列に正規表現を使えるのでその辺得意な方は是非。

UserAgent での拒否

UserAgent ちょっと聞き慣れないものですが,アクセスする際にサーバ側に送るブラウザのバージョンなどを含んだ情報,っといったところでしょうか。例えばこんなものです: Mozilla/4.0 (compatible; MSIE 6.0; Windows 98 )詳しい解説は避けますが OS が Win98 で IE6を使っているという事が分かります。このUAはわりとメジャーなのでおそらく拒否する必要は無いと思います。で,次のようなUAはパッと見た感じアレなので拒否してもいいかなあと。おまけにこのUAでスパムを投下してたら確実ですけど:
Mozilla/4.0 (compatible; Viagra; Windows 98 )
Viagraという有名な単語が入っているのでこれを拒否してしまいましょう。書くとするとこんな感じです:
SetEnvIfNoCase User-Agent "Viagra" ua_deny
deny from env=ua_deny

ここもリファラと同じように直接拒否できないので一旦 env 変数に格納した後に拒否するので SetEnvIf を使います。でその後の NoCase ですけど,これは次の ” ” で括られた部分が大文字でも小文字でも同じように扱います,という意味。後,ここでも拒否する文字列に正規表現を使えるのでその辺得意な方は是非。

まとめて書いてみる

さて,上の3つをまとめて書いてみましょう。こんな感じになります:
SetEnvIf Referer "^XXXX:" ref_deny
SetEnvIfNoCase User-Agent "Viagra" ua_deny
order allow,deny
allow from all
deny from 123.456.789
deny from 234.567.890
deny from env=ref_deny
deny from env=ua_deny

あくまでも個人的な好みなんですが,order allow,deny の前に SetEnv を宣言してる理由は

  1. deny リストを途切らせずに一覧にしたい
  2. env 変数宣言する前に env 変数に格納されている文字列を拒否するというのは順序としてどうも好きになれない

です。
プログラミングをする人から見てこの辺はどう見てるのかは分かりませんが…おかしいですか?

最後に

スパムなんかが無くなればこんな事をしなくて済むんですけどねぇ… :s

この記事は Apache や .htaccess の知識(しかも大さじ1杯ほどの!)を駆使して書かれております。それ故間違いが多分に入っている可能性があるので,間違ってたら指摘お願いします。ここよりももっとまともなアクセス制限の方法を書いているサイトがあるのでそちらも参考にどうぞ。