如何检测和禁止攻击ip使用php


How to detect and ban attacking ips using php

我有一个不允许编辑iptables的虚拟主机。有时我遇到轻微的(大约300个请求/秒)DoS攻击(通常不是分布式的)。我决定编写一个PHP脚本来阻止这些ip。首先,我尝试在数据库中存储最近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请求,然后被阻止。

那么,问题是,这种方法是否具有最佳性能?有更好的方法来完成这个任务吗?

尝试使用Memcache,查找速度会快得多。

可以使用IP地址作为密钥。读取该值。如果不存在,初始化为0,如果是数字,则自增。然后用TTL(1秒或10秒,或您想要的任何时间)回写它。如果计数超过阈值,则TTL周期内的请求数过多,可以阻止该IP。

更新:我只是认为设置更新的值将再次给它一个至少一秒的新TTL,所以一个IP可能被阻止,如果它请求 <threshold> 请求的连续间隔不到一秒
我不认为它使这个答案完全无用,但是如果您想要对我所描述的内容进行文字实现,请记住这一点。

阻塞可以是永久的(通过在数据库中记录),也可以是短时间的。您也可以使用MemCache,通过记录标记(如'X')而不是计数器,并将TTL设置为更长的周期。计数器脚本必须检查读值是否不是'X',否则计数器将覆盖该块。

我会选择使用Memcache,即使你想让黑名单持久化。查找(您需要为每个请求执行查找)要快得多。您可以在数据库中保存列入黑名单的IP,并定期恢复该列表,或者至少在服务器重新启动时恢复该列表。这样,您就得到了一个持久的黑名单,而不必为每个请求检查数据库而增加开销。

下面是我的代码:

$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