Nginx 的 limit_req 模块虽然也能控制单个 IP
地址访问频率,但是时间最长单位是每分钟 1 次,如果想要更大的时间跨度,比如没小时一次,甚至每天一次,就需要这个 PHP 版本的,URL
自定义访问频率时间限制,保护 API 接口防 CC
攻击,支持上万并发的代码了。
优势:
- 可以自由设置访问频率时间,可以以月为时间长度
- 简单易用,无论你懂不懂 PHP 开发,只要会复制粘贴就行。
- Memcached 内存缓存技术,高性能,高并发。
- 精准无误,0 误封。
- 能防护 QPS 10000 以内的CC攻击,看机器配置,有可能更高。
- 支持范围较广,直接你网站支持 PHP 就行。
- 源码简单,可自行修改,可以套自己喜欢的前端模板主题。
要求:
- PHP 版本 ≥ 7.2
- PHP 需安装 Memcached 扩展
- Memcached ≥1.6
使用方法
以下开源代码添加到你网站核心文件中,相当于你网站任何页面都会引用的一个文件,类似于:config.php
WordPress 网站添加到根目录的 /index.php
头部即可,即控制所有的页面访问,如果想要控制单独某个页面,只需要将此代码放到此页面的 PHP 内即可。
其他 PHP 网站根据你的程序逻辑决定。
代码
代码语言:javascript复制<?php
ini_set("display_errors", "Off");
error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
extension_loaded('memcached') or die('memcached扩展未安装!');
$logPath = $_SERVER['DOCUMENT_ROOT'] . '/waf/waf.log'; //日志记录文件保存路径,$_SERVER['DOCUMENT_ROOT']是网站根目录
$fileht = $_SERVER['DOCUMENT_ROOT'] . '/waf/ban.log'; //被拉黑IP记录文件保存路径
if (!file_exists($logPath)) {
@mkdir($_SERVER['DOCUMENT_ROOT'] . '/waf/', 0777, true);
@file_put_contents($logPath, '');
@file_put_contents($fileht, '');
}
$allowtime = 2; //防刷新时间(秒)
$allownum = 5; //防刷新次数(比如2秒5次,超过就警告)
$allowRefresh = 10; //在此警告次数之后拉黑IP
$bantime = 600; //封禁时间,超时自动解封(秒)
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
$uri = $_SERVER['PHP_SELF'];
$cache = new Memcached();
$cache->addServer('127.0.0.1', '11211') or die('memcached连接失败!');
$inban = $cache->get('waf-ban-' . $ip);
if ($inban) {
header("HTTP/1.1 403 Forbidden");
exit('<h1>403 Forbidden 非法访问</h1>
<p>你的请求似乎不符合常理,已被服务器防火墙拦截,如有疑问请联系管理员QQ523077333</br>如果你在开发测试过程中超频被封IP,请等待' . ($bantime / 60) . '分钟后自动解封</br>你的IP:' . $ip . '</p>');
}
$wafarr = $cache->get('waf-' . $ip);
if (!$wafarr) {
$wafarr = ['path' => $uri, 'time' => time() $allowtime, 'sum' => 1, ];
$cache->set('waf-' . $ip, $wafarr, time() $allowtime);
} else {
if ($wafarr['sum'] > $allownum) {
$wafsum_arr = $cache->get('waf-sum-' . $ip);
if (!$wafsum_arr) {
$wafsum_arr = ['sum' => 1, ];
$cache->set('waf-sum-' . $ip, $wafsum_arr, time() $bantime);
} else {
if ($wafsum_arr['sum'] > $allowRefresh) {
$cache->set('waf-ban-' . $ip, 1, time() $bantime);
file_put_contents($fileht, $ip . "n", FILE_APPEND);
} else {
$wafsum_arr['sum'] ;
$cache->set('waf-sum-' . $ip, $wafsum_arr, time() $bantime);
}
}
file_put_contents($logPath, $ip . '--' . date('Y-m-d H:i:s', time()) . '--' . $uri . "n", FILE_APPEND);
header("HTTP/1.1 403 Forbidden");
exit("请求频率QPS超过限制,请酌情访问,多次提醒后会封禁IP!");
} else {
$wafarr['sum'] ;
$cache->set('waf-' . $ip, $wafarr, $wafarr['time']);
}
}