SSH 密钥登录失败提示 Permission denied (publickey) 通常是因为服务器端 .ssh 目录或 authorized_keys 文件权限过于开放,或者公钥未正确写入。最推荐的处理方向是严格限制服务器端密钥文件权限,并确认 SSH 服务配置允许公钥认证。
先说结论:修复权限设置并确保公钥格式正确是解决该报错的核心步骤,适用于 Linux 服务器 SSH 配置场景。
- 先确认:服务器端 ~/.ssh 目录权限是否为 700,authorized_keys 文件权限是否为 600
- 先处理:使用 chmod 和 chown 命令修正文件归属和读写权限
- 再验证:通过 ssh -v 命令查看客户端调试日志,确认认证流程是否通过
命令速用版
如果拥有服务器终端访问权限,可直接执行以下命令修复常见权限问题:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R $USER:$USER ~/.ssh
执行完成后尝试重新登录,若仍失败需检查 SSH 服务配置。
为什么会这样
SSH 服务进程 sshd 默认开启严格模式,会检查密钥相关文件的权限和归属。
OpenSSH 出于安全考虑,如果私钥文件权限过于开放(例如其他用户可读),或者服务器端 authorized_keys 文件权限不对,sshd 会拒绝使用该密钥进行认证,直接返回 Permission denied (publickey) 错误。这不是密钥本身无效,而是安全策略拦截了登录请求。
分步处理
按照以下顺序排查客户端和服务端配置,每一步操作后都需尝试登录验证。
步骤 1:检查客户端私钥权限
本地私钥文件(如 id_rsa)权限必须限制为仅所有者可读。在本地终端执行:
chmod 600 ~/.ssh/id_rsa
如果权限是 644 或更开放,SSH 客户端会拒绝加载该私钥。
步骤 2:检查服务端目录权限
登录服务器(使用密码或其他方式),检查用户家目录下的 .ssh 目录权限。执行:
ls -ld ~/.ssh ls -l ~/.ssh/authorized_keys
确保 ~/.ssh 目录权限为 700,authorized_keys 文件权限为 600。如果权限不对,执行:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys
步骤 3:检查文件归属
确保 .ssh 目录和 authorized_keys 文件属于当前登录用户,而不是 root 或其他用户。执行:
chown -R $USER:$USER ~/.ssh
步骤 4:检查 SSH 服务配置
查看服务器端 /etc/ssh/sshd_config 文件,确认以下配置项未被禁用:
PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys
修改配置后需重启 SSH 服务:systemctl restart sshd 或 service ssh restart。
怎么验证是否生效
使用详细模式发起 SSH 连接,观察认证过程输出。
ssh -v user@host
在输出日志中寻找 Offering public key 和 Authentication succeeded 字样。如果看到 Permission denied (publickey) 且没有密码登录提示,说明公钥认证失败且密码认证可能也被禁用。同时可查看服务器端日志 /var/log/auth.log 或 /var/log/secure,查找 sshd 进程记录的拒绝原因,例如 Bad ownership or modes for file。
常见坑
1. 家目录权限过大:如果用户家目录本身权限是 777,sshd 也可能拒绝认证,建议家目录权限不超过 755。
2. SELinux 限制:在 CentOS 或 RHEL 系统上,SELinux 上下文错误会阻止 sshd 读取密钥文件,需运行 restorecon -R -v ~/.ssh 修复上下文。
3. 密钥格式错误:authorized_keys 文件内的公钥必须是一行,不能换行,且前后不能有多余空格。
4. 根用户限制:默认配置通常禁止 root 直接密钥登录,需检查 PermitRootLogin 配置项。
常见问题
为什么修正权限后仍然提示 Permission denied?
可能是 SSH 服务配置禁用了公钥认证,或者服务器端日志显示了更具体的拒绝原因。
可以使用密码登录但密钥不行,是密钥问题吗?
通常是服务端 authorized_keys 文件内容错误或权限问题,而不是密钥对不匹配。
多个密钥文件时如何指定登录?
使用 ssh -i /path/to/key user@host 命令明确指定私钥路径,或在 ~/.ssh/config 中配置 IdentityFile。