
核心要点(TL;DR)
- SSH 暴露公网必然被扫,关闭密码登录改用密钥是最有效的第一道防线。
- fail2ban 读取日志自动封禁多次失败的 IP,可与密钥登录叠加使用。
- 改 sshd_config 前务必保留一个已登录会话,改完先 sshd -t 校验再重载。
- 加固后检查项:密码登录关闭、root 禁止直登、fail2ban 规则生效。
服务器刚上线几天,/var/log/auth.log 里就塞满了几千条 Failed password for root——这是几乎每台暴露公网的 Linux 主机都会遇到的日常。SSH 暴力破解本身不可怕,可怕的是你只改了端口就以为万事大吉。本文给出一套可直接照做的加固流程:先确认爆破规模,再用 fail2ban 自动封禁,最后关闭密码登录切换到密钥认证,全程附命令与检查清单。
一、先确认:你的 SSH 到底被扫成什么样
动手之前先看清现状,避免盲目改配置。多数发行版把 SSH 日志写在 auth.log 或 secure 中,systemd 系统也可直接查 journal。
# Debian/Ubuntu
sudo grep "Failed password" /var/log/auth.log | wc -l
# CentOS/RHEL
sudo grep "Failed password" /var/log/secure | wc -l
# 通用:查看失败登录来源 TOP10
sudo lastb | awk '{print }' | sort | uniq -c | sort -rn | head
# systemd 系统
sudo journalctl -u ssh -u sshd --since "24 hours ago" | grep -c Failed如果失败次数在几百到几万量级,说明已被持续扫描;若出现 Accepted password for 且来源陌生,则要立刻按入侵事件处理,而不只是加固。确认 PermitRootLogin 与 PasswordAuthentication 当前值:
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|port'二、fail2ban:让爆破 IP 自动进小黑屋
fail2ban 的原理很简单:持续读取认证日志,匹配失败模式,超过阈值就调用防火墙封禁该 IP 一段时间。它不替代密钥登录,但能显著降低日志噪声与撞库成功率。
安装与最小配置
sudo apt install fail2ban -y # Debian/Ubuntu
sudo yum install epel-release fail2ban -y # CentOS
sudo systemctl enable --now fail2ban不要直接改 jail.conf,新建 /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 你的办公出口IP
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s重载并验证:
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd输出中能看到 Currently banned 与 Total failed 即表示规则已生效。常用运维命令:fail2ban-client set sshd unbanip 1.2.3.4 解封误伤 IP,fail2ban-client status 查看所有 jail。若服务器使用 nftables 或 firewalld,确认 banaction 与系统防火墙匹配,否则会出现「显示已封禁但实际未拦截」的假象。
三、密钥登录:从根上关掉密码这道门
只要密码认证还开着,爆破就永远有理论成功率。切换到密钥认证是收益最高的一步。
1. 本地生成密钥并上传公钥
ssh-keygen -t ed25519 -C "ops@example" -f ~/.ssh/id_ed25519
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server没有 ssh-copy-id 时,手动追加到服务器 ~/.ssh/authorized_keys,并确保权限正确:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh2. 修改 sshd_config 并校验
关键前提:保留一个已登录的 SSH 会话不要断开,另开窗口操作。编辑 /etc/ssh/sshd_config:
PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2先做语法检查再重载,顺序不能反:
sudo sshd -t && sudo systemctl reload sshd随后新开终端用密钥登录验证成功,再关闭旧会话。若使用云厂商镜像,注意 /etc/ssh/sshd_config.d/ 下的片段可能覆盖主配置,需一并检查。
四、组合效果与配置对比
| 措施 | 拦截层 | 主要作用 | 是否可单独依赖 |
|---|---|---|---|
| 关闭密码登录 | 认证层 | 爆破直接失效 | 是,核心防线 |
| fail2ban | 主机防火墙 | 自动封禁高频失败 IP | 否,需配合密钥 |
| 安全组/防火墙白名单 | 网络层 | 缩小暴露面 | 否,粒度粗 |
| 改默认端口 | 网络层 | 减少无差别扫描噪声 | 否,仅辅助 |
可以看到,密钥登录是唯一能单独成立的手段,其余都是叠加项。想进一步收敛暴露面,可在云安全组只放行运维出口 IP,并在主机侧用 AegisX 的主机入侵检测与登录行为审计能力,对异常登录时间、异常来源地做持续监控,与 fail2ban 的即时封禁形成「拦+看」的闭环。
五、加固后检查清单
sshd -T | grep passwordauthentication输出为 no;sshd -T | grep permitrootlogin不为 yes;fail2ban-client status sshd显示 jail 已启用且有封禁记录;- 新终端密钥登录成功,密码登录被拒绝;
- 保留至少一个可用恢复通道(控制台 VNC 或跳板机账号);
- 定期轮换密钥,离职人员公钥及时从 authorized_keys 移除。
行动建议:今天就先完成「生成密钥 + 关闭密码登录」这两步,明天再补 fail2ban 与白名单。加固顺序永远是先保证自己能进得去,再关掉别人进得来的路。
常见问题(FAQ)
关闭密码登录后,我自己的电脑重装系统丢了私钥怎么办?
结论是提前准备一条带外恢复通道。可在云控制台使用 VNC/救援模式登录,或保留一个仅允许内网或跳板机访问的备用账号。更稳妥的做法是把私钥加密备份到密码管理器,并在加固前用新密钥完整测试一次登录,确认无误后再关闭密码认证。
fail2ban 封禁后,正常用户输错几次密码也会被封吗?
会,但可调。默认规则通常在 5 次失败后封禁 10 分钟,正常用户偶尔输错影响很小。你可以在 jail.local 中调整 maxretry、findtime、bantime,例如改为 5 次/10 分钟、封禁 1 小时,并对办公出口 IP 加入 ignoreip 白名单,避免团队被误封。
只改 SSH 端口能防住暴力破解吗?
不能,只能减少噪音。改端口可以避开大量无差别扫描,但针对性扫描仍能发现新端口,爆破依旧会发生。正确顺序是:先上密钥登录并关闭密码认证,再叠加 fail2ban 自动封禁,改端口仅作为降低日志噪声的辅助手段。
fail2ban 和云厂商的安全组哪个更该用?
两者互补,建议都用。安全组在云网络层拦截,粒度粗但生效早;fail2ban 在主机层根据真实登录日志动态封禁,能识别应用层爆破行为。安全组限制来源 IP 段,fail2ban 处理漏网之鱼,组合后防护更完整。
加固后怎么确认配置真的生效了?
用三步验证:执行 sshd -t 检查语法;新开终端用密钥登录成功;再用另一台机器尝试密码登录,应被拒绝。同时运行 fail2ban-client status sshd 查看当前封禁列表与失败计数,确认 jail 已启用。