运行 ssh、scp 或 sftp 时出现 Bad owner or permissions on ~/.ssh/config,是本地OpenSSH客户端拒绝读取不安全的用户配置文件。连接还没有进入远程服务器认证阶段,修改远端 sshd_config 不会解决它。
这个检查用于防止其他本地用户篡改SSH目标、跳板机或代理命令。重点是恢复正确所有者和写权限,不是把文件改成所有人可读写。

先确认报错指向本地哪个文件
使用详细模式查看客户端在解析哪个配置文件:
ssh -vvv example-host
默认用户配置是 ~/.ssh/config,但脚本可能通过 -F 指向其他文件,配置中也可能使用 Include 加载更多片段。先确认当前用户和家目录:
id
printf '%s\n' "$HOME"
不要在root和普通用户之间来回执行命令后,凭路径外观判断文件属于谁。
检查目录、文件和链接链路
查看每一级路径的所有者和权限:
namei -l "$HOME/.ssh/config"
ls -ld "$HOME" "$HOME/.ssh"
ls -l "$HOME/.ssh/config"
readlink -f "$HOME/.ssh/config"
如果 config 是符号链接,还要检查最终目标。备份还原、用sudo编辑、从其他账户复制文件,都可能让它变成root或另一个UID所有。
恢复正确所有者
只修复明确属于当前登录用户的SSH配置:
sudo chown "$(id -u):$(id -g)" "$HOME/.ssh" "$HOME/.ssh/config"
如果 .ssh 中混有共享文件或其他服务账户文件,不要直接递归 chown -R。先逐项确认用途,再修改具体目标,以免破坏自动化任务和密钥访问边界。
设置安全而够用的权限
用户SSH目录可设为700,配置文件可设为600:
chmod 700 "$HOME/.ssh"
chmod 600 "$HOME/.ssh/config"
OpenSSH手册要求用户配置文件可由本人读写,并且不能被其他用户写入。644在不少系统上也满足不可被他人写入的条件,但600更容易保持私有。绝对不要使用777或666来消除报错。
处理Include加载的配置片段
列出配置中的Include规则:
grep -nE '^[[:space:]]*Include[[:space:]]+' "$HOME/.ssh/config"
OpenSSH会展开通配符并按顺序读取匹配文件。检查每个片段的所有者与写权限,避免某个共享目录让其他用户可以替换配置内容。若Include使用相对路径,用户配置中的相对路径按 ~/.ssh 解释。
在容器、WSL和挂载目录中注意权限映射
Windows共享目录、网络文件系统或容器绑定挂载可能无法按Linux方式保存属主和权限。先用 stat 查看实际结果:
stat -c '%U %G %a %n' "$HOME/.ssh" "$HOME/.ssh/config"
更稳妥的做法是把SSH配置放到当前Linux用户的本地家目录,再通过受控方式同步内容。需要在独立VPS验证SSH客户端配置时,可以使用 萤光云 或 LightNode 建立测试环境。只能使用测试密钥,不能上传生产私钥。
修复后怎样验收
先让SSH只解析配置并输出最终参数,不必立刻建立连接:
ssh -G example-host >/dev/null
随后使用详细模式连接,确认不再出现权限错误,并核对目标主机、端口、用户名和IdentityFile是否符合预期。验收标准是配置可被当前用户读取、不可被其他用户修改,Include片段同样安全,实际连接没有被错误规则重定向。
FAQ
为什么sudo ssh能用,普通用户却报错? 两者读取的家目录和用户配置不同,sudo还可能改变有效用户。应修复普通用户自己的配置,不要长期依赖sudo连接。
私钥也要设置600吗? 私钥必须防止其他用户读取,600是常用设置;公钥可以更宽松,但仍应确认所有者和目录边界正确。
温馨提示
权限修复前先查看所有者和链接目标,避免对错误路径递归操作。SSH配置可以包含代理命令和跳板规则,应把它当作安全敏感文件管理。


