[PHP] サイト丸コピーをしようとするIPを検出してメールでアラートする
とあるサイトで、サイト内容をまるっとコピーされることがありました。そこでサイトコピーを未然に防ぐために、丸コピーをしようとするIPを検出してメールでアラートするプログラムを書いてみました。
更新日: 2018.7.17公開日: 2017.10.4
サイトをコピーされてしまったら
定番は、GoogleへのDMCAによる著作権侵害申請
コピーされてから、ネットでいろいろと調べてみましたが、コピーされた方は、GoogleにDMCAによる著作権侵害を申請される方が多かったイメージです。プロバイダーを見つけて削除依頼をする方法もありますが、そちらは書類を用意したり結構面倒なので、フォームから申請するだけのDMCAは楽ですよね。
ただ、今回の自分の事象では、気づいた時にはコピーサイトが閉鎖していてDMCAで侵害を訴えられない状況でした。(それでも、コピーサイトのゴミインデックスだけがGoogleに残り、こちらのSEOは下がる)
また、DMCAはそもそもGoogleが取り合ってくれないなど、コピーしたもん勝ちなとこがあるのが現状です。
DMCAを乱用して自社の悪評を消すなんて逆SEO的なやり方も流行っているので、DMCAでコピーコンテンツ対策は万全!とはいかないのは仕方ないところです。
コピーされてからでは遅いのかもしれない=コピーを止めよう!
少し考え方を変えて、コピーサイトを止めるのではなく、「そもそもコピーされないようにするのはどうすればいいのか?」と考えた時に、
- ネットで公開している時点でオープンなので、個別コンテンツのコピーは防げない
- でも、コピーしてるユーザーは見つけることができるかもしれない
- コピーされる前にそのユーザーのアクセスを禁止してしまうのがいいかもしれない
という結論に至りました。
つまり、短期間に大量アクセスするIPを弾いてしまえばいいということです。
個別の記事をコピーする人は、パソコンで個別にコピーするで検出が難しいですが、サイト丸コピーをする人間は確実に1台のPCまたはサーバーからアクセスしてくるはずだから、ある程度の効果はあるはず!
プログラムの構成と流れ
まず、格安レンタルサーバーでも動かせるようにPHPで書きます。なるべくいろんなサーバーで使えるようにしたいのですが、exec関数を使うので、サーバーによっては使えないかもしれないのでご注意ください。
プログラムの流れをざっと書きだすと、
- access.logからIPごとのアクセス数を取る
- 全体の中央値を取って、異常値を出しているIPを抽出
- メールでアラートする
という感じにします。完璧ではないですが、**発見の補助くらいにはなるかな?**というレベルのものを目指します。
実装
access.logを一般ユーザーが閲覧できるようにする
まずはaccess.logが見れないと話にならないので、Apacheがaccess.logを読み取れるように権限を変えます。以下はCentOSの例。
access.logはサーバーによって場所が違うので、その辺りはサーバーのマニュアル等を参照してください。
chmod 0605 /var/log/httpd
プログラムを書く
さて、読み出せるようになったのでPHPプログラムを書いていきます。ここではcheck_spam_ip.phpというファイルで作成します。
//ログが保存されているパス
$log_path = "/var/log/httpd/access_log";
//google botなど。都度追加していく
$ok_ip = array(
"157.55.39.74",//bingbot
"207.46.13.50",//bingbot
"157.55.39.58",//bingbot
"157.55.39.242",//bingbot
"207.46.13.37",//bingbot
"66.249.71.154",//googlebot
"66.249.71.155",//googlebot
"66.249.79.10",//googlebot
"66.249.71.88",//googlebot
);
$date = date("d/M/Y");
//アクセスログを整形させる
exec("grep '{$date}:01' {$log_path} | cut -d ' ' -f 1 | sort | uniq -c", $results);
//取得したアクセスログを配列に変換
$log_ips = array();
foreach($results as $result){
$temp = explode(" ", trim($result));
if(!in_array($temp[1], $ok_ip)){
$log_ips[$temp[1]] = $temp[0];
}
}
//降順にする
arsort($log_ips);
//中央値を出す
$valuees = array_values($log_ips);
if (count($valuees) % 2 == 0){
$median = (($valuees[(count($valuees)/2)-1]+$valuees[((count($valuees)/2))])/2);
}else{
$median = ($valuees[floor(count($valuees)/2)]);
}
//中央値+n回までは許容する(ここではn=10)
$limit = intval($median) + 10;
//limitを超えたIPを抽出
$spam_ip = array();
$message = '';
foreach($log_ips as $ip=>$num){
if($num > $limit){
$spam_ip[$ip] = $num;
$message .= $ip . ": " . $num . PHP_EOL;
}
}
//結果が空でなかったらメール送信
if(!empty($spam_ip)){
$now = date('Y-m-d h:i:s');
$headers[] = 'From: Spamchecker <[email protected]>';
$title = "[{$now}] スパムIPを検出しました";
// 送信する
mail('[email protected]', $title, $message, implode("rn", $headers));
}
cronで一定期間で自動的に実行する
今度は、作ったプログラムを一定時間で実行させます。cronが簡単なのでcronを使いました。
下記の例では、1時間に一回(毎時1分)実行します。
1 * * * * /usr/bin/php /path/to/check_spam_ip.php
IPをチェックして、ApacheやNginxでアクセス制限をする
あとは、ApacheやNginxで対象のIPアドレスからのアクセスを拒否すればOK。
ただし、普通にいっぱいアクセスしてくれるヘビーユーザーの可能性もあるので、ブロックは慎重にする必要があります。
例えば、IPを抽出したら、そのIPの動きをアクセスログでチェックして、あきらかにおかしい挙動(1秒間に数回アクセスしているなど)を確認してからブロックするなど、「確実にスパムだ」と確定できてからブロックするようにすると良いと思います。
ざくっとしたプログラムですが、バッチで勝手に動いてくれれば面倒なアクセスログチェックもルーティンで行えます。
ただ、これだけでは当然不十分なので、抽出したIPの動きや数日、数週間の動きも同時にチェックできるように、今後プログラムを改善していこうと思います。
つづく(多分)。