とっても迷惑なアクセス

2011年11月1日
  ホームページのアクセスログを見ていますと、毎日同じようなところから幾度も気になるアクセスがあります。
主にmsn.com, amazonaws.com, as13448.com といったところからですが、何か情報収集アクセスのようです。しつこく挙動も不審で迷惑なのでちょっと対策を講じることにしました。

以前より時折ホームページのアクセスログを見ていて不審なアクセスが目についていました。
私は自前のアクセスログに通例に従いIPアドレスとユーザエージェントごとにログを記録していますが、これらのアクセスは以下のような特徴があり貴重な?ログリソースを多く浪費しています。

1.多数のIPアドレスを使って一日幾度もアクセスしてくる。
2.ユーザエージェント(ブラウザ名)が頻繁に変わり、一見通常のブラウザ名だが偽装しているのではないかとの疑いもある。
3.Apacheの生ログを確認しても通常のブラウザのアクセスとは異なり人間が見ているようなアクセスには思われない。
4.かといってrobots.txtも読んではいない。
時には1日のログの半分以上がこれらのアクセスで埋まっていたりします。
ひとつのIPで同じユーザエージェントならアクセス回数の表示が増えるだけなので気にはならないのですが。
代表的なものとしてas13448.com, amazonaws.com, msn.com といったところからのアクセスが目につきます。

どういう種類のアクセスなのだろうかと思いいろいろ検索して調べてみても、単にログをさらしているだけのサイトばかり目について、その実態がつかめません。
何も公開せず秘密裏に何かを行っているようで、ますますあやしい!。

特におかしいのが search.msn.com からのアクセスで、
まったく普通のMSIEを名乗っている。bingbotやmsnbotというのがあるのにだ。
いちおうjavascriptも解するようだし、一時cookieも有効になっている(継続cookieは有効になっていない)。
ただしナビゲーションページを見た形跡もないのに常にいきなり記事idを要求してきてページのソースだけは取っているが、背景画像やアイコンなどにはアクセスしてくることはない。
 明らかに人間が操作しているブラウザとはちがう。
もちろんrobots.txtにはアクセスしてこない。
いくらなんでも通常ブラウザの名を名乗ったから、あるいはその挙動が通常ブラウザと同等だからといって、明らかに情報収集のロボットアクセスなのにrobots.txtも見ずに何をやってもいいというもんでもないだろう!
まして天下のMicrosoftがやっていいことなのだろうか!
別に大きな実害があるわけでもないので放っておいてもいいのだが、気がついてしまうと何かしてあげなくてはいけないと思うたちで…

で、少なくともrobots.txtで制御できないアクセスに関しては対策を講じることとしよう。どういうやりかたがいいかな。
一思十考とまではいかなくても一思三考くらいはせずばなるまい。
(1)ファイヤウォール(iptables)で蹴る。
(2).htaccessで蹴る。
(3)その他アクセスチェックプログラムで蹴る。
とまあ、これくらいはすぐ思いついたのだが、どれも大人気ないし能がないなあ。

ここでちょっと思い出したが、以前 naver.jp の Yetiクローラが頻繁にアクセスしてきたとき、naver.jpに少し文句を言って問い合わせたら非常に丁重な返答を頂き親切にrobots.txtの設定の仕方など教えてくれた。その後は全く問題はない。
で今回もまずはできればそれをやってみよう。ただas13448.comは問い合わせ先すらわからないし、日本語以外でとなると全く無理。
msnは何とかなるかもしれないと思い、問い合わせしようとしたが、な、なんと、ユーザ登録してユーザログインしないと問い合わせさえ受け付けてくれないようだ。

ならばこちらもログインを要求してもいいだろう。
ただしGUESTという形で人間ならば簡単にログインできるようにしておく。

(4)GUEST LOGINを要求する。
badaccess.phpとでもいうファイルを作って以下を書く。
<?php
function is_bad_access()
{
  // 多数のIPでアクセスしてくる通常のブラウザを装う情報収集アクセスは拒否。
  // httpd.confのHostnameLookupsをOnにしてないと動作しません。
  $host  = isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : '';
  $agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';

  // ちゃんと検索ロボットだと名乗ったのは許す。
  if(preg_match('%bot|crawl|search|spider|survey%i', $agent)){ return(FALSE); }
  // それ以外以下からのアクセスは該当。
  if(preg_match('%msnbot[-0-9]+\.search\.msn\.com%', $host)){ return(TRUE);}
  if(preg_match('%static[-0-9]+\.as13448\.com%', $host)){ return(TRUE);}
  if(preg_match('%\.amazonaws\.com%', $host)){ return(TRUE);}

  return(FALSE);
}

function www_guest_login() // 実はBad Access 拒否用。
{
  $GUEST_ID = 'GUEST';
  $GUEST_PW = 'GUEST';

  $login_id = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : '';
  $login_pw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : '';
  if($login_id == $GUEST_ID && $login_pw == $GUEST_PW)
  {
    return(TRUE); // Login OK
  }

  // ログイン要求。ただしユーザ名とパスワードを明示しておく。
  header('WWW-Authenticate: Basic realm="GUEST Login: User='.$GUEST_ID.', PW='.$GUEST_PW.' !!!"');
  header('HTTP/1.0 401 Unauthorized');
  header('Content-type: text/html; charset=UTF-8');
  echo('Members Login Failed !
Guest login is
User Name : '.$GUEST_ID.'
Password  : '.$GUEST_PW.'
');
  exit;
}

// BAD ACESS対処
if(is_bad_access())
{
  if(!www_guest_login()) // ログインを要求してみる。GUEST:GUESTでログイン可能。
  {
    exit;
  }
}

?>
そして各ページの頭でこれをincludeすればいい。ページの出力はphpプログラムでやっており、すべてアクセスチェックとログプログラムをincludeしているので、実際にはその頭1箇所に設定すればOK。
しばらく様子を見てたらいい感じ。やっぱりGUEST Loginなどしてこない。弾くの正解。

...とここまで書いていたら、ふともっといいのを思いついてしまった。

それは、
(5)有無を言わさずこのページに飛ばす!

最後のところを、
......

// BAD ACESS対処
if(is_bad_access())
{
  // 一時的なredirectにとどめるなら応答コードを302にしておく。
  header('Location: http://kuragane.jp/troublesome.html', true, 301);
  exit;
}
などとすればいい。

注意すべきは、このページそのものに飛ばすとここにもリダイレクトが仕掛けられているので堂々めぐりになるから、いったんソースを落としてアクセスチェックを取り除いたページtroublesome-access.htmlを作って置いておき、そこに飛ばす。

でも、ページが日本語だから泥棒猫に説教するようなもんで効果あるかな? 猫語...じゃなかった英語わからんし。
ま、いいか。

要は、言いたいこと:
1.不要にいろんなIP, Agent名でアクセスするな。
2.検索アクセスならagentでちゃんと名乗れ。通常ブラウザをかたるな。
3.robots.txtを読んでちゃんと守れ。
4.容易に確認なり問い合わせなりできるようにしておけ。
これだけ。