SSH 安全加固实战:从密钥登录到 fail2ban 防爆破一次讲清


很多站长把 VPS 买回来、网站部署上线之后,就很少再管服务器本身了。可几乎每台公网服务器都在被扫描爆破——凌晨两三点,SSH 日志里全是 Failed password 的刷屏,有人用字典一轮一轮地试 root 密码。SSH 默认的"密码登录 + root 账号 + 22 端口"组合,在这种攻势面前就是一座不设防的门。

这篇文章不聊虚的,按真实操作顺序,把 SSH 从密钥登录、关闭密码、禁 root、改端口到 fail2ban 自动封禁一次讲清楚。文章里的命令都经过验证,照着敲就能用,适合买了 VPS 之后想给服务器真正上一把锁的站长。

一、为什么 SSH 一直是爆破重灾区

SSH 是运维服务器的唯一入口,几乎每台公网 VPS 都会长期暴露在扫描器的火力之下。攻击者的思路很简单:默认端口 22 不用猜,root 用户名不用猜,剩下就是拿弱口令字典暴力尝试。只要你的密码稍微弱一点——比如纯数字、生日、网站域名——被撞开只是时间问题。

更重要的是,爆破本身几乎无成本:脚本一天可以扫几万个 IP,撞开一台就算赚到。所以不要心存侥幸"我的服务器没什么价值",对攻击者来说,一台能登录的肉鸡就是价值。防爆破的思路也不是"让密码更复杂",而是从根上让密码登录这条路走不通。

二、第一步:生成密钥对,配置免密登录

密钥登录的原理是"一对钥匙":私钥留在本地,公钥放到服务器。登录时服务器用公钥验证你的身份,没有私钥的人即使知道用户名也无从下手。先在本地电脑(不是服务器)上生成密钥对:

# 本地执行,一路回车即可
ssh-keygen -t ed25519 -C "你的备注,如 laptop"

生成的文件默认在 ~/.ssh/ 下,id_ed25519 是私钥(绝不要外传),id_ed25519.pub 是公钥。然后把公钥传到服务器:

# 本地执行,需要输入一次服务器密码
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@你的服务器IP

如果你的系统没有 ssh-copy-id,也可以手动追加:把 id_ed25519.pub 的内容贴到服务器的 ~/.ssh/authorized_keys 文件里,一行一个,权限检查一下:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

配置完成后,先不要急着关密码登录。开一个新终端窗口测试:ssh root@你的服务器IP,如果不再要密码、直接进系统,说明密钥登录已经生效。

三、第二步:关闭密码登录,只留密钥

确认密钥登录没问题后,就把密码登录这条路彻底堵死。编辑 SSH 配置文件:

nano /etc/ssh/sshd_config

找到(或新增)以下几项:

PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password

改完先检查语法,再平滑重载配置:

sshd -t
systemctl reload sshd

这里有个关键习惯:改 SSH 配置前,永远先确认密钥能登录;改完重载后,也永远开一个新终端先试一次再关旧连接。一旦自己把自己锁在门外,只能去商家后台用网页版 VNC 救,非常麻烦。如果确实需要 root 直接登录,PermitRootLogin 用 prohibit-password(仅允许密钥)比 yes 安全得多。

四、第三步:关闭 root 远程登录,用普通用户管理

root 是每个系统都存在的账号,天然是爆破的首选目标。更稳妥的做法是:建一个普通用户日常登录,需要提权时再用 sudo。先创建用户并加入 sudo 组:

# Ubuntu/Debian
useradd -m -s /bin/bash deploy
usermod -aG sudo deploy
passwd deploy

# CentOS/RHEL
useradd -m -s /bin/bash deploy
usermod -aG wheel deploy
passwd deploy

把公钥也装到这个用户的 authorized_keys 里(方法同上),然后用新用户测试登录:

ssh deploy@你的服务器IP
sudo whoami   # 输入密码后应输出 root

确认新用户能正常用 sudo 之后,再把配置文件里的 root 登录彻底关掉:

