本系列:SSH 安全加固实战(共 5 篇) ① 为什么你的 SSH 正在裸奔 → ② 先读懂配置文件再动手 → ③ 用密钥认证告别密码 → ④ 限制谁能登录、从哪里登录 → ⑤ 防暴力破解与安全审计(本篇,终篇)

前四篇把"门"层层收窄:密钥认证堵死了密码爆破,白名单与防火墙限制谁能进、从哪进。最后一篇做主动拦截持续运维——用 fail2ban 自动封禁恶意来源、看懂日志做审计,最后给出一份贯穿全系列的自测清单,让你能一键检查自己到底加固到几成。

用 fail2ban 自动封禁爆破来源

fail2ban 会监控登录日志,一旦某个 IP 短时间内连续失败多次,就自动调用防火墙把它封掉一段时间。这是对"扫描爆破"最直接的反制。

安装

# Debian / Ubuntu
sudo apt update && sudo apt install -y fail2ban

# RHEL / CentOS / Rocky
sudo yum install -y fail2ban     # 或用 dnf

配置

fail2ban 的主配置是 /etc/fail2ban/jail.conf,但我们不要改它,而是新建本地覆盖文件,避免升级被覆盖:

sudo cp /etc/fail2ban/jail.local /etc/fail2ban/jail.local 2>/dev/null
# 若上面报错说明文件不存在,直接新建:
sudo vim /etc/fail2ban/jail.local

写入最小可用配置,为 SSH 开启默认 jail:

[DEFAULT]
bantime  = 1h        # 封禁时长,可写成 10m / 1h / 1d
findtime = 10m       # 统计窗口
maxretry = 5         # 窗口内失败 5 次即封禁

[sshd]
enabled = true
backend = systemd    # 用 systemd 日志;传统 syslog 发行版可省去或改 auto

提示框:backend = systemd 适用于使用 journald 的较新发行版(Ubuntu 18.04+、RHEL 7+)。老系统(纯 syslog)通常不写这行或设为 auto 让 fail2ban 自动判断。拿不准就删掉该行用默认。

启用并查看状态:

sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

status 输出的 Banned IP list 若出现 IP,说明 fail2ban 已开始工作。可以用下面命令手动解除误封的 IP:

sudo fail2ban-client set sshd unbanip 你的IP

提示框:别把自己封了。 若你在用 fail2ban 的同时又频繁输错密码、或防火墙白名单没覆盖自己,容易误封。封了也别慌:多数云控制台可"重开实例"或通过带外 VNC 登录后 fail2ban-client set sshd unbanip 解封。生产上建议先把自己的固定 IP 加入白名单(fail2ban 的 ignoreip)再启用。

jail.local[DEFAULT] 段加:

ignoreip = 127.0.0.1/8 ::1 你的固定IP

日志审计:看清攻击长什么样

加固不是设完就完,要会"看日志"判断是否仍在被攻击、有没有异常登录。

查看失败登录(爆破痕迹):

# Debian / Ubuntu
sudo grep 'Failed password' /var/log/auth.log | tail -30

# RHEL / CentOS / Rocky
sudo grep 'Failed password' /var/log/secure | tail -30

# 使用 systemd 的发行版通用写法
sudo journalctl -u ssh -u sshd --since "1 hour ago" | grep -iE 'failed|invalid|break-in'

看成功登录(谁在登、从哪登):

sudo grep 'Accepted' /var/log/auth.log | tail -30      # Debian/Ubuntu
sudo grep 'Accepted' /var/log/secure | tail -30        # RHEL 系

提示框:日志路径与格式因发行版而异——auth.log(Debian/Ubuntu)vs secure(RHEL),见第 1 篇提示。用 journalctl 是较新发行版的统一入口。

想一眼看到"最频繁的来源 IP",可统计:

sudo grep 'Failed password' /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr | head -20

提示框:字段位置会随日志格式和发行版变化,awk 取列未必通用,仅作演示思路。生产更稳的做法是看 fail2ban 的 banned 列表、或用 lastb(若启用 btmp)看爆破来源。

查看最近登录记录:last(看 /var/log/wtmp)和 lastb(看失败的 /var/log/btmp):

last | head -20      # 最近成功登录
sudo lastb | head    # 最近失败尝试(爆破来源)

审计要点:

  • 有大量来自陌生 IP 的 Failed password → 正常,公网常态;fail2ban 会拦截。若持续暴涨再排查是否配置未生效。
  • 出现你不认识的 Accepted → 立刻核查是否有人入侵(改密、踢掉会话、查进程)。可 w 查看当前在线用户。
  • 关注异常时段的登录、非白名单账号的 Accepted、可疑的反弹 shell 进程。

长期维护:安全不是一劳永逸

  • 及时升级 OpenSSHsudo apt upgrade openssh-serversudo yum update openssh-server,修复 CVE。
  • 关注安全公告:留意发行版安全通告中的 openssh 条目,重大漏洞时第一时间升级。
  • 定期轮换密钥:长期使用的密钥可定期换新(删旧公钥、生成新 key、清理 authorized_keys 里的陈旧公钥)。
  • 只开最小端口、最小账号:随时间推移新增的服务/账号记得及时清理,别让入口悄悄变宽。
  • 做好备份与逃生通道:无论怎么加固,都保留一个带外管理入口(云控制台/VNC/串口)作为兜底。

全系列最终自测清单

把五篇的成果汇总成一份可复检清单,建议定期跑一遍:

认证与账号

  • 仅使用密钥登录,PasswordAuthentication no(第 3 篇)
  • 私钥设了 passphrase 且保管妥当,公钥权限正确(700 / 600)(第 3 篇)
  • PermitRootLogin no(或 prohibit-password),日常用普通账号 + sudo(第 2、4 篇)
  • 配置了 AllowUsers / AllowGroups 白名单(第 4 篇)

会话与资源

  • LoginGraceTimeMaxAuthTriesMaxStartups 已限制(第 4 篇)
  • ClientAliveInterval / ClientAliveCountMax 已清理空闲会话(第 4 篇)

网络层

  • 防火墙仅放行可信来源 IP 到 SSH 端口(ufw / firewalld)(第 4 篇)
  • (可选)已改非默认端口并写入 ~/.ssh/config(第 4 篇)

主动防御与维护

  • fail2ban 已启用,ssh-agent jail 生效,ignoreip 含自己(本篇)
  • 会看认证日志判断异常(auth.log / secure / journalctl)(本篇)
  • OpenSSH 保持最新,密钥定期轮换,保留带外逃生通道(本篇)

全系列回顾

至此,从"为什么 SSH 会裸奔"到"如何系统加固",五篇层层推进:

  1. 认知:SSH 是唯一远程入口,默认不设防,公网被爆破是常态。
  2. 基础:读懂 sshd_config,学会安全改配置不锁死自己。
  3. 核心:ed25519 密钥认证,彻底告别密码登录。
  4. 纵深:账号白名单 + 会话限制 + 防火墙来源白名单 + 禁用 root 直登。
  5. 收尾:fail2ban 主动封禁 + 日志审计 + 长期维护自测。

安全没有终点,是一个持续收紧、验证、维护的过程。愿你的服务器大门从此清净。

我们下个系列再见。