Linux SSH Key 管理与权限控制

2次阅读

openssh因私钥或目录权限过宽(如>600或>700)拒绝连接;须用chmod 600设私钥、700设.ssh目录;多密钥靠~/.ssh/config的host+identityfile绑定;ssh-agent需手动注入或配置shell启动;command=限制需配合no-*选项及绝对路径才安全。

Linux SSH Key 管理与权限控制

SSH Key 权限太松导致连接被拒绝

OpenSSH 默认拒绝使用权限过宽的私钥文件,这是硬性安全策略,不是配置错误。一旦 ~/.ssh/id_rsa~/.ssh/config 的权限大于 600(比如被设成 644755),ssh 会直接报错:Permissions for '/home/user/.ssh/id_rsa' are too open

实操建议:

  • 私钥文件必须用 chmod 600 ~/.ssh/id_rsa;公钥可保持 644
  • ~/.ssh 目录权限不能高于 700,否则某些 OpenSSH 版本(如 8.8+)也会拒绝读取 authorized_keys
  • 别用 sudo chmod 修权限——改完属主可能变成 root,导致普通用户无法读取
  • windows WSL 用户注意:NTFS 挂载卷上默认无 unix 权限,需启用 metadata 选项并重启

多个 SSH Key 怎么自动选对主机

~/.ssh/config 文件做 Host 别名 + IdentityFile 绑定,比在命令行反复加 -i 可靠得多。它不依赖 shell 别名或环境变量,是 OpenSSH 原生支持的路由逻辑。

实操建议:

  • 每个 Host 块必须顶格写,缩进无效;IdentityFile 路径建议用绝对路径,避免 ~ 展开失败
  • 如果同时配了 IdentitiesOnly yes,SSH 就只用你指定的 key,不会遍历 ssh-agent 里的其他密钥
  • 测试配置是否生效:运行 ssh -F ~/.ssh/config -T git@github.com,看实际用了哪个 key(加 -v 可见调试输出)
  • 别把生产环境和测试环境的 key 都塞进一个 config 文件里——容易误连,按用途拆成 config-prod + include config-prod 更可控

ssh-agent 不持久、重启后失效

linux 桌面环境(GNOME/KDE)通常自带 ssh-agent 管理,但终端新开的 bash/zsh 子进程并不自动继承其环境变量(SSH_AUTH_SOCK),所以 ssh-add -l 会显示 “The agent has no identities”。

实操建议:

  • 检查当前 shell 是否已接入 agent:echo $SSH_AUTH_SOCK,为空就说明没连上
  • 手动启动并注入:先 eval $(ssh-agent),再 ssh-add ~/.ssh/id_work;但这样每次开终端都要重做
  • 更稳的方式是在 ~/.bashrc~/.zshrc 里加判断逻辑:if [ -z "$SSH_AUTH_SOCK" ]; then eval $(ssh-agent); fi
  • systemd 用户可用 ssh-agent.socket 激活,但注意它默认不加载 key,仍需配合 ssh-addgnome-keyring

authorized_keys 中 command= 限制执行但绕过风险

~/.ssh/authorized_keys 里给某条公钥加 command="rsync --server ...",能锁定该 key 只跑指定命令,但这个限制仅在 SSH 连接建立后生效,不防端口扫描、协议探测或密钥泄露后的滥用。

实操建议:

  • command= 后面的命令会被完整传给 shell,务必用绝对路径(如 /usr/bin/rsync),避免 PATH 劫持
  • 加上 no-port-forwarding,no-X11-forwarding,no-agent-forwarding 才算真正收紧,光靠 command= 不够
  • 如果命令含参数且可能被用户控制(比如传入文件路径),必须用 environment="PATH=/usr/bin" 锁死环境,并验证输入合法性——command= 本身不做参数过滤
  • 这种配置适合自动化部署脚本,不适合交互式登录;真要限制登录,优先考虑 ForceCommand + Match User/etc/ssh/sshd_config 里配

权限控制最麻烦的不是设不设,而是设完没人定期 audit。比如 authorized_keys 里混着三年前的测试 key,或者 config 文件里写了硬编码密码(虽然不该这么干),这类细节一漏,前面所有配置都白搭。

text=ZqhQzanResources