PermitRootLogin no

从此公网再也无人能以 root 身份直连你的 SSH。

五、第四步:修改 SSH 端口(可选但有效)

默认 22 端口让扫描器连猜都不用猜。改个高位端口,能把绝大多数自动扫描直接挡在外面——扫描器通常只扫常用端口,不会对每个 IP 的 6 万多个端口做全量爆破。修改 sshd_config:

Port 22022

同样 sshd -t 检查语法、systemctl reload sshd 重载。然后先别关 22,新开一个终端用新端口测试:

ssh -p 22022 deploy@你的服务器IP

测试通过后,记得在防火墙(ufw / firewalld / 宝塔安全 / 商家安全组)里放行新端口、移除 22 端口,避免旧端口留个永久的后门。

六、第五步:用 fail2ban 自动封禁爆破 IP

密钥登录和关 root 之后,密码爆破基本失效了,但日志里依然会有大量"猜用户名"的噪音,而且更隐蔽的暴力尝试仍然存在。fail2ban 就是干这个的:它监控登录日志,同一 IP 失败次数达到阈值,就自动用防火墙把它封禁一段时间。

安装:

# Ubuntu/Debian
apt install -y fail2ban

# CentOS/RHEL
yum install -y fail2ban

默认配置在 /etc/fail2ban/jail.conf,不建议直接改它(升级会被覆盖),而是新建一个本地覆盖文件:

nano /etc/fail2ban/jail.local

写入:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true

含义:10 分钟内失败 5 次,封禁 1 小时。启动并验证:

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

如果日志显示某个 IP 已经被 ban,说明规则正在生效。日常也可以手动拉黑一个 IP:fail2ban-client set sshd banip 1.2.3.4。

七、第六步:日常检查与审计

安全配置做完不是终点,建议把下面几条养成习惯:

  • 定期看登录日志:`grep -i failed /var/log/auth.log`(Ubuntu)或 `/var/log/secure`(CentOS),确认爆破来源和频率变化。
  • 检查 authorized_keys:`cat ~/.ssh/authorized_keys`,确认里面每一行公钥都是你自己的,防止有人偷摸加后门。
  • 观察 fail2ban 状态:`fail2ban-client status sshd`,看封禁数量和最新封禁来源,异常骤增往往意味着有新的攻击源。
  • 保持系统更新:`apt update && apt upgrade -y`(或 yum update),安全补丁不及时打,再强的 SSH 配置也挡不住系统本身的漏洞。

八、进阶:叠加安全组 / 防火墙白名单

如果服务器只给固定的几个人用(比如个人网站后台、自己的服务器),可以更进一步:在商家安全组或系统防火墙里,把 SSH 端口只对常用 IP 白名单放行。这样非白名单 IP 连端口都摸不到,比任何口令方案都干净。

# 以 ufw 为例,只允许白名单 IP 访问 SSH
ufw allow from 你的固定IP to any port 22022 proto tcp
ufw deny 22022
ufw enable

注意:固定 IP 的判定要谨慎,家庭宽带公网 IP 可能会变,先确认自己的出口 IP 稳定再上白名单,否则可能把自己锁在外面。

九、结语

SSH 安全没有一劳永逸,但把这几步做下来:密钥登录、关闭密码、禁 root、改端口、fail2ban 封禁,服务器就从一个"谁都能撞的门"变成了一扇上了多重锁的门,绝大多数自动爆破和脚本攻击都会被挡在外面。

这套流程对所有 Linux VPS 通用,不管是宝塔用户还是纯命令行的 LNMP 用户,都建议照着走一遍。遇到问题先在本地看 SSH 日志(/var/log/auth.log),大多数登录失败的原因都能在里面找到答案。也欢迎在评论区聊聊你自己踩过的坑和防爆破的经验。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

SSH 安全加固实战:从密钥登录到 fail2ban 一次讲清

域名解析实战:从 A 记录、CNAME 到 TTL,域名解析设置与不生效排查一次讲清

评 论