AuthorizedKeysCommand默认以root运行导致密钥查询失败,须设AuthorizedKeysCommandUser为普通用户;输出须严格单行公钥无空格;禁用共享authorized_keys文件,改用独立用户目录;需存密钥创建与使用时间戳便于审计;SELinux需打ssh_exec_t标签,systemd-run需加--scope等参数。

AuthorizedKeysCommand执行权限和用户上下文容易错
SSH用AuthorizedKeysCommand动态提供公钥时,命令默认以sshd进程用户(通常是root)运行,但多数审计脚本或数据库查询逻辑是按登录用户名设计的——结果就是查不到对应密钥,直接拒绝登录。
常见错误现象:Authentication refused: bad ownership or modes for directory这类报错其实和目录权限无关,而是命令返回空或非预期格式。
- 必须在
sshd_config中显式指定AuthorizedKeysCommandUser为普通用户(如ssh-keymgr),避免越权访问数据库或家目录 - 命令脚本开头加
set -u和set -e,防止$1(用户名参数)为空时静默失败 - 输出必须严格为一行一个
ssh-rsa/ssh-ed25519开头的公钥,末尾不能有空格或换行符,否则SSH解析失败
多用户共用authorized_keys文件导致覆盖风险
把所有用户的公钥硬塞进同一个/etc/ssh/authorized_keys,看似省事,实则破坏SSH的权限隔离模型——任意用户只要能写这个文件,就能登进别人账号。
使用场景:运维批量部署、CI/CD临时密钥注入、容器镜像预置密钥。
- 绝对不要用
echo ... >> /etc/ssh/authorized_keys追加,>>在并发写入时会截断或错位 - 改用
tee -a配合flock:flock /etc/ssh/authorized_keys.lock -c 'echo "key..." | tee -a /etc/ssh/authorized_keys' - 更稳妥的做法是每人独立
~/.ssh/authorized_keys,用StrictModes yes(默认)强制校验属主和权限,避免误配
公钥指纹重复或过期密钥没清理引发审计盲区
用户反复重生成密钥但不删旧的,ssh-keygen -l -f扫出来的指纹列表越来越长,人工核对基本失效;而ssh-add -l只看agent,不反映服务端真实状态。
性能影响:每多一条公钥,SSH认证阶段就要多一次公钥解码+签名验证,高并发下延迟可增加毫秒级——不明显,但压测时会暴露。
- 定期用
awk '{print $2}' ~/.ssh/authorized_keys | ssh-keygen -lf /dev/stdin 2>/dev/null | awk '{print $2,$4}'提取指纹和类型,去重比对 - 禁止在
authorized_keys里写no-port-forwarding,no-X11-forwarding等限制项后还留空行——OpenSSH 8.8+会跳过后续所有密钥 - 数据库存密钥时,别只存
fingerprint,一定要存created_at和last_used时间戳,否则无法判断是否僵尸密钥
SELinux或systemd-run干扰AuthorizedKeysCommand执行
在RHEL/CentOS上启用了SELinux,或者用systemd-run --scope包装密钥查询命令,常出现“command not found”或“permission denied”,但journalctl -u sshd里只显示Unable to execute AuthorizedKeysCommand,没具体原因。
兼容性影响:同一套脚本在Ubuntu(默认无SELinux)跑通,在Rocky Linux上静默失败。
- 先用
sudo -u nobody /path/to/cmd testuser手动模拟执行,确认基础可用性 - SELinux下需打标签:
sudo semanage fcontext -a -t ssh_exec_t "/path/to/cmd",再restorecon - 若用
systemd-run,必须加--scope --same-dir --collect,否则工作目录丢失,相对路径配置全崩
最麻烦的不是写脚本,是让不同团队都遵守同一套密钥生命周期规则——比如开发提PR加密钥,得自动触发指纹登记+过期时间写入数据库,否则审计永远滞后一步。










