SSH 密钥登录配置好后仍被要求输密码/登录失败的排查
配好 SSH 密钥登录后,一敲 ssh,服务端还是弹出 password 提示,或者直接报 Permission denied (publickey)。密钥明明生成了,公钥也放进了 authorized_keys,为什么就是认不出来?这类问题九成出在三个地方:文件权限、sshd 配置、密钥文件格式。下面按排查顺序逐一讲清楚。
一、先分清三种现象
第一种:提示输入密码,输入密码能登录,说明 SSH 服务、网络和账号都没问题,只是公钥认证被服务端跳过了。第二种:直接报 Permission denied (publickey),连密码都不让输,说明服务端只开了公钥认证,或者密码认证也被关了。第三种:提示 UNPROTECTED PRIVATE KEY FILE,这是客户端私钥权限太宽。先分清现象,再决定查哪一端。
二、最容易踩的坑:权限
OpenSSH 对权限非常严格,权限一错就静默拒绝公钥,服务端日志里往往只留一句 Authentication refused: bad ownership or modes。记住三组数字:用户家目录 755,.ssh 目录 700,authorized_keys 600,私钥默认也是 600。
先在服务端执行 ls -ld ~ ~/.ssh ~/.ssh/authorized_keys,逐项核对。不对就用 chmod 700 ~/.ssh 和 chmod 600 ~/.ssh/authorized_keys 改回来。还要注意属主:如果 .ssh 目录或 authorized_keys 属于 root,当前用户是读不到的,也会被拒绝。家目录被写成 777 时,sshd 出于安全考虑同样会拒绝公钥。很多人用 sudo 复制公钥时顺手把属主改成了 root,这就是典型的人为失误。客户端也要检查私钥权限:chmod 600 ~/.ssh/id_ed25519。
三、sshd 配置没有生效
权限没问题,就去看 /etc/ssh/sshd_config,关键项是 PubkeyAuthentication yes 和 AuthorizedKeysFile .ssh/authorized_keys。注意文件里经常有重复项,后面的会覆盖前面的,只看第一行可能被骗。改完配置必须重载或重启 sshd,否则改了也白改:systemctl reload sshd 或 systemctl restart sshd。有些发行版在 sshd_config.d 目录里还有额外配置文件,优先级更高,也容易被忽略。顺便确认 AllowUsers、DenyUsers 没有把当前用户排除在外。
四、文件格式和密钥本身
authorized_keys 里的每一行都要是一行完整的公钥,不能换行,也不能带 Windows 回车符。从网页或聊天工具复制公钥时,很容易带进换行或不可见字符,整行就失效了。检查办法:ssh-keygen -l -f ~/.ssh/authorized_keys,看能不能读出指纹;也可以用 cat -A 看行尾是不是多了 ^M,有的话用 dos2unix 去掉。
另外要确认放进 authorized_keys 的是公钥 id_ed25519.pub,而不是私钥 id_ed25519。把私钥传上去不但登录不了,还是一次泄漏。老旧的 ssh-rsa 在新版本默认配置下可能被禁用,优先用 ed25519 重新生成一对密钥再试。客户端用 ssh-add -l 列出已加载的密钥,确认要用的那一把在里面。
五、用日志定位,别靠猜
在客户端用 ssh -vvv user@host 看详细握手过程,重点看 offering public key、Server accepts key、sign_and_send_pubkey 这几行:卡在哪一步,问题就在哪一端。客户端 offering 了密钥但服务端没有接受,问题大概率在服务端权限或配置;客户端根本没有 offering,问题在客户端密钥加载或 ssh_config。
服务端看日志:journalctl -u sshd,或 /var/log/auth.log、/var/log/secure,搜索 Authentication refused、bad ownership、Failed publickey。还有一个实用技巧:用 /usr/sbin/sshd -T 查看当前生效的完整配置,确认改的那几项是不是真的生效了。
六、排查清单
家目录 755、.ssh 目录 700、authorized_keys 600 且属主正确;私钥 600;sshd_config 里 PubkeyAuthentication 是 yes 且配置已重载;authorized_keys 每行完整、无回车符;确认放的是公钥不是私钥;客户端用 ssh -vvv 看握手卡在哪一步;服务端用 journalctl 看拒绝原因。最后提醒一句:每次只改一个地方,改完马上验证,多个改动一起上,出问题就不知道是哪一个引起的。
- 点赞
- 收藏
- 关注作者
评论(0)