1、改造网站本身前端代码,尽可能的将静态资源使用cdn方式调用,图片通过js生成,减少对自身服务器的请求
#1、免费好用的cdn库推荐,比如调用jquery、tailwind、font-awesome等开源插件,可以直接通过cdn来调用 https://www.bootcdn.cn/ https://cdnjs.com/ #2、一些简单的图片可以通过原生绘图canvas实现;个人微信、公众号等二维码可以通过qrcode插件生成 <script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
2、后端使用Redis缓存,在数据量大和访问频繁的情形下,Redis缓存能显著提升网站的性能
具体参考之前的文章:《cc防护经验分享一:分享一个Redis缓存类,兼容redis和文件缓存》
步骤1和2在正常访问,没有攻击的情况下,对网站性能提升是非常有帮助的;但是如果遇到了cc攻击,前面2个优化步骤对于服务器攻击问题的解决还是杯水车薪,遇到cc攻击后网站打开将非常缓慢,像最近我的服务器每天上百万独立IP的攻击,网站本身优化后还是基本打不开,解决的办法是想办法拦截异常的IP
3、初级限制,对各种web软件做好初级设置,我这里使用的是宝塔面板
1、设置php,找到网站对应php版本,在"性能调整"那里,先把限制设置严格点,比如: max_children = 6 80 //允许创建的最大子进程数,80是后期服务器攻击被拦截稳定后的推荐值(4G内存方案),下面类似 start_servers = 2 10 //起始进程数(服务启动后初始进程数量) min_spare_servers = 2 10 //最小空闲进程数(清理空闲进程后的保留数量) max_spare_servers = 2 30 //最大空闲进程数(当空闲进程达到此值时清理) //redis数据库存储数据会占用内存,要记得预留一定量的内存冗余给redis,比如1G或者更多 //参数调高会让CPU消耗会降下来,内存消耗提升,这个需要根据自己服务器实际配置情况做调整 2、设置nginx,同样在"性能调整"那里,根据自己服务器的配置先设置适当严格点,比如: worker_connections = 20000 //最大并发链接数 3、设置fail2ban,这个是防护关键之一,前期攻击大也可以设置严格点 #3.1 比如单个网站参数:表示如果有某个IP在300s内,有2次异常访问,就拦截6000s; 这个可以等后面访问正常了,根据实际情况适当设置宽泛一点 --最大重试次数:2 --周期:300 --禁止时间:6000 #3.2 另外,等后期Redis防护生效而且稳定了,可以关闭sqlite数据库,进一步提升fail2ban性能 #复制一份/etc/fail2ban/fail2ban.conf为fail2ban.local(这样即使升级fail2ban,自定义配置也不受影响), 然后将dbfile = /var/lib/fail2ban/fail2ban.sqlite3改成 --dbfile = none #3.3 定期清理fail2ban日志,这里我把每周清理fail2ban、网站和maillog日志写到一个脚本了,见第4大步骤 4、网站流量限制:宝塔面板-网站-设置-流量限制,可以对每个网站的如下参数做限制, 能一定程度上做到异常拦截(可以在网站的错误日志里查看效果): 4.1 并发限制:如50,限制当前站点最大并发数 4.2 单IP限制:如3,限制单个IP访问最大并发数 4.3 流量限制:如100,限制每个请求的流量上限(单位:KB) 5.开启宝塔自带的系统防火墙,这个也非常重要 不过要注意测试下百度等蜘蛛抓取是否正常,可以将百度的爬虫IP加入防火墙白名单: 116.179.32.0/24 116.179.37.0/24 220.181.108.0/24 123.125.66.0/24
4、定期清理fail2ban、网站和maillog日志,一方面可以降低存储空间,另一方面可以提升fail2ban性能
可以根据实际情况,在宝塔计划任务里面,设置清理时间,比如每隔7天的半夜1点50清理一次
# 1、清理fail2ban日志,清空日志文件内容,但不删除文件本身(防止服务报错)
echo "" > /var/log/fail2ban.log
# 2、清理maillog日志,强制清空 maillog 文件内容,保留文件本身
> /var/log/maillog
# 3、清理7天以上的统计日志(如果有统计日志而且占用空间比较多才加上这条)
find /home/server/site_total/data/cache/all_ip_cache -type f -mtime +7 -delete
# 4、清理网站的日志
#find /www/wwwlogs -name "*.log" -exec rm -rf {} \;
#find /wwwlogs -name "*.log" -exec rm -rf {} \;
#/etc/init.d/nginx restart
#service mysqld restart
# 遍历并清空所有日志文件
for log in /www/wwwlogs/*.log; do
truncate -s 0 "$log"
done
5、开启Redis数据库存储异常访问IP,这一步是最重要的,等有异常IP自动写入Redis数据库,在访问具体网站的时候,先验证当前访问IP是否在异常IP数据库里,如果在则直接返回不做后面处理,具体参考之前的文章:
《cc防护经验分享二:redis在fail2ban中的应用,提升fail2ban防护性能》
这个是半天多时间的拦截情况,效果还是非常明显,原来50多M的带宽占用,降到了10M以内;理论上,时间越久,拦截效果越好,而不会像之前那样,时间越久防护性能越低;而且拦截的IP还可以做一个API接口,供服务器以外的其他网站共享使用

最后,如果确实没有攻击,网站流量还是很高,可能就是真实访客,需要升级服务器扩容了
6、后续观察和优化,经过10多天的拦截防护,服务器逐渐趋于稳定,拦截的IP快到110万了
6.1 网站加速:这个时候可以针对一直处于攻击状态的网站开启cdn加速处理(有交互内容,缓存更新不方便,我现在关闭了)

如果是用的宝塔面板,最新版本里有2个免费的cdn,腾讯云EdgeOne免费CDN 1.3和CloudFlare免费CDN 1.0.1,每个CDN可以绑定一个域名,特别是EdgeOne免费CDN 1.3,生效比较快,不限流量,目前我有个被攻击非常厉害的网站绑定后,异常带宽占用在一定程度上得到了缓解。

6.2 将某些爬虫加入防火墙黑名单:网站平稳运行了一段时间,再也没有出现过之前那种四五十M带宽的消耗情况,不过逐渐每天还是有15M多带宽的消耗,导致网站打开还是有点慢;平时就一些小网站,访问量也不高,看访问统计,有的网站每天只有几个IP,消耗的流量却在5个G以上,这明显不正常,想了很多方法拦截都无效,最后看日志全是国外AI和搜索引擎的爬虫,从访问日志里将这些IP统计出来直接加入防火墙黑名单,网站访问一下恢复正常了
原来这些爬虫模拟真实用户访问,可以直接绕开前面的防护,所以真是拿他们没办法,现在直接拉人黑名单一劳永逸


6.3 彻底屏蔽国外爬虫,步骤6.2对于正在大量爬取网站的国外IP,确实能起到紧急拦截的作用;但是如果后期又有新的爬虫来爬取网站,又需要手动发现异常IP并加入黑名单,还是挺麻烦的;经过继续测试,写一个允许爬虫和禁用爬虫的全局配置文件,然后在网站配置那里引入,是一个终极解决方案
1、写一个允许国内爬虫访问和国外爬虫屏蔽的配置文件deny_spider.conf 放到/www/wwwroot/common/目录,点击下载deny_spider配置文件2、宝塔面板-网站-对应网站-设置-配置文件,在server节点引入配置文件引入 #屏蔽国外爬虫 include /www/server/nginx/conf/deny_spider.conf;
3、重新加载nginx配置使配置生效
4、测试配置是否生效 测试放行:curl -I -A "Baiduspider" -k https://www.test.com 测试拦截:curl -I -A "AhrefsBot" -k https://www.test.com
开启拦截后,网站消耗带宽进一步减少,下行带宽甚至一度降到了100K以内(最开始cc防住之前有2M以上攻击,cc防住之后也有500k以上的攻击),原来自己网站每天平时很多国外爬虫来爬取

6.4 进一步优化,最终版本:将查询redis数据库异常IP库功能,从应用层网站入口文件移除,然后放到web服务层,进一步提升性能;要在nginx查询redis数据库,这里需要用到lua模块,下面是配置步骤:
1、切换nginx服务器,在宝塔面板管理后台,切换nginx不会影响网站配置 软件商店—>搜索“OpenResty”,会弹出nginx服务器—>设置—>版本切换—>选择“openresty-1.27” 2、编写脚本deny_ip.lua,核心功能是检测当前访问IP,如果在IP白名单则放行,如果在redis数据库黑名单则屏蔽 放到/www/wwwroot/common,下载下载IP黑白名单检测脚本deny_ip.zip 3、引用脚本,对应网站—>设置—>配置文件,将脚本引入进来,保存即可生效 #屏蔽redis数据库里黑名单ip access_by_lua_file /www/wwwroot/common/deny_ip.lua;4、如果重新修改了脚本,只需要在nginx服务器那里,重载配置即可生效
可以和前面的6.3国外爬虫功能组合到一起,逻辑更通顺,网站的配置文件里引入一个即可
下载屏蔽国外爬虫和黑名单组合deny_spider_ip #屏蔽国外爬虫和黑名单ip,合并前2个配置 access_by_lua_file /www/wwwroot/common/deny_spider_ip.lua;# 测试正常访问——返回正确内容 curl -H "User-Agent: Mozilla/5.0" http://www.test.com # 测试百度爬虫(通过User-Agent放行)——返回正确内容 curl -A "Baiduspider/2.0" http://www.test.com # 测试GPTBot拦截——返回403,Blocked Spider Bot curl -A "GPTBot" http://www.test.com # 测试Redis黑名单——返回403,Blocked IP redis-cli SET "ip_110_191_43_78" "1" EX 3600 curl -H "User-Agent: Mozilla/5.0" -H "X-Forwarded-For: 110.191.43.78" http://www.test.com
后续优化,上面步骤针对cc攻击是没有问题的,但是如果遇到大流量DDOS攻击,那是完全没法了,如果有经济预算,可开启ddos高防,如果没有,可以通过下面命令观察带宽消耗和占用带宽前10的IP,然后加入上面的redis数据库黑名单,可以起到一定的防护效果
高峰期达到70多M带宽消耗,只有临时关闭网站了,所有软件层面的防护无效1、安装iftop (以CentOS为例) yum install iftop -y 2、运行iftop,监控外网网卡(通常是eth0或eth1),加上-P可以显示端口,有助于判断攻击类型 圈起来的地方显示的是自己的带宽和下行带宽,如果自己的带宽有几十M那明显被DDOS攻击了 iftop -i eth0 -p
3、查看带宽使用前10的IP,将消耗带宽很厉害的IP加入Redis黑名单IP库 加黑名单之前可以打开百度,输入IP,会显示自己的IP地址,然后点击查看更多>,可以输入其他IP查看更多信息。 包括风控标签,如果被标记存在多个风控标签,比如5个以上,那基本就是爬虫IP或者其他非法IP了,可以将其永久拉人黑名单 iftop -P -n -t 2>&1 | head -30
总结,本文分享了网站安全防护设置的一些常用方法,特别是开启Redis数据库存储异常访问IP并验证,对cc攻击是非常有效的;当cc攻击被拦截成功后,对于一些异常访问的国外爬虫IP,通过将IP直接加入黑名单,或者在nginx配置文件里直接屏蔽的方法,对于类似于DDOS攻击是非常有效的。这2个方法应该是本文最核心的方法,目前作者服务器CPU、内存、带宽现在都非常正常,读者可以根据实际情况,把前面限制比较严格的有些设置适当调宽泛一点,比如php的性能调整、网站的限流设置、fail2ban的cc防护限制、Redis里存储异常IP的时间等,进一步提升网站性能。

2、宝塔面板-网站-对应网站-设置-配置文件,在server节点引入配置文件引入
#屏蔽国外爬虫
include /www/server/nginx/conf/deny_spider.conf;
3、重新加载nginx配置使配置生效
4、测试配置是否生效
测试放行:curl -I -A "Baiduspider" -k https://www.test.com
测试拦截:curl -I -A "AhrefsBot" -k https://www.test.com

4、如果重新修改了脚本,只需要在nginx服务器那里,重载配置即可生效
# 测试正常访问——返回正确内容
curl -H "User-Agent: Mozilla/5.0" http://www.test.com
# 测试百度爬虫(通过User-Agent放行)——返回正确内容
curl -A "Baiduspider/2.0" http://www.test.com
# 测试GPTBot拦截——返回403,Blocked Spider Bot
curl -A "GPTBot" http://www.test.com
# 测试Redis黑名单——返回403,Blocked IP
redis-cli SET "ip_110_191_43_78" "1" EX 3600
curl -H "User-Agent: Mozilla/5.0" -H "X-Forwarded-For: 110.191.43.78" http://www.test.com
1、安装iftop (以CentOS为例)
yum install iftop -y
2、运行iftop,监控外网网卡(通常是eth0或eth1),加上-P可以显示端口,有助于判断攻击类型
圈起来的地方显示的是自己的带宽和下行带宽,如果自己的带宽有几十M那明显被DDOS攻击了
iftop -i eth0 -p
3、查看带宽使用前10的IP,将消耗带宽很厉害的IP加入Redis黑名单IP库
加黑名单之前可以打开百度,输入IP,会显示自己的IP地址,然后点击查看更多>,可以输入其他IP查看更多信息。
包括风控标签,如果被标记存在多个风控标签,比如5个以上,那基本就是爬虫IP或者其他非法IP了,可以将其永久拉人黑名单
iftop -P -n -t 2>&1 | head -30
