SSH 密钥登录配置与暴力破解防护实战指南

为什么你的服务器每天都被暴力破解

把服务器 IP 暴露在公网上的那一刻起,扫描器就盯上你了。它们不需要针对你,只是全网段批量扫描 22 端口,然后用常见用户名加密码字典轮番尝试。你的服务器可能每天收到几十上百次失败的登录尝试,而你毫无察觉。只要某天密码足够弱、或者被撞库撞中,服务器就沦陷了——挂马、挖矿、发垃圾邮件,一夜之间全来了。本文要解决的,就是把这个最大的风险点彻底关掉:用 SSH 密钥替代密码登录,再配合 fail2ban 兜底。

一、为什么密钥比密码安全

密码登录的问题在于「可猜测」。无论密码设得多复杂,只要还支持密码认证,攻击者就可以无限次尝试;字典里没有就换下一个,一万次不行就十万次。而密钥登录基于非对称加密:私钥保存在你本地,公钥放到服务器。登录时服务器用公钥验证你的私钥签名,整个过程没有任何可猜测的口令在网络上传送,也就没有「猜」的窗口。

现在主流推荐使用 Ed25519 算法:密钥短、生成快、安全性高,OpenSSH 7.0 以上版本都支持。相比传统的 RSA 2048,Ed25519 在同等安全强度下性能更好,签名验证更快,也更不容易被暴力破解。除非有旧系统兼容性要求,否则新环境直接用 Ed25519 就行。

二、生成 SSH 密钥对

在本地电脑(不是服务器上)执行:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519

参数说明:-t ed25519 指定算法;-a 100 表示对私钥做 100 轮 KDF 拉伸,防止私钥文件被偷走之后被离线暴力破解;-f 指定保存路径。过程中会提示你设置 passphrase(口令),强烈建议设置:即使私钥文件泄露,没有口令也无法使用。

生成后检查文件权限:~/.ssh 目录权限应为 700,私钥 id_ed25519 应为 600,公钥 id_ed25519.pub 可以是 644。权限过宽的话 SSH 会直接拒绝使用该密钥并报 bad permissions。

三、把公钥安装到服务器

最简单的方式是用 ssh-copy-id:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@服务器IP

它会自动把公钥追加到服务器上对应用户的 ~/.ssh/authorized_keys,并设置好文件权限。如果服务器上没有 ssh-copy-id,也可以手动操作:把公钥内容追加到服务器的 ~/.ssh/authorized_keys 文件末尾,然后确认该文件权限为 600、~/.ssh 目录权限为 700。

安装完成后先测试一次:ssh user@服务器IP,如果不再提示输入密码,说明密钥登录已经生效。注意:这一步只是「增加」了密钥登录方式,密码登录还没关,所以即使测试失败也不会被锁在门外,可以反复调试。

四、禁用密码登录(最关键的一步)

密钥验证通过之后,才轮到关闭密码登录。编辑服务器的 /etc/ssh/sshd_config,找到或添加以下几行:

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
MaxAuthTries 3

PermitRootLogin prohibit-password 的意思是允许 root 用密钥登录、但不允许 root 用密码登录,兼顾便利和安全;MaxAuthTries 3 限制单次连接最多尝试 3 次认证,进一步压缩暴力破解空间。改完先做语法检查:

sshd -t

确认没有语法错误再重载服务:systemctl reload ssh(不同发行版服务名可能是 sshd 或 ssh)。

一定要记住:改完配置后,先新开一个终端窗口,用密钥登录一次确认没有问题,再关掉旧的连接。否则一旦配置写错,你可能会把自己锁在服务器外面,只能去 VPS 商的控制台用网页终端或救援模式自救。

五、用 fail2ban 兜底

密钥登录关闭了密码通道,但 sshd 本身还会记录失败的认证尝试,加上 fail2ban 可以自动封禁反复试探的 IP,双保险。安装并启用:

apt install fail2ban    # Debian/Ubuntu
yum install fail2ban    # CentOS/RHEL

在 /etc/fail2ban/jail.local 中添加:

[sshd]
enabled = true
maxretry = 5
bantime = 3600

含义:同一个 IP 在短时间内认证失败 5 次,封禁 1 小时。fail2ban 通过分析 /var/log/auth.log(或 /var/log/secure)里的认证失败记录来触发封禁,原理简单、效果实在。封禁的 IP 可以随时用 fail2ban-client set sshd unbanip 解封。

