authorizedkeyscommand 不支持直接通过 url 加载公钥,需在自定义脚本中用 curl/wget 从 http 接口拉取;必须配置 authorizedkeyscommanduser 指定非 root 用户运行,并严格校验输入、输出格式、权限及 selinux 上下文。

AuthorizedKeysCommand 本身不支持直接通过 URL 加载公钥,它要求你提供一个本地可执行命令(如 shell 脚本或二进制程序),由 SSH daemon 调用该命令并传入用户名($1)作为参数,命令标准输出必须是严格格式的单行公钥(如 ssh-rsa AAAA... user@host)。
核心要点:URL 是数据源,不是执行方式
所谓“通过 URL 动态加载”,实际是指在你的 AuthorizedKeysCommand 脚本中,用 curl、wget 或类似工具从 HTTP/HTTPS 接口拉取对应用户的公钥。这不是 OpenSSH 内置功能,而是你自定义逻辑的一部分。
关键配置与权限设置
必须显式指定运行上下文,否则默认以 root 身份执行,会导致无法访问用户专属资源(如数据库连接、API token 文件、家目录):
- 在
/etc/ssh/sshd_config中添加两行:
AuthorizedKeysCommandUser ssh-keymgr
其中 ssh-keymgr 是一个普通系统用户(非 root),专用于运行该命令;脚本需属主为该用户,且不可被组或其他人写入。
脚本编写注意事项
示例脚本 /usr/local/bin/fetch-key-by-user.sh(需 chmod 755):
- 开头加
set -euo pipefail,防止$1为空时静默失败 - 校验
$1是否为合法用户名(避免路径遍历或注入) - 用
curl -fsS --max-time 3 "https://auth.example.com/keys?user=$1"获取内容 - 输出必须是**一行纯公钥**:不能有前后空格、不能有多余换行、不能带 HTTP 头或错误信息
- 建议加日志(如
logger -t ssh-keys "fetched for $1"),但别输出到 stdout
服务端接口设计建议
你提供的 HTTP 接口应满足:
- 只返回一条公钥字符串(例如
ssh-ed25519 AAAAC3NzaC... user@example) - 响应状态码为 200 时才视为有效;404 或 403 应让脚本 exit 1(SSH 就会拒绝登录)
- 接口需鉴权(如 API key 放在请求头、或用客户端证书),不能公开可读
- 后端应记录每次密钥查询时间,配合审计字段
created_at和last_used
不要跳过的安全细节
常见失败原因往往不是网络问题,而是这些细节:
- SELinux 上下文:脚本和 curl 必须打上
ssh_exec_t标签,否则被阻止 - systemd-run 隔离:若脚本内需启动临时进程(如数据库 client),要用
systemd-run --scope --scope避免孤儿进程 - 禁止共享文件:绝不能把所有用户公钥 dump 到同一个
/etc/ssh/authorized_keys,必须按用户隔离 - 禁用宽松权限:脚本、其所在目录、调用的 token 文件,都不能有 group/o write 权限










