Top/PukiWiki/1.4/ちょっと便利に/連続アクセスを回避する

連続アクセスを回避する by Cue

ノーウェイトでwgetできなくなる等々副作用も多いので必要とされる方・解説無しで動作が理解できる方の参考程度にお願いします。

  1. ストレステストはやってません
  2. 瞬間最大風速を抑制する効果しかありません
  3. 制限の処理で少し変なところがあります
  4. Googleのクローラーは通ります
  5. 本当に困った時は .htaccess なり別の手段をお勧めします

メッセージ

  • 返すヘッダーは 503 Service Unavailable にして、Retry-After: 60 でもつけておくと良いかもしれませんね :) -- henoheno 2005-09-23 (金) 16:51:21
  • 例ではありますがwgetにはランダムな秒数を空けてgetするオプションがありますから、遠慮はいらないと思われます -- henoheno 2005-09-23 (金) 16:52:09
  • Statusは適当に変えてやってください。Retry-afterは設定した時間を経過すれば必ずアクセスできるようになっているとは限らないので少し微妙かもしれません。 -- Cue 2005-09-23 (金) 19:31:32
    • Retry-Afterを無視する輩には関係のないことですし、尊重する輩であればアクセス頻度を低下させる効果があります(それ以外に意味はありません :) ) 数値は60でも120でも何でも構いません -- henoheno 2005-09-23 (金) 20:01:48

追加ファイル

/lib/pukiwiki.phpでDATA_HOME、LIB_DIRを設定した直後にrequireするのが効果的です。

access_check.php

<?php
// PukiWiki - Yet another WikiWikiWeb clone.
//
//	access_check.php		Copyright Cue 2005
//
//	2005/09/18	v0.01
//		とりあえず作る(PHP4.3.5以降でflock可能な環境専用)
//
//	2006/03/26	v0.02
//		flockに第三引数を与えないよう変更(与えるとPHP4と5で戻り値が異なる)
//
//
//	あるリモートアドレスから1秒間に受け付けるリクエストの最大値
//	※リダイレクトすると強制的に連続アクセスになるので2以上を設定すること
define('ACCESS_CHECK_MAX_EXEC_PER_SEC',	4);
//
//	アクセス拒否を解除するまでに最低限必要な秒数
define('ACCESS_CHECK_DENY_TIME_LIMIT',	5 * 60);
//
//	アクセス記録するディレクトリ(counter/に置くとファイル名が困ったことになる)
define('ACCESS_LOG_DIR',	DATA_HOME . 'access_log/');


$time = time();
if(!access_check_set_ip_log($_SERVER['REMOTE_ADDR'], $time)){
	header('Status: 403 Forbidden');
	exit;
}
$_plugin_online2_ip_count = access_check_get_online_ip($time);
unset($time);

function access_check_set_ip_log($ip, $time)
{
	$logfile = ACCESS_LOG_DIR . $ip . '.log';
	$retcode = FALSE;
	$fp = fopen($logfile, 'a+b');
	if(flock($fp, LOCK_EX | LOCK_NB)){
		rewind($fp);
		$data = explode("\n", fread($fp, 4096));
		if(count($data) > ACCESS_CHECK_MAX_EXEC_PER_SEC){
			if((int)$data[0] != $time)
				ftruncate($fp, 0);
			fputs($fp, $time . "\n");
			$retcode = TRUE;
		}
	}
	fclose($fp);
	return $retcode;
}

function access_check_get_online_ip($time)
{
	$lists = array();
	if(($dh = @opendir(ACCESS_LOG_DIR)) !== FALSE){
		while(($lists[] = readdir($dh)) !== FALSE);
		closedir($dh);
	}
	$count = 0;
	$time -= ACCESS_CHECK_DENY_TIME_LIMIT;
	foreach($lists as $key=>$file){
		if(preg_match('/^(?:\d+\.){4}log$/', $file)){
			if(@filemtime(ACCESS_LOG_DIR . $file) <= $time){
				@unlink(ACCESS_LOG_DIR . $file);
			}else{
				$count++;
			}
		}
	}
	return $count;
}
?>

このログを利用するとonlineプラグインを下のように変えることもできます。

<?php
// PukiWiki - Yet another WikiWikiWeb clone.
//
//	online2.inc.php		Copyright Cue 2005
//
//	2005/09/18	v0.01
//		とりあえず作る

function plugin_online2_convert()
{
	return plugin_online2_itself(TRUE);
}

function plugin_online2_inline()
{
	return plugin_online2_itself(FALSE);
}

function plugin_online2_itself($convert)
{
	global $_plugin_online2_ip_count;

	if(isset($_plugin_online2_ip_count)){
		$retval = $_plugin_online2_ip_count;
	}else{
		$retval = 'access_check.php required';
	}
	return $retval . ($convert ? '<br />' : '');
}
?>

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2006-03-26 (日) 20:54:26
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.235 sec.

OSDN