服务器突然CPU飙升卡顿?用宝塔大日志分析排查恶意IP

核心导读:记录一次小站被爬虫和高频请求刷爆 CPU 的排查过程,通过宝塔大日志分析工具快速捞出异常 IP,并配置规则阻断的实操备忘。

昨天下午两点多,收到阿里云的告警短信,一台跑着个人博客和测试接口的 2核4G 服务器 CPU 占用突然冲到了 100%,连 SSH 终端敲回车都有明显的粘滞感。

打开宝塔面板看监控,发现磁盘 IO 和带宽基本正常,但 PHP-FPM 进程占满了 CPU 核心,网站前台已经偶发 504 Gateway Timeout。凭借以往的经验,大概率是某些无良蜘蛛或者扫描脚本在拼命刷接口。由于平时访问量不大,单日访问日志文件有接近 1.5G,直接用 tailvim 翻找效率太低,顺手记录一下这次用大日志分析工具快速揪出“真凶”的排查过程。

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

日志文件一旦超过几百兆,宝塔默认的在线文本编辑器就会打不开或者提示文件过大。这时候面板自带的【日志切割】和【大日志分析】功能就很实用。

在宝塔【网站】管理列表中,找到出问题的站点,点击右侧的【设置】->【网站日志】。如果文件太大,可以直接在左侧菜单栏点击【日志安全】或打开【大日志分析工具】(部分旧版本在软件商店的系统工具分类里)。

排查时主要看三个维度:

  1. IP 访问排行:按请求总数降序排列。正常访客浏览文章,一分钟顶多产生几十次静态资源请求;如果某个 IP 在十分钟内发起了几千甚至上万次请求,基本可以直接认定为恶意爬虫或攻击。
  2. URL 访问排行:看看异常流量集中在哪里。这次我排查出来,高频 IP 全在死磕 /wp-login.php 和带搜索参数的模糊查询接口,导致后端一直在反复查库并消耗 PHP 线程。
  3. 状态码分布:如果出现大量 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 规则里加上频率限制:
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; }
这样单 IP 每秒最多只能请求 2 次,超出直接返回 503,防止后端计算资源被耗尽。如果觉得手动写 Nginx 配置繁琐,也可以使用宝塔自带的 Nginx 防火墙插件,里面有现成的 URL 防刷和单 IP 频次限制开关,效果是一样的。

4. 针对不同规格服务器的日志与处理建议

不同配置的机器对高频请求和日志读写的承受能力差异很大,平时在做运维配置时可以参考下面的经验值:

服务器配置推荐日志保留天数日志单文件切割上限PHP-FPM max_children 建议应对思路
1核 / 1G 内存3 天50 MB5 - 8内存极易溢出,必须开启日切/大小切分,频繁访问建议全靠静态缓存扛
2核 / 2G-4G 内存7 天200 MB15 - 30可开启大日志分析留存现场,关键动态接口必须加上限流规则
4核 / 8G 以上15 - 30 天500 MB40 - 80算力充裕,重点防范短时间突发 CC,建议配合系统级防火墙策略

小机器最怕的不仅是 CPU 跑满,还有日志无限膨胀后吃爆磁盘 inode 和可用空间。建议在宝塔的【计划任务】里,把站点日志切分任务加上去(例如每天凌晨 00:00 自动切割,并自动清理 7 天前的压缩归档),这样下次再需要排查日志时,文件体积可控,分析工具秒开,不至于卡死在读取步骤。

常见问题与解答 (FAQ)

Q 宝塔分析日志时提示文件过大读取超时怎么办?

可以先去 SSH 终端用 `split -b 100m access.log sub_log_` 命令把几 G 的大日志临时切成几个小文件,或者用 `grep` 过滤出当天时间段后再用面板工具分析。

Q 直接在系统防火墙封禁 IP 会影响 Nginx 日志记录吗?

会,系统防火墙(iptables)阻断发生在网络层,被拦截的数据包根本不会到达 Nginx,所以 Nginx 访问日志里不会记录这些连接,能极大减轻服务器压力。

返回运维知识库