此网站是自己做买的VPS服务器,然后自己搭建的WEB服务网站,从操作系统到网站搭建都是自己搞的,然最近几个月以来,网站的IP越来越多,可更多的IP是各种肉鸡,采集内容IP,而我的服务器资源总是有限,就导致此网站近几个月又来经常性的崩溃,或者是内存不足,CPU资源不足等等,使用网站访问异常,
由于网站的经常性出错问题,导致近一个月百度搜索来源的IP几乎近于0,也联系了服务器的提供商腾讯云,不过都只是问了个寂寞,对问题没什么实际办法。只能自己折腾,
最近几天通过从网络上查找 解决办法,通过以下几进应该对垃圾IP也一定的限制,通过近两天的观察,现服务器基本正常了,
1.安装Nginx免费防火墙 8.1
这步应该是最基本的,这步应该控制了大部分的垃圾IP。由于我用的是宝塔服务搭建的WEB服务,但他的Nginx防火墙是收费的,所以我选择了软件商店中的第三方软件“Nginx免费防火墙 8.1”,功能上,我把“User-Agent过滤”设置成444错误,这样能直接拒绝问题的AGENT的访问,这能加快些速度。
同时在原来的规则的基础上,增加过滤规则:
(SemrushBot|Barkrowler|AhrefsBot|opensiteexplorer|petalsearch|Googlebot|Nexus|WOW64|YisouSpider|amazonbot|CFNetwork)
这样来把一些不需要的访问控制了,不让他访问。
2.流量控制
通过上面的防火墙后,还发现有两个情况没办法控制 ,
- 同一IP,同一时间段内大量访问,且User-Agent相同,此种IP应该是为采集网站内容的,但GOOGLE的爬虫也是类似这样的访问,,
- 同一IP,同一时间段内访问少量,但User-Agent不同,此种IP正常情况的访问应该是一个大公司的IP,然后内部很多人用这个公网IP访问我的网站,但我的就一小网站,这种情况应该会很少,所以应该完全的非法的。
为解决上面两种,我在网站模板的HEAD文件中增加一个流水控制 ,下面的代码,
大概的意思 是:
1.在40分钟内,如同一IP访问网站20次以内,都可正常访问,当20以上时会提示出错,30次以上就会禁IP 2小时。
2.在40分钟内,如同一IP访问网站,如User-Agent改变(用户正常通过浏览器访问此值 应该是不会变的)时,第三次改变User-Agent就把访问次数设置为20次,这样就相当于已访问20次,下一次打开网站就会报403出错了。
以下是代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
<head> <?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 = 2400; //防刷新时间(秒) $allownum = 20; //防刷新次数(比如40分钟20次,超过就警告),一般用户很少会访问20页以上 $allowRefresh = 10; //在此警告次数之后拉黑IP $bantime = 7200; //封禁时间,超时自动解封(秒) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']; $uri = $_SERVER['PHP_SELF']; $userAgent = $_SERVER['HTTP_USER_AGENT'];//User-Agent $cacheKey = md5($clientIp . $userAgent); $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>你的请求似乎不符合常理,已被服务器防火墙拦截,等30分钟再访问吧,如有疑问请联系管理员QQ415402519</br>如果你在开发测试过程中超频被封IP,请等待' . ($bantime / 60) . '分钟后自动解封</br>你的IP:' . $ip . '</p>'); } //file_put_contents($fileht, $ip . $userAgent . "\n", FILE_APPEND); $wafarr = $cache->get('waf-' . $ip); if (!$wafarr) { $wafarr = ['path' => $uri, 'time' => time() + $allowtime, 'sum' => 1 , 'Agent1' => $cacheKey , 'Agent2' => '' , 'Agent3' => '' ]; $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 { if ( ($wafarr['Agent1'] !== $cacheKey ) and ($wafarr['Agent2'] !== $cacheKey) and ($wafarr['Agent3'] !== $cacheKey ) ) { file_put_contents($fileht, $ip . 'key不同' . $wafarr['Agent3'] . '--' . $cacheKey . "\n", FILE_APPEND); if ( $wafarr['Agent1'] == '' ) { $wafarr['Agent1'] = $cacheKey; file_put_contents($fileht, "Agent1 为空\n", FILE_APPEND); } elseif ( $wafarr['Agent2'] == '' ) { $wafarr['Agent2'] = $cacheKey; file_put_contents($fileht, "Agent2 为空\n", FILE_APPEND); } elseif ($wafarr['Agent3'] == '' ) { $wafarr['Agent3'] = $cacheKey; file_put_contents($fileht, "Agent3 为空\n", FILE_APPEND); } else { //ip 相同,三次Agent不同 $wafarr['sum'] = $allownum; file_put_contents($fileht, "三次以上Agent不同,将被禁用IP\n", FILE_APPEND); } } $wafarr['sum']++; $cache->set('waf-' . $ip, $wafarr, $wafarr['time']); } } ?> |
3.安装memcached
上面的代码使用了memcached做缓存处理,所以需要PHP的程序上安装一下memcached插件,如下图