SSH 报 .pub 文件权限过宽
SSH 报 .pub 文件 Permissions 0644 are too open 时,先确认公钥是否被当作本地私钥读取。核对 IdentityFile、真实私钥权限和 agent 身份,避免只改公钥权限后继续遇到认证失败。
SSH 登录失败,日志里出现了私钥权限警告,但报错路径却以 .pub 结尾:
WARNING: UNPROTECTED PRIVATE KEY FILE!
Permissions 0644 for '/home/alice/.ssh/server_key.pub' are too open.
This private key will be ignored.
Permission denied (publickey,password).
如果同目录下的私钥已经是 600,继续收紧 .pub 文件权限往往没有解决关键问题。先确认 SSH 是否把公钥文件当作本地私钥读取。
下面针对 Linux、macOS 上的 OpenSSH 客户端,以及保存在本地普通文件系统中的密钥。Windows 原生 OpenSSH 的 ACL、WSL 挂载盘权限和硬件密钥另有条件,不应直接套用文件权限命令。示例别名 app-server、账号 deploy、地址 server.example.com 和文件名 server_key 都需要替换。
报错里的文件名比权限数字更关键
常见的一对文件是:
~/.ssh/server_key 私钥,留在客户端
~/.ssh/server_key.pub 公钥,可配置到服务器账号
普通文件密钥登录需要客户端用私钥完成签名。把公钥交给服务器是正常的,但如果本来打算从磁盘读取私钥,客户端的配置却写成:
IdentityFile ~/.ssh/server_key.pub
SSH 就可能在需要私钥时读取这个公钥文件,并先触发私钥权限检查。把它改成 600 只能改变文件权限,不能把公钥变成私钥,之后还可能出现格式错误。
.pub 只是常用命名习惯,文件名本身不能证明里面的内容。也不要通过重命名、删除扩展名,把一份公钥伪装成私钥。应找到原来生成的配套私钥,或者确认对应私钥确实由 agent 管理。
查看实际生效的身份文件
先展开平时使用的主机别名:
ssh -G app-server
关注 hostname、user、port、identityfile 和 identityagent。这个命令输出配置后退出,不建立远程 SSH 会话。若平时还传了 -F、-i 或其他连接选项,检查时也要带上,否则得到的并非同一套配置。
不要只看刚编辑的那个 Host 段。多个 IdentityFile 会累加,通配 Host、包含文件或命令行里可能仍有另一个 .pub 路径。找到实际提供错误路径的位置,只改对应条目,不要清空全部 SSH 配置。
若展开结果不够清楚,可在已有授权的目标上使用调试连接:
ssh -v app-server
对照日志中读取的配置文件、提供的公钥和权限警告中的完整路径。Offering public key 只是提供候选公钥;即使出现 Server accepts key,也不能单凭这一行判断签名和最终认证已经完成。继续查看后续日志,确认公钥认证最终成功。
调试日志可能暴露用户名、路径和服务器地址,分享前应脱敏。不要把私钥内容贴出来,也不要为了排查而关闭主机指纹验证。
本地有私钥时,修改指向而不是修改公钥内容
确认 ~/.ssh/server_key 是自己有权使用的现有私钥后,先查看两个文件的所有者和权限:
ls -l ~/.ssh/server_key ~/.ssh/server_key.pub
私钥应当由当前登录用户妥善保管,不能让其他用户访问。若所有者正确、文件系统支持普通 Unix 权限,可仅对这一个私钥收紧权限:
chmod 600 ~/.ssh/server_key
600 允许所有者读写;只读的 400 也可以用于读取私钥。公钥本身不需要按私钥保密,正常的 .pub 文件可以让其他人读取。不要递归修改整个 .ssh 或 /etc/ssh,也不要用 sudo ssh 绕过当前用户的配置和权限问题。
备份现有客户端配置后,将该主机的身份文件改为实际私钥。例如:
Host app-server
HostName server.example.com
User deploy
Port 22
IdentityFile ~/.ssh/server_key
IdentitiesOnly yes
这是一个主机配置片段,不是整份配置文件的替代品。已有跳板机、非默认端口和其他网络设置应当保留。IdentitiesOnly yes 限制额外身份的尝试,但不会清除其他已经配置的 IdentityFile;修改后仍要再次检查展开结果。
如果需要确认这份文件能作为私钥读取,可在本机使用:
ssh-keygen -y -f ~/.ssh/server_key
它读取私钥并输出对应公钥,不会重新生成或覆盖密钥。加密私钥可能要求输入私钥口令。将输出的密钥类型和公钥主体,与现有 .pub 文件或服务器上已经授权的公钥比较;末尾注释不同不代表密钥不同。输出的是公钥,也没有必要随意传播其中的身份信息。
如果只有 .pub,没有私钥,也没有可用的 agent,就不能靠调整权限完成签名。应从自己有权访问的安全备份恢复私钥,或通过已有管理通道登记一对新密钥的公钥。不要删除旧授权,直到新身份经过验证;如果私钥曾泄露,恢复登录后还应撤销对应旧公钥,单纯改权限不能收回已经泄露的副本。
有意用公钥选择 agent 身份时,不必改成私钥路径
当前 OpenSSH 支持另一种用法:本地没有私钥文件,IdentityFile 指向公钥,由 agent 中对应的私钥完成签名。因此,不能只看到 .pub 就断言配置一定错误。
这种配置依赖当前 SSH 进程能够访问正确的 agent,并且该 agent 确实持有对应身份。先在运行 SSH 的同一个终端查看:
ssh-add -l
ssh-keygen -l -f ~/.ssh/server_key.pub
比较指纹时,要使用相同的指纹算法。没有 agent、agent 中没有身份,或指纹不同,都不能证明目标公钥对应的私钥可用。还需检查 IdentityAgent:它可以覆盖 SSH_AUTH_SOCK,所以这个终端中的 ssh-add 与实际 SSH 连接未必访问同一个 agent。
如果就是要使用这条路线,应恢复预期的 agent 连接和身份加载方式。密钥有确认、解锁或硬件触摸要求时,也需完成相应操作;列表中出现指纹不等于本次签名一定成功。不要为了消除报错,把原本由专门 agent 保管的私钥复制出来。
明确使用磁盘私钥还是 agent 中的身份,再按对应方式验证。旧版客户端的功能和报错措辞可能不同,不应把一份旧日志中的行为当成所有版本的规则。
修复后确认认证完成,再处理服务器授权
使用原来的主机别名和连接路线再连接一次。确认 SSH 已停止把错误文件当私钥读取,使用了预期身份,通过公钥认证并登录到正确账号。不要把消失了一条权限警告当成全部修复完成。
若权限警告已消失,仍然是 Permission denied,继续检查服务器上对应账号是否授权了这把公钥,以及客户端实际使用的身份。此时问题可能已转到服务器授权或其他认证条件,反复调整 .pub 权限没有帮助。
需要回退时,恢复本次修改的客户端配置条目,保留其他主机设置,再检查展开结果。对真实私钥已经收紧的权限,无需为了回退配置而重新放宽;本次排查也不要求删除公钥文件、重新生成现有密钥或重启远程 SSH 服务。


