No space left on device:服务器被 SSH 爆破到日志写满的完整排查与止血

No space left on device 的根因是 /var/log/secure 被 SSH 爆破日志写到了 4.2G、/var/log/btmp 涨到 2.8G,把根分区撑满。急救动作是截断日志文件,止血动作是关掉 SSH 密码登录。

要点速览:

  • 根因不是业务数据,是 SSH 爆破日志:secure 4.2G + btmp 2.8G
  • 排查顺序:df -h / df -i → du -sh /var/log/* → 统计来源 IP
  • 清日志必须用截断(> /var/log/secure),不能用 rm
  • 治本动作:PasswordAuthentication no,封 IP 只是打地鼠
  • 验证标准:df -h 回到正常水位,btmp 不再增长

2026 年 10 月上旬,一台业务机的 sshd 起不来,登录直接报 No space left on device。本来以为是日志写爆磁盘这种老问题,结果一查,根因是被人爆破了一整周。

故障现场是什么表现

这台机器的表现是典型的磁盘写满,但不是完全不可用:

  • 远程 ssh 登录失败,偶尔能连上,但一执行命令就报错;
  • nginx、cron 这些服务写入失败;
  • 客户端提示 Connection closed by remote host。

看到 No space left on device 先别急着删文件,按下面两步定位。

怎么区分是磁盘满还是 inode 满

两者报错一模一样,处理方式完全不同,所以第一步必须把这两条命令都跑一遍:

bash 复制代码
df -h
df -i

df -i 别跳过,inode 被打满一样会报 No space left on device。这次是根分区使用率 100%,inode 正常,属于前者。

怎么定位是哪个目录吃掉了空间

bash 复制代码
du -sh /var/log/* 2>/dev/null | sort -rh | head -10

结果很整齐:

复制代码
4.2G  /var/log/secure
2.8G  /var/log/btmp

secure 4.2G、btmp 2.8G,这就不用猜了。btmp 记录失败登录,正常服务器放几个月也就几百 K 的量级,涨到 G 级只有一种解释。顺手看下爆破规模:

bash 复制代码
lastb | head -20
wc -l /var/log/btmp

怎么查是谁在爆破

bash 复制代码
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20

Failed password for root from 1.2.3.4 port 51234 ssh2 这种格式里,从后往前数第 4 个字段就是源 IP。跑完就能看到 top 攻击源,通常前几名是同一批 IP 在几十万次地试。再看下总共有多少个来源:

bash 复制代码
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort -u | wc -l

为什么清日志不能用 rm

这是整个过程里最容易踩的坑。日志文件被 rsyslog 打开着,rm 掉之后空间不会立刻释放,df -h 还是满的,非得重启服务才行。正确做法是截断:

bash 复制代码
> /var/log/secure
> /var/log/btmp
df -h

如果打算留取证记录(我这次就留了一份),清之前先把关键片段抠出来:

bash 复制代码
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' \
  | sort | uniq -c | sort -rn > /root/attack_ips_$(date +%F).txt

怎么止血:四步,优先级从低到高

先把四步的作用和优先级说清楚,再展开具体命令:

步骤 作用 优先级 是否治本
限制日志体积(logrotate) 防止再次撑满磁盘 高 只治症状
封禁攻击源 IP 减少噪音 低 否,换 IP 即可绕过
关闭 SSH 密码登录 爆破彻底失效 最高 是
部署 fail2ban 自动封禁 中 辅助

第一步:限制日志体积

给 secure 加大轮转力度,改 /etc/logrotate.d/syslog:

复制代码
/var/log/secure {
    weekly
    rotate 4
    maxsize 200M
    compress
    missingok
    notifempty
    sharedscripts
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

journald 也顺手压一下,改 /etc/systemd/journald.conf:

复制代码
SystemMaxUse=500M
MaxRetentionSec=2week

改完 systemctl restart systemd-journald。

第二步:封禁攻击源 IP

少量 IP 直接 iptables,数量多就上 ipset,别一条条写:

bash 复制代码
ipset create blacklist hash:ip timeout 86400
while read ip; do ipset add blacklist $ip; done < <(awk '{print $2}' /root/attack_ips_$(date +%F).txt)
iptables -I INPUT -m set --match-set blacklist src -j DROP

不过说句实话,光封 IP 是打地鼠,攻击源换 IP 是秒级的。真正有效的是下面两条。

第三步:关闭密码登录(治本)

bash 复制代码
# 确认密钥能正常登录之后再执行
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sshd -t && systemctl restart sshd

密码登录一关,爆破就彻底失去了意义,btmp 基本不会再涨。这一步是整件事的转折点。

第四步:部署 fail2ban

bash 复制代码
yum install -y fail2ban
cat > /etc/fail2ban/jail.local <<'EOF'
[sshd]
enabled = true
port = ssh
maxretry = 5
findtime = 600
bantime = 86400
EOF
systemctl enable --now fail2ban
fail2ban-client status sshd

怎么验证恢复成功

bash 复制代码
df -h                        # 根分区回到正常水位
lastb | head                 # 失败登录不再疯涨
fail2ban-client status sshd  # 能看到 Banned IP list

三条都符合预期才算收工,只看到 df -h 降下来是不够的。

常见问题

报 No space left on device 一定要先删文件吗

不一定,先分清楚是磁盘满还是 inode 满。df -h 看空间,df -i 看 inode,两者的处理方式完全不同。这次是磁盘满,inode 正常。

为什么 rm 删掉大日志后 df -h 还是满的

因为文件还被 rsyslog 这类进程打开着。Linux 下删除的只是目录项,进程持有的文件描述符仍然指向数据块,空间不会释放,直到进程关闭句柄或重启。正确的清理方式是截断文件内容。

关掉密码登录之后,我自己怎么登录

提前配置好 SSH 密钥登录,确认密钥能正常登录之后再执行 PasswordAuthentication no。顺序反了就会把自己关在门外。

封 IP 能彻底解决爆破问题吗

不能。攻击源换 IP 是秒级的,封禁只降低日志噪音,不降低风险。真正的解法是关闭密码登录,让爆破在原理上失效。

btmp 和 secure 有什么区别,为什么要看两个

btmp 记录失败登录(lastb 读取),secure 记录认证过程详情。btmp 看体量和趋势,secure 看源 IP 和尝试方式,两个配合才能还原爆破规模和来源。

日志该不该直接纳入监控

建议纳入。把 secure 和 btmp 的体积纳入监控,涨幅异常基本就等于有人在敲门,比等磁盘满更早拿到信号。

日志被写满,表面是磁盘问题,根因基本都指向"机器暴露在公网 + 还开着密码登录"。清日志只是急救,PasswordAuthentication no 才是止血。遇到类似问题的,把 df -h 和 du 的结果贴评论区,我帮你看看。

相关推荐
明日清晨1 小时前
mobaxterm root身份登录Ubuntu
linux·ubuntu·postgresql
编程序的员1 小时前
使用OpenTelemetry来监控Rust应用
运维·rust·monitoring·opentelemetry
沫璃染墨1 小时前
《Linux工程实践篇(二):线程池实战——从线程安全单例到完整源码实现》
linux·开发语言·c++·单例模式·设计模式·系统架构
极光通讯1 小时前
服务器内存来料检验(IQC)实操:批次追溯、外观判定与上机验证
java·服务器·算法
Raspberry_Pi_官方账号1 小时前
Raspberry Pi Desktop 全面升级,现已登陆 PC 和 Mac
服务器·网络·macos·树莓派·raspberry pi·raspberrypios
实战派K8S&DB1 小时前
TDSQL 核心模块与进程体系
运维·数据库·分布式·sql·mysql
Rooting++1 小时前
用友打包的APP壳子怎么获取SHA1码?
运维·服务器
云飞云共享云桌面2 小时前
降本 + 护图纸:珠海制造装备工厂 SolidWorks 服务器共享设计方案
运维·服务器·制造
yumgpkpm2 小时前
(CDH 7)CDP Private Cloud Base 7.3.1 → Acceldata ODP 3.3.6.4 引擎迁移风险评估表
服务器·人工智能·hadoop·python·华为·zookeeper·hbase