SSH 密钥化改造:先保住退路再关密码登录
很多服务器入侵的起点都是同一个:SSH 密码登录开着,root 弱口令被爆破成功。把登录方式收敛到仅密钥,是性价比最高的一步加固。但真动手时最常见的翻车姿势是——改完 sshd_config、重启 sshd,密钥没配对,密码登录也关了,云控制台的 VNC 成了唯一的救命通道。
所以这套改造的核心原则只有一条:**每一步都留着退路,确认下一步真的能进,再收掉上一步的退路。**以下步骤在 Ubuntu 22.04 上验证过,其他发行版路径可能不同(比如 CentOS 的 sshd 配置位置和 SELinux 策略),需自行确认。
第一步:生成密钥并送达服务器
本地是 Windows 的话用 PowerShell 自带的 OpenSSH 即可:
ssh-keygen -t ed25519 -C "ops-laptop-2026"
把公钥送到服务器,不要手动复制粘贴(容易丢换行或结尾的注释):
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@121.37.39.242
如果这台机器已经禁用了密码登录(比如接手别人加固过的机器),ssh-copy-id 会失败,此时用另一个渠道把公钥内容追加进 /root/.ssh/authorized_keys,注意一个公钥占一行。
第二步:验证密钥登录,而且要开新会话验证
这一步很多人偷懒:在当前已登录的会话里测一下就以为没问题。错。当前会话的登录态和你要验证的「全新连接」是两回事。正确做法是另开一个终端,强制走密钥试一次:
ssh -i ~/.ssh/id_ed25519 -o PasswordAuthentication=no root@121.37.39.242
-o PasswordAuthentication=no 强制客户端不回退到密码,能提前暴露「密钥根本没生效」的问题。能进去,第一步才算过关。
第三步:排查权限——密钥被拒的头号原因
如果上一步报 Permission denied (publickey),九成不是密钥内容错了,而是权限。sshd 对权限的检查非常严格,对照排查:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R root:root /root/.ssh
ls -ld /root /root/.ssh /root/.ssh/authorized_keys
注意最后一列的输出:家目录本身不能是 777,也不能归属别人。sshd 默认配置下(StrictModes yes),只要 authorized_keys、.ssh 目录或家目录任何一级权限过宽或属主不对,公钥认证直接静默拒绝,日志里才会留痕。看日志定位:
journalctl -u ssh -n 50 --no-pager | grep -i "authentication"
常见的两条:Authentication refused: bad ownership or modes 就是权限问题;userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms 说明还在用老的 RSA 密钥且服务端算法收紧了,换 ed25519 最省事。
第四步:修改 sshd 配置,用 include 意识避开覆盖
Ubuntu 22.04 的 /etc/ssh/sshd_config 末尾有一行 Include /etc/ssh/sshd_config.d/*.conf,而云厂商镜像常在这里预置了 50-cloud-init.conf 之类带 PasswordAuthentication yes 的文件。Include 的文件先于主文件生效,你改主文件里的 PasswordAuthentication 可能不生效。稳妥做法是新建一个数字更大的覆盖文件:
printf 'PasswordAuthentication no\nPermitRootLogin prohibit-password\nPubkeyAuthentication yes\n' > /etc/ssh/sshd_config.d/60-hardening.conf
sshd -t && systemctl restart ssh
sshd -t 先做语法检查再重启,避免配置写错导致 sshd 起不来。Ubuntu 22.04 上服务名是 ssh(个别系统是 sshd),用 systemctl status ssh 确认。
第五步:不退出,用新会话做最终验证
改完配置后不要退出当前会话。另开一个新终端再连一次,确认密钥登录正常、密码登录已被拒:
ssh -o PreferredAuthentications=password root@121.37.39.242
# 期望输出:Permission denied (publickey). ← 注意括号里只剩 publickey,说明密码通道已关
看到 (publickey) 单独出现,说明密码认证已经彻底关闭;此时新会话的密钥登录成功,改造完成,旧会话可以放心退出。
报错对照表
| 现象 | 原因 | 处理 |
|---|---|---|
| Permission denied (publickey),但密钥没配错 | .ssh 或家目录权限/属主不对 | 700/600 + chown,查 StrictModes |
| bad ownership or modes 日志 | 同上,sshd 静默拒绝 | 同上 |
| key type ssh-rsa not in PubkeyAcceptedAlgorithms | 老 RSA 算法被收紧 | 换 ed25519 密钥 |
| 改了主配置密码登录还能用 | sshd_config.d 里 Include 文件优先级更高 | 建 60-xxx.conf 覆盖 |
| 重启 sshd 后服务起不来 | 配置语法错误 | 重启前先 sshd -t |
| 全都配对仍拒绝 | fail2ban 把你 IP 封了 | fail2ban-client status sshd 查 |
真被锁死了怎么办
最后留个底:如果以上全踩坑、密钥密码都进不去,用云厂商控制台的 VNC 救援登录(这也是为什么密码要留一份给 VNC 应急,而不是彻底丢弃)。进去后先看 /etc/ssh/sshd_config.d/ 里的覆盖文件,把 PasswordAuthentication no 临时改回 yes 并 systemctl restart ssh,恢复密码通道后再按上面的顺序重来。整个过程只要严格走「新会话验证再收退路」的节奏,走到锁死这一步的概率很低。
- 点赞
- 收藏
- 关注作者
评论(0)