由于typecho是动态的博客系统,因此单纯的使用GET请求博客动态内容都能对网站造成非常大的负载压力。
注意:这篇文章只是用来防御脚本小子的F5攻击,实际防御能力有限,无法防御刷流量,无法防御大佬的攻击。做站千万别惹大佬,犯错了及时认怂才是王道。
如果是需要防御dd源站ip,可以看这篇博客,有少许的效果。
博客防御体系 - 利用阿里云安全组防御dd
原理
typecho由于是动态博客,单纯的搜索接口甚至刷新页面,都需要服务器的CPU进行处理,因此即使套上了CDN也防御不了CC。也就是站长们常说的F5都能打死网站。
因此,就需要从软件和硬件两个方面入手:提高服务器的负载能力(堆硬件)以及配置nginx/apache/MySQL的策略。
操作流程
站库分离
通过分离网站后端与数据库,减少服务器在高负载情况下CPU与内存的消耗,防止出现服务器在高负荷情况下连web软件都挂掉/ssh都进不去的尴尬情况。
博客搬迁,分离站库的过程:
救援服务器的记录
简单的来讲就是把博客和图床的数据库地址指向数据库服务器内网ip,数据库服务器修改配置,仅对博客数据库开放ip,加上阿里云账户直接内网不通策略,其实还算安全。
阿里云的北京学生机内网带宽只有0.5G,平常够用,但在被C请求过程中,内网带宽成了瓶颈之一。
趁着阿里云给大学生的活动才能弄到第二台服务器,平常我可买不起。
其实最优解是购买阿里云/腾讯云的云数据库,但我没钱,并且云数据库对并发限制的非常死。
因此我使用的是:一台服务器作为网站后台服务器,一台服务器单纯作为数据库服务器。
土豪大佬直接购买的时候请注意要用ECS,阿里云轻量服务器没法通过阿里云内网互相连接。
(假)负载均衡
我这有从同学那蹭来了两台活动服务器,和我博客网站后台服务器和数据库服务器都在阿里云北京地区,虽然都是1Mb的带宽,但通过(假)负载均衡,最大可以拥有4Mb的出口带宽。
大致流程就是,同学的两台活动服务器加上数据库的服务器通过阿里云CEN,在内网反向代理网站服务器,再在cdn处的回源ip处填这四台服务器的ip。(你也可以平常选择使用两台服务器,另外两台作为热备份)
配置数据库
我是用的APPNODE,它的数据库管理功能有个优化建议
,我是按照这个来处理MySQL的参数的。
需要注意的是,为了处理海量数据,如果你的服务器数据库性能还不错的话,最大连接数max_connections
请调到最大:16384
配置nginx与PHP
我用的是APPNODE,它只有nginx,因此我这里只讲在appnode上配置nginx的参数。
为了增加nginx对动态请求并发处理能力,我们需要配置以下两个地方。
进入APPNODE - 网站设置
- 优化 - 连接优化 - 保持连接请求数限制(10000次)
- PHP - PHP进程 - 按如下配置
其实我也不太清楚最好的配置参数,我也是根据我博客实际运行情况尽可能调大。
配置完成后,请重启php与nginx,使用网站上的配置检测
,检查自己的配置是否有误。
真实IP识别
在反向代理服务器 IP
里面填入127.0.0.1
与CDN的回源ip/ip段即可。
真实 IP 识别来源使用X-Forwarded-For
,腾讯云CDN与cloudflare默认都使用这个传递用户ip。其他cdn不清楚。
配置完成后使用网站上的配置检测
,检查自己的配置是否有误。我之前弄了半天都不能用,结果测试了半天才发现是在ip段后面多了个空格
0.0.0.0/0
这种自欺欺人的方法来实现真实ip识别。腾讯云CDN使用了访客来源ip来制作X-Forwarded-For
,而不是直接传递用户提供的X-Forwarded-For
,因此一般不会被欺骗。配置nginx防火墙
CC攻击防护
其实就是ngx_lua
模块,在宝塔里叫nginx防火墙,在appnode里是网站设置 - 安全
我的网站接了CDN,因此就不打开CC攻击防护
了。appnode的官方也建议不要使用。
在CDN后面打开CC攻击防护
,CDN会缓存验证页面验证,从而影响正常用户访问。
并且由于appnode的CC攻击防护验证原理:
会导致typecho+handsome无法评论(其他主题/博客我没测试过因此不清楚)
因此我在平常还是关闭吧,除非在特殊情况,我才会打开这个功能。
关于为什么不像宝塔那样使用真实ip识别后限制ip频率
大佬的回复是:
因此,appnode的选择是:测试客户端是脚本还是真浏览器。而不单纯的对ip限流。
随意拉黑ip其实毫无效果,因为真正的CC攻击甚至会用上万的ip来进行攻击。
更新:
appnode的CC防御从302跳转更新到307跳转了,现在打开了也可以评论了,因此我常开了。
但实际体验测试下发现效果不是很好,测试的时候只封了2个ip,聊有胜无吧
反代攻击防护
原理:
由于反代攻击防护
会强行压缩JS文件导致我的图床和博客的Dplayer挂掉,因此我选择关闭。
并发与请求限制
打开博客的并发限制
与请求限制
位置在:网站设置 - 安全
启用整站并发限制,启用单IP并发限制,启用IP请求限制,启用整站请求限制
由于我不清楚我博客具体情况,因此我选择了默认配置,实际上默认配置完全足够。
(真)负载均衡
我不会做动态网站的负载均衡,四台服务器也不需要这个。
静态网站还好,动态网站配置(真)负载均衡的话需要配置redis,貌似很麻烦的样子(主要是怕后面迁移博客太麻烦了)。
好像有那种通过docker实现单台服务器的负载均衡,以后有机会在其他网站测试。
配置系统
在测试过程中,出现了Too Many Open Files,其原因是Linux / Unix 设置了软硬文件句柄和打开文件的数目限制。
因此,我在appnode - 系统信息 - 系统配置 设置了最大监控文件个数(fs.inotify.max_user_watches
)与最大文件打开数量(DefaultLimitNOFILE)
均设置成:65535
保存设置后,重启服务器。
调试
测试
在仅做了站库分离
与配置nginx与PHP
,嫂子在对我的搜索接口进行10K/s的post攻击后,我博客仅坚持了几秒,PHP就挂了。
在做好站库分离、(假)负载均衡、配置数据库、配置nginx与PHP、配置nginx防火墙后,嫂子通过GET,对我的时光机界面进行了30K/S的请求攻击,勉强能响应正常用户的访问,评论就算了。
设置了软硬文件句柄和打开文件的数目后我还没测试,不知道实际效果如何。
分析解决方法
通过分析错误日志,瓶颈还是在MySQL的服务器与网站后台服务器的通信带宽上,在嫂子测试过程中,直接跑满了500Mb内网带宽。PHP与nginx的报错倒没看到有多少。
解决方法有两种,一种是加钱,阿里云的服务器配置越高内网带宽也越大。还有一种就是做(真)负载均衡,用多台数据库服务器共同分担压力。
其他
在测试过程中,腾讯云的云监控成功的给我发了短信提示,间接测试了我的云监控配置的还不错。
TODO
- 写个python脚本,处理nginx的日志,生成ip段来填入Nginx防火墙的黑名单中/用api填入腾讯云cdn。这也是为什么我要弄真实ip识别。
- 利用另一台服务器+安全狗一类软件做简易版WAF。
此处评论已关闭