限制对 WordPress 特定网址的访问频率,比如一个 IP 地址每秒只能访问一次,每分钟一次,甚至每小时一次,可以有利避免对 wp-login.php 进行暴力破解登录、对 admin-ajax.php 恶意提交文章评论、刷手机短信验证码,以及 CC 攻击你的 API 接口等。
当限制请求次数在 1 分钟 1 次之内时,比如:1 分钟 1 次、 1秒 1 次、20 秒 1 次,推荐 使用 Nginx 限制访问频率。当限制频率超过了 1 分钟 1 次,比如 20 分钟 5 次、2 小时 3 次时,就要使用如下方法了。
准备工作
为了提高性能,代码使用了 memcached 缓存数据到服务器的内存,因此你的服务器必须安装 memcached 。宝塔面板—— PHP——扩展选项,找到 memcached 点击安装, 注意看最后一个字母是 d 。PHP 版安装就绪,再去软件商店搜一下,确认软件版的是否也已安装。
代码部署
代码分为两部分,第一部分是自定义一个控制访问频率的函数,第二部分是使用WordPress 动作钩子,将频率控制函数挂在到所需要控制页面 PHP 上。原理不懂没事,只要你明白步骤分两步走就行。
第一步:添加频率控制函数
你可以自行调整防刷新时间、次数、警告次数、解封时间等,在代码中用 //
对关键内容做了注释,一看就能明白在哪里修改。
/** * 使用教程:https://www.cccitu.com/5079.html * 限制URL访问频率的函数,对管理员登录状态以外的访问起效 * 可以通过动作钩子引用此函数,限制特定的页面 * 该函数主要参考了https://www.tjit.net/194.html */ function cccitu_waf() { if(!current_user_can( 'manage_options' )){ //对登录后的网站管理员访问不起作用。该函数是 WordPress 网站独有,非 WordPress 请不要使用此判断 ini_set("display_errors", "Off"); error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING); extension_loaded('memcached') or die('memcached扩展未安装!'); $logPath = $_SERVER['DOCUMENT_ROOT'] . '/cccitu-waf/cccitu-waf.log'; //日志记录文件保存路径,在网站根目录的 cccitu-waf 文件内内可以查看 $fileht = $_SERVER['DOCUMENT_ROOT'] . '/cccitu-waf/cccitu-ban.log'; //被拉黑IP记录文件保存路径 if (!file_exists($logPath)) { @mkdir($_SERVER['DOCUMENT_ROOT'] . '/cccitu-waf/', 0777, true); @file_put_contents($logPath, ''); @file_put_contents($fileht, ''); } $allowtime = 60; //防刷新时间,以秒为单位,具体数字可以根据需要自行调整 $allownum = 3; //防刷新次数,比如上面设置的房刷新时间为60,这里设置为3,那么60秒访问次数超过3次就会引发警告 $allowRefresh = 1; //在此警告次数之后拉黑IP,写 1 则是警告一次后,将会拉黑该访问IP地址 $bantime = 3600; //封禁时间,超时自动解封,以秒为单位,3600 即为 1个小时后解封该IP地址,注意时间最长不能超过30天 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; $uri = $_SERVER['REQUEST_URI']; $cache = new Memcached(); $cache->addServer('127.0.0.1', '11211') or die('memcached连接失败!');//如果你更改了memcached 默认的IP或端口,请根据实际情况修改 $inban = $cache->get('cccitu-waf-ban-' . $ip); if ($inban) { header("HTTP/1.1 403 Forbidden"); //可以自行修改h1和p标签内的提示内容,当被封IP访问此页面时显示。 exit('<h1>403 Forbidden 非法访问</h1> <p>非法访问</p>'); } $wafarr = $cache->get('cccitu-waf-' . $ip); if (!$wafarr) { $wafarr = [ 'path' => $uri, 'time' => time() + $allowtime, 'sum' => 1, ]; $cache->set('cccitu-waf-' . $ip, $wafarr, time() + $allowtime); } else { if ($wafarr['sum'] > $allownum) { $wafsum_arr = $cache->get('cccitu-waf-sum-' . $ip); if (!$wafsum_arr) { $wafsum_arr = [ 'sum' => 1, ]; $cache->set('cccitu-waf-sum-' . $ip, $wafsum_arr, time() + $bantime); } else { if ($wafsum_arr['sum'] > $allowRefresh) { $cache->set('cccitu-waf-ban-' . $ip, 1, time() + $bantime); file_put_contents($fileht, $ip . "\n", FILE_APPEND); } else { $wafsum_arr['sum']++; $cache->set('cccitu-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('cccitu-waf-' . $ip, $wafarr, $wafarr['time']); } } } }
将以上代码,复制到主题 functions.php 最后一行,如果最后一行是 ?>
,则要将代码放在 ?>
的上一行。functions.php 文件在哪里?在服务器 /wp-content/themes/ 目录的主题文件夹中。
如果你无法进入服务器,也可以进入:网站后台——外观——主题编辑器——模板函数(functions.php) 进行操作。
第二步:限制具体的网址
/** * 使用教程:https://www.cccitu.com/5079.html * 限制 wp-login.php 的访问频率,可以防止恶意注册和登录暴力破解 */ add_action('login_enqueue_scripts', function(){ cccitu_waf(); });
/** * 使用教程:https://www.cccitu.com/5079.html * 限制使用 admin-ajax.php 进行 ajax 异步加载的数据提交的频率,一般文章评论,短信发送等功能都使用了此功能 * 注意,这里所限制的是通过 post 和 get 提交数据,测试效果时,要以 域名/admin-ajax.php?action=cccitu 的形式访问 */ add_action('admin_init', function(){ if (wp_doing_ajax()){ cccitu_waf(); } });
/** * 使用教程:https://www.cccitu.com/5079.html * 限制任意一个网址 */ add_action('init', function(){ $cccitu_get_url = $_SERVER['REQUEST_URI']; $cccitu_waf_check = false; //例如要限制 https://www.cccitu.com/5065.html ,就将主域名后面的 /5065.html 填写到代替换的单引号内 if(strpos($cccitu_get_url, '待替换') !== false) { $cccitu_waf_check = true; break; } if ($cccitu_waf_check){ cccitu_waf(); } });
/** * 使用教程:https://www.cccitu.com/5079.html * 限制任意多个网址 */ add_action('init', function(){ //例如要限制 https://www.cccitu.com/5065.html ,就将主域名后面的 /5065.html 填写到代替换的单引号内 //当三个网址以上时,自己在括号内以英文的逗号,单引号的形式添加即可,比如('/5065.html','admin-ajax.php','wp-login.php') $cccitu_waf_kay = array('/5065.html','admin-ajax.php'); $cccitu_get_url = $_SERVER['REQUEST_URI']; $cccitu_waf_check = false; foreach($cccitu_waf_kay as $word) { if(strpos($cccitu_get_url, $word) !== false) { $cccitu_waf_check = true; break; } } if ($cccitu_waf_check){ cccitu_waf(); } });
为尽量减少影响 WordPress 的性能,虫子菌针对不同的限制需求,写了以上不同的代码,当多个代码都能满足你的需求时,建议优先选择专一的,其次才是通用的。将所选代码同样复制进 functions.php 的最后一行,也就是第一步代码的下面,当第一步和第二步代码都加入后,即可生效。
暂无评论
要发表评论,您必须先 登录