想看看到底有多少人盯上你的服务器,可以翻一翻认证日志:journalctl -u ssh | grep "Failed password" 或者直接执行 lastb 查看失败的登录记录。看到大量陌生 IP 的失败记录不用慌,这正是 fail2ban 要处理的对象;真正需要警惕的是某个陌生 IP 曾经登录成功,那说明服务器可能已经失守,要立即排查。

六、进阶:加上双因子认证

如果服务器上跑着重要业务,或者账号权限比较大,可以在密钥之上再加一道双因子认证(2FA),让安全等级再上一个台阶。最常见的方案是 Google Authenticator:服务器安装 libpam-google-authenticator 后,用户执行 google-authenticator 命令生成一次性验证码并绑定手机,然后在 sshd 配置里开启键盘交互认证,要求先验证密钥、再输入 6 位动态码。

配置要点:sshd_config 中设置 AuthenticationMethods publickey,keyboard-interactive,并确保 ChallengeResponseAuthentication 已启用。注意 2FA 的配置过程同样有把自己锁在门外的风险,务必保持一个已登录的会话不要退出,配置完成、新终端验证通过后再关闭旧会话。对个人站长来说,密钥登录已经能挡住绝大多数攻击,2FA 属于锦上添花的纵深防御,按需选择即可。

七、多台服务器的密钥管理

如果你手里有多台服务器,建议维护一个 ~/.ssh/config 文件统一管理,避免记 IP 和用户名:

Host web1
    HostName 1.2.3.4
    User root
    Port 22
    IdentityFile ~/.ssh/id_ed25519

这样以后只需要 ssh web1 就能登录,还能针对不同服务器指定不同密钥、不同端口。关于「一台服务器一把密钥还是共用一个密钥」:个人站长图省事可以共用一把,但要注意私钥文件的管理——任何一台机器上的私钥泄露,等于所有服务器都暴露。有条件的话,重要服务器单独生成密钥。

如果怀疑私钥泄露,立即在服务器上把对应的公钥从 authorized_keys 中删掉,然后重新生成密钥对并安装,同时检查服务器上有没有新增的可疑登录记录。

八、常见问题排查

  • 登录时报 Permission denied (publickey):先确认服务器上 authorized_keys 内容没被截断、权限是否为 600;再确认 sshd_config 里 PubkeyAuthentication 是 yes 且已重载服务。
  • 报 bad permissions:本地私钥权限太宽,执行 chmod 600 ~/.ssh/id_ed25519 即可。
  • 忘记 passphrase:私钥口令无法找回,只能重新生成密钥对并重新安装公钥。
  • 脚本和定时任务需要免密登录:可以使用 ssh-agent 临时加载带口令的密钥;或者为低风险内网场景单独生成一把无口令密钥,但务必严格限制它的使用范围和目标主机。

九、总结

整个过程就三步:本地生成密钥、公钥装到服务器、关闭密码登录。做完这三步,暴力破解基本就对你失效了,因为攻击者连「猜」的机会都没有。再叠加 fail2ban,连试探都会被自动封禁。这套组合是个人站长最基础也最值得做的安全投入,半小时搞定,换来的是长期安心。

常见问题(FAQ)

Q:把 SSH 端口从 22 改成别的有用吗? A:治标不治本。全网扫描器会扫描所有端口,改端口只能降低被随机扫描命中的概率,不能阻止定向攻击。根本解法还是密钥登录加禁用密码认证。

Q:Windows 电脑怎么用? A:Windows 10 以上自带 OpenSSH 客户端,在 PowerShell 里执行同样的 ssh-keygen 和 ssh-copy-id 命令即可;老系统也可以配合 PuTTY 系列工具,流程一样。

Q:密钥丢了怎么办? A:在服务器上删掉旧公钥,重新生成一对并安装。只要密码登录已经关闭,删掉公钥就等于收回了那台丢失设备的访问权。

Q:光靠密钥登录就够了吗? A:对个人站长来说基本够了。如果服务器上有重要业务或多人协作,可以再加双因子认证作为纵深防御,具体配置见上文第六节。

Last modification:August 5th, 2026 at 08:07 am

Leave a Comment