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

时间:2011-11-05 12:09:04

标签: php firewall

我有一个不允许编辑iptables的虚拟主机。从时间到我有轻量级(约300请求/秒)DoS攻击(通常不分发)。我决定编写一个可以阻止这些ips的PHP脚本。首先,我尝试将所有最近10秒的请求存储在数据库中,并查找滥用每个请求的地址。但我很快意识到,这样我每次DoS请求都必须至少向数据库发出1个请求,这并不好。然后我优化了这种方法如下:

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个请求,然后被阻止。

所以,问题是,这种方法是否具有最佳性能?有没有更好的方法来完成这项任务?

2 个答案:

答案 0 :(得分:3)

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

您可以使用密钥的IP地址。读取值。如果它不存在,则将其初始化为0,如果是数字,则将其递增。然后使用1秒或10秒的TTL或任何您想要的时间将其写回。如果计数高于阈值,则在TTL期间会有许多请求,您可以阻止IP。

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

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

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

答案 1 :(得分:2)

这是我的代码:

$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