我有一个不允许编辑iptables的虚拟主机。有时我会遇到轻微(大约300个请求/秒)的DoS攻击(通常不是分布式的)。我决定编写一个PHP脚本来阻止这些ips。首先,我尝试将过去10秒内的所有请求存储在数据库中,并查找每个请求的滥用地址。但我很快意识到,这种方式我必须为每个DoS请求至少执行一个对数据库的请求,这并不好。然后我优化了这个方法,如下所示:
Read 'deny.txt' with blocked ip's
If it contains request ip, then die()
--- at this point we have filtered out all known attacking ips ---
store requesting ip in database
clean all requests older than 10 secs
count requests from this ip, if it is greater than threshold, add it to 'deny.txt'这样,新的攻击ip将只向数据库发出Threshold请求,然后被拦截。
因此,问题是,这种方法是否具有最佳性能?有没有更好的方法来完成这项任务?
发布于 2011-11-22 20:43:09
下面是我的代码:
$ip = $_SERVER['REMOTE_ADDR'];
// Log ip
$query = "INSERT INTO Access (ip) VALUES ('$ip')";
mysql_query($query) or HandleException("Error on logging ip access: " . mysql_error() . "; Query: " . $query);
// Here should be database cleanup code
// Count requests
$query = "SELECT COUNT(*) FROM Access WHERE ip='$ip' AND time > SUBTIME(NOW(), '00:01:00')";
$result = mysql_query($query) or HandleException("Error on getting ip access count: " . mysql_error() . "; Query: " . $query);
$num = mysql_fetch_array($result);
$accesses = $num[0];
// Ban ip's that made more than 1000 requests in 1 minute
if($accesses > 1000)
{
file_put_contents('.htaccess', 'deny from ' . $ip . "\r\n", FILE_APPEND | LOCK_EX);
}和.htaccess存根:
order deny,allow
deny from 111.222.33.44
deny from 55.66.77.88发布于 2011-11-05 20:19:26
尝试使用Memcache,它的查找速度会快得多。
您可以使用密钥的IP地址。读取值。如果它不存在,将其初始化为0,如果它是一个数字,则递增。然后用1秒或10秒的TTL或您想要的任何时间段将其写回。如果计数超过阈值,则在TTL周期内有太多请求,您可以封堵该IP。
更新:我只是认为设置更新值将再次给它一个至少一秒的新TTL,所以如果一个IP以不到一秒的连续间隔请求<threshold>请求,它可能会被阻塞……
我不认为它使这个答案完全无用,但如果您想要对我描述的内容进行字面上的实现,请记住这一点。
阻塞可以永久地完成(通过将其记录在数据库中),也可以在较短的时间内完成。您也可以使用MemCache来实现这一点,方法是记录一个标记(如'X'),而不是计数器,并将TTL设置为更长的时间段。计数器脚本必须检查读取的值是否不是“X”,否则计数器将覆盖该块。
为此,我会选择使用Memcache,即使您希望使黑名单持久化。查找(您需要为每个请求执行的操作)要快得多。您可以在数据库中保存列入黑名单的IP,并定期恢复该列表,或者至少在服务器重新启动时恢复该列表。这样,您就得到了一个持久的黑名单,而无需在每次请求时检查数据库的开销。
https://stackoverflow.com/questions/8020083
复制相似问题