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

前两篇铺垫完毕,这一篇是全系列最关键的一步:用公钥密钥认证替换密码登录。原理上,密钥是一个几乎无法被"猜中"的数字签名,比任何密码都难破解得多。配好它之后,你就能彻底关闭 PasswordAuthentication,从根上断掉爆破这条路。

为什么选 ed25519

现代 OpenSSH 支持多种密钥算法,最常用的两种:

  • ed25519:曲线加密,密钥极短(公钥约几十字节)、生成快、安全性强,是当前推荐首选
  • RSA 4096 位:兼容老设备,但密钥长、生成慢,安全性也不优于 ed25519。

结论:新环境一律用 ed25519。只有当你的旧服务器、网络设备或运维脚本只认 RSA 时才退回去用 RSA 4096。

第 1 步:在你自己的电脑上生成密钥对

密钥要在**客户端(你自己的电脑)**生成,不是在服务器上生成。先看你电脑上有没有:

ls -l ~/.ssh/id_ed25519* 2>/dev/null

没有则生成(一路回车即可,-t 指定算法,-C 只是给个备注便于识别):

ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/id_ed25519

提示框:要不要 passphrase? 建议设一个口令保护私钥,即使私钥文件泄露攻击者也无法直接使用;搭配 ssh-agent(见第 4 步)只需输入一次。若嫌麻烦可留空,但私钥文件务必只有你能读。

生成后会得到两个文件:

  • ~/.ssh/id_ed25519 —— 私钥,绝不能外泄
  • ~/.ssh/id_ed25519.pub —— 公钥,可以放心上传到服务器

私钥就是你"钥匙",公钥是配给服务器这把锁的"齿模"。私钥泄露 = 家门钥匙掉了,务必保管好。

第 2 步:把公钥安装到服务器上

推荐用 ssh-copy-id 一键完成(它会自动把公钥追加到服务器的 ~/.ssh/authorized_keys 并修好权限):

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip

按提示输入当前仍生效的密码,完成后即安装成功。

手动安装(备选)

若没有 ssh-copy-id,可以手动做。在服务器上创建必要目录并修正权限(这一步的权限是常见坑):

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

然后把公钥内容追加进 authorized_keys

# 在你电脑上把公钥内容复制出来
cat ~/.ssh/id_ed25519.pub
# 在服务器上把那段内容追加进去
echo "ssh-ed25519 AAAA...你的公钥..." >> ~/.ssh/authorized_keys

权限要点(必须满足)

authorized_keys 及其所在目录权限不对,OpenSSH 会直接忽略这个文件:

  • ~(家目录)不可被 group/other 写
  • ~/.ssh 应为 700
  • ~/.ssh/authorized_keys 应为 600

第 3 步:验证能否用密钥登录

先用密钥试试能否登录,不要立刻关密码

ssh -i ~/.ssh/id_ed25519 user@server_ip

能免密登进(或只需输 passphrase),说明密钥已生效。可以再加 -v 查看详细握手过程确认用的是 publickey 而非 password

ssh -v user@server_ip 2>&1 | grep -i "authentications that can continue"

第 4 步:用 ssh-agent 告别反复输 passphrase

给私钥设了 passphrase 的话,可以启动 ssh-agent 只输入一次,之后自动使用:

eval "$(ssh-agent -s)"          # 启动 agent
ssh-add ~/.ssh/id_ed25519       # 添加私钥(输入一次 passphrase)

提示框:macOS 用钥匙串管理、Linux 桌面端常配 GNOME Keyring,机制各有差异,但概念一致——agent 在你登录期间替你保管已解锁的私钥。重启后需要重新 ssh-add(或配置开机加载)。

第 5 步:给常用主机配别名

~/.ssh/config(客户端配置,还记得吗?)里给常用服务器配置别名,省去记 IP 和端口:

Host myserver
    HostName 你的服务器IP或域名
    User     你的用户名
    Port     22
    IdentityFile ~/.ssh/id_ed25519

之后直接 ssh myserver 即可。注意这里的文件是你电脑上的 ~/.ssh/config(不是服务器的 /etc/ssh/sshd_config)。

第 6 步:彻底关闭密码登录(安全地)

确认上面都能用密钥登录后,再回到服务器改 sshd_config。先开一个新终端窗口作为逃生会话保持登录,再:

sudo vim /etc/ssh/sshd_config

把密码登录关掉:

PasswordAuthentication no

语法校验 + 重载(不改服务名,参考第 2 篇,Debian 用 ssh、RHEL 用 sshd):

sudo sshd -t && sudo systemctl reload ssh    # Debian/Ubuntu
sudo sshd -t && sudo systemctl reload sshd   # RHEL/CentOS/Rocky

再次强调顺序:先确认密钥能登录 → 保留逃生会话 → 才改 no → 另开终端用密钥连一次验证 → 确认无误后再考虑关闭逃生会话。

禁用密码前的自检清单

准备关掉密码前,逐条打勾:

  • 能从客户端用密钥登录成功(ssh -v 确认走的是 publickey)
  • 公钥、~/.sshauthorized_keys 权限正确(700 / 600)
  • 保留了一条已登录的逃生会话
  • 服务器仍可访问(IP/端口没写错)
  • 若私钥设了 passphrase,确认已记住或已配 ssh-agent

应急预案:如果不慎把自己锁在门外,而你有云服务商控制台或服务器机房,可走VNC / 控制台/单用户模式进入系统把 PasswordAuthentication 改回 yes,或临时用 root 登录恢复。这也是为什么生产环境建议保留带外(out-of-band)管理入口。

本篇小结

  • 首选 ed25519 密钥,私钥私钥绝不能外泄,建议设 passphrase。
  • ssh-copy-id 上传公钥,手动上传要特别注意 700 / 600 权限。
  • 先验证密钥登录成功,再开逃生会话,最后才关 PasswordAuthentication
  • ssh-agent + ~/.ssh/config 别名能大幅提升日常体验。

下一篇预告

密码已关闭,爆破这个最大的威胁基本堵死。第 4 篇继续收窄攻击面:限制谁能登录、从哪些来源登录,以及用防火墙只放行可信 IP

现在就去生成你的 ed25519 密钥并完成上面的自检清单。我们下一篇见。