昨天下午两点多,收到阿里云的告警短信,一台跑着个人博客和测试接口的 2核4G 服务器 CPU 占用突然冲到了 100%,连 SSH 终端敲回车都有明显的粘滞感。
打开宝塔面板看监控,发现磁盘 IO 和带宽基本正常,但 PHP-FPM 进程占满了 CPU 核心,网站前台已经偶发 504 Gateway Timeout。凭借以往的经验,大概率是某些无良蜘蛛或者扫描脚本在拼命刷接口。由于平时访问量不大,单日访问日志文件有接近 1.5G,直接用 tail 或 vim 翻找效率太低,顺手记录一下这次用大日志分析工具快速揪出“真凶”的排查过程。
1. 临时恢复与现场确认
机器卡死的时候,首先要做的是恢复业务可用性,避免影响正常访客。
先通过 SSH 连上去,用 top 确认占用资源的进程:
bash# 确认是 php-fpm 还是 nginx 在狂转 top -c
如果发现几十个
php-fpm: pool www 都在跑满,可以先在宝塔面板的【软件商店】里重载一下 PHP 服务,或者在终端执行平滑重启:bash# 平滑重启 PHP-FPM(以 PHP 8.1 为例) systemctl reload php-fpm-81
这招可以临时杀掉挂起的长耗时连接,让 CPU 回落。但这只是治标,几分钟后恶意请求一进来依然会打满,必须立刻找到对应的源 IP。
2. 用大日志分析工具定位高频 IP
日志文件一旦超过几百兆,宝塔默认的在线文本编辑器就会打不开或者提示文件过大。这时候面板自带的【日志切割】和【大日志分析】功能就很实用。
在宝塔【网站】管理列表中,找到出问题的站点,点击右侧的【设置】->【网站日志】。如果文件太大,可以直接在左侧菜单栏点击【日志安全】或打开【大日志分析工具】(部分旧版本在软件商店的系统工具分类里)。
排查时主要看三个维度:
- IP 访问排行:按请求总数降序排列。正常访客浏览文章,一分钟顶多产生几十次静态资源请求;如果某个 IP 在十分钟内发起了几千甚至上万次请求,基本可以直接认定为恶意爬虫或攻击。
- URL 访问排行:看看异常流量集中在哪里。这次我排查出来,高频 IP 全在死磕
/wp-login.php和带搜索参数的模糊查询接口,导致后端一直在反复查库并消耗 PHP 线程。 - 状态码分布:如果出现大量 404、403 或者 502/504,说明对方在盲扫漏洞或者已经打穿了后端处理上限。
通过分析工具直接导出的 IP 排序,我当场揪出了两个来自某海外机房的 IP,在过去 1 小时内发起了接近 4.8 万次 POST 请求。
3. 防火墙与 Nginx 规则阻断
定位到 IP 和具体的攻击路径后,处理起来就简单了,根据自身配置有几种不同深度的阻断方案:
方案 A:直接拉黑 IP(系统级)
如果只发现两三个孤立的机房 IP,可以直接在宝塔【安全】页面的系统防火墙中,将对应 IP 加入屏蔽列表(选择 Drop 丢弃或 Reject 拒绝)。这种方式直接在 iptables / nftables 层面丢包,完全不经过 Nginx 和 PHP,消耗资源最少。方案 B:针对路径进行 Nginx 频率限制
如果是很多轮换 IP 盯着特定接口(比如搜索页、登录接口)扫,单纯封 IP 很容易封不完。这时需要在网站配置的 Nginx 规则里加上频率限制:这样单 IP 每秒最多只能请求 2 次,超出直接返回 503,防止后端计算资源被耗尽。如果觉得手动写 Nginx 配置繁琐,也可以使用宝塔自带的 Nginx 防火墙插件,里面有现成的 URL 防刷和单 IP 频次限制开关,效果是一样的。nginx# 在 http 块定义限流区域(可在宝塔 Nginx 主配置里添加) limit_req_zone $binary_remote_addr zone=search_limit:10m rate=2r/s; # 在站点配置的 location 中应用 location /search { limit_req zone=search_limit burst=5 nodelay; # 传递给后端的 PHP 处理 try_files $uri =404; include pathinfo.conf; }
4. 针对不同规格服务器的日志与处理建议
不同配置的机器对高频请求和日志读写的承受能力差异很大,平时在做运维配置时可以参考下面的经验值:
| 服务器配置 | 推荐日志保留天数 | 日志单文件切割上限 | PHP-FPM max_children 建议 | 应对思路 |
|---|---|---|---|---|
| 1核 / 1G 内存 | 3 天 | 50 MB | 5 - 8 | 内存极易溢出,必须开启日切/大小切分,频繁访问建议全靠静态缓存扛 |
| 2核 / 2G-4G 内存 | 7 天 | 200 MB | 15 - 30 | 可开启大日志分析留存现场,关键动态接口必须加上限流规则 |
| 4核 / 8G 以上 | 15 - 30 天 | 500 MB | 40 - 80 | 算力充裕,重点防范短时间突发 CC,建议配合系统级防火墙策略 |
小机器最怕的不仅是 CPU 跑满,还有日志无限膨胀后吃爆磁盘 inode 和可用空间。建议在宝塔的【计划任务】里,把站点日志切分任务加上去(例如每天凌晨 00:00 自动切割,并自动清理 7 天前的压缩归档),这样下次再需要排查日志时,文件体积可控,分析工具秒开,不至于卡死在读取步骤。