内容
# ssh-broker
用于 AI 代理的 SSH 访问代理,带有**临时 CA**。模型**从不接收凭证**:它请求在主机上运行的命令,代理机构签署临时、范围受限的 SSH 证书,自身打开 SSH 连接,并仅返回**命令输出**。
三个前端共享同一个引擎(`internal/broker`)和工具表面(`internal/mcpserver`):
- **MCP stdio(本地,推荐个人使用)** — `cmd/mcp-broker`。工具:`ssh_execute`、`ssh_session_open` / `ssh_session_exec` / `ssh_session_close`、`ssh_list_servers`、`ssh_put_file` / `ssh_get_file`。无传输认证 — 隔离来自用户启动的进程(MCP 规范推荐用于 stdio)。
- **MCP HTTP + OAuth2/OIDC(远程,多用户)** — `cmd/mcp-broker-http`,可流式 HTTP。相同的工具,但每个客户端都使用**OIDC bearer token**进行身份验证,该 token 在本地针对颁发者的 JWKS 进行验证;用户身份(和组,用于按用户 RBAC)被传播到签名者。
- **HTTP + mTLS** — `cmd/broker`,`POST /v1/ssh_run`(一次性),用于通过客户端证书进行身份验证的网络代理。
## 文档
本 README 是一个登陆页面。详细信息位于聚焦的、单一来源的文档中:
| 文档 | 内容 |
|---|---|
| [ARCHITECTURE.md](docs/ARCHITECTURE.md) | 图表、请求流程、设计决策、sudo 提升、会话、多 CA |
| [THREAT_MODEL.md](docs/THREAT_MODEL.md) | 参与者、信任边界、安全控制和明确的非目标/漏洞 |
| [OPERATIONS.md](docs/OPERATIONS.md) | 运行手册:启动、添加主机、热重载、`broker-ctl`、PKI 轮换、配置 |
| [API.md](docs/API.md) | 所有服务的 HTTP 端点参考 |
| [USAGE.md](docs/USAGE.md) | MCP 工具指南(SSH + Kubernetes)、干运行和审计审查(适用于模型/操作员) |
| [SECURITY.md](docs/SECURITY.md) | 漏洞披露政策 |
| [CONTRIBUTING.md](docs/CONTRIBUTING.md) · [CODING_STYLE.md](docs/CODING_STYLE.md) | 工作流程、版本控制、Go 风格 |
## 为什么选择 ssh-broker
- **防外泄(提示注入)**:临时密钥/证书仅在代理的内存中生存;它们从不进入模型的上下文。
- **防重用**:每个证书都带有分钟级的 TTL、`source-address`(代理或堡垒 IP)和一次性 `force-command`。在主机/时间/IP 以外无用。
- **受控提升**:`allow_sudo` / `allowed_sudo_users` 生存在签名者中;受损的代理无法提升权限,而策略禁止。
- **CA 泄露范围限定**:每个主机组一个 CA 密钥(`ca_keys`),每个密钥可选地存储在 Azure Key Vault 中 — 私有密钥从未离开 HSM。
- **审计/不可否认**:仅追加、Ed25519 链式日志,由签名者、代理和 `sshd` 关联的 `serial`。
完整的威胁模型 — 包括系统**不防御的内容** — 在 [THREAT_MODEL.md](docs/THREAT_MODEL.md) 中。
## 工作原理
```
AI 模型 ──工具调用──> 代理 ──mTLS──> [控制平面] ──mTLS──> 签名者
(无凭证) (RAM 中的临时密钥 (审批 + (CA 密钥 +
永不落地) 准入控制, 策略 + RBAC,
) 无 CA 密钥) 签署证书)
│
└── 使用临时证书的 SSH ──> 堡垒 ──> 目标主机
└─ stdout/stderr/exit_code ─> 模型
```
代理发送一个**意图**(`{host, role, purpose, command?, sudo?, pty?, pubkey, …}`);签名者从策略中推导出每个证书约束并返回签名的证书。临时私钥在代理中生成,从不离开。有关请求流程、设计决策和每跳 ProxyJump 证书图表,请参见 [ARCHITECTURE.md](docs/ARCHITECTURE.md)。
## 功能概述
| 功能 | 一句话描述 | 更多信息 |
|---|---|---|
| **临时证书** | RAM 中每个操作生成的 Ed25519 密钥对;分钟级、范围受限的证书。无可重用密钥。 | [ARCHITECTURE](docs/ARCHITECTURE.md) |
| **外部签名者** | 单独的 `cmd/signer` 持有 CA 密钥和策略;代理从不持有。 | [ARCHITECTURE](docs/ARCHITECTURE.md) |
| **多 CA + HSM** | 通过 `ca_keys` 每个主机组一个 CA 密钥;本地 PEM 或 Azure Key Vault。 | [ARCHITECTURE](docs/ARCHITECTURE.md#multi-ca--azure-key-vault-v1110) |
| **AI 动作防火墙** | 按主机或**按组可组合**的命令策略(允许/拒绝/需要批准),POSIX-sh AST 解析,干运行。适用于一次性请求的权威。 | [ARCHITECTURE](docs/ARCHITECTURE.md#ai-action-firewall) · [USAGE](docs/USAGE.md) |
| **人工审批** | 可选控制平面门控 `require_approval` 命令,需经人工审批;签名者强制执行。 | [ARCHITECTURE](docs/ARCHITECTURE.md#human-in-the-loop--control-plane) · [API](docs/API.md#control-plane-api) |
| **行为准入控制** | 按主体异常检测(速率、新主机、新型命令);观察或强制执行。 | [ARCHITECTURE](docs/ARCHITECTURE.md#human-in-the-loop--control-plane) |
| **RBAC** | 代理-CN 组(mTLS)+ 按最终用户 OIDC 组;失败关闭。 | [ARCHITECTURE](docs/ARCHITECTURE.md#rbac) |
| **sudo / PTY** | 策略控制的权限提升(`sudo -n`)和主机 PTY 分配。 | [ARCHITECTURE](docs/ARCHITECTURE.md#privilege-elevation-sudo-nopasswd) |
| **会话记录** | `shell`/`pty` 会话到 ASCIIcast v2(`.cast`),由 `session_id` 索引。 | [USAGE §8](docs/USAGE.md#8-session-recording) |
| **链式审计** | 仅追加、Ed25519 签名、SHA-256 链式;由 `serial` 关联。 | [USAGE §7](docs/USAGE.md#7-reviewing-audit-logs) · [API](docs/API.md#audit-log-correlation) |
| **热重载** | `signer.json` 重新读取(并验证)而无需重启,通过 `POST /v1/reload` 或 SIGHUP。 | [OPERATIONS §3](docs/OPERATIONS.md#3-hot-reload) |
## 与现有解决方案的比较
几个工具解决了 SSH 访问控制或 AI 代理凭证安全问题,但没有一个涵盖 ssh-broker 目标的完整组合,即一个轻量级、自行托管的软件包。
| 功能 | **ssh-broker** | Teleport | Vault + SSH 引擎 | StrongDM | ssh-mcp |
|---|---|---|---|---|---|
| 内存中的临时证书(无磁盘) | ✅ | ✅ | ✅ | ❌ | ❌ |
| 单独的代理 / 签名服务 | ✅ | ✅ | 部分 | ❌ | ❌ |
| MCP 原生(AI 代理) | ✅ | ✅(2025) | ✅(2025) | ❌ | ✅ |
| MCP 传输上的 OAuth2/OIDC | ✅ | ✅ | ✅ | ❌ | ❌ |
| 按命令策略 + 干运行(AI 动作防火墙) | ✅ | ❌ | ❌ | ❌ | ❌ |
| AI 命令的人工审批 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 按代理的行为准入控制(异常/速率) | ✅ | ❌ | ❌ | ❌ | ❌ |
| 会话记录(ASCIIcast v2,stdin+stdout+stderr) | ✅ | ✅ | ❌ | 部分 | ❌ |
| 加密链式审计日志 | ✅ | ❌ | ❌ | 部分 | ❌ |
| 单二进制 / 简单自行托管 | ✅ | ❌ | ❌ | ❌ | ✅ |
| CA 密钥的 HSM/KMS | ✅(AKV) | ✅ | ✅ | — | — |
**[Teleport](https://goteleport.com/)** 是最接近的商业等效产品 — 短期 SSH 证书、RBAC 和自 2025 年起的**安全 MCP**;其 2026 年 1 月的**代理身份框架**针对相同的威胁模型。区别在于操作权重:Teleport 需要一个专用的控制平面集群、记录代理和 Web UI — 比 Go 二进制文件 + 签名者重数量级。
**[HashiCorp Vault SSH 秘密引擎](https://developer.hashicorp.com/vault/docs/secrets/ssh)** 是一个 SSH CA,具有完整的 HSM/KMS 支持和(2025 年)其自己的 MCP 服务器,但它仅提供签名部分 — 您仍然需要自己构建执行层(`engine.go`、`session.go`、MCP 工具)。
**[StrongDM](https://www.strongdm.com/)** 隐藏凭证但存储长期密钥而不是在内存中生成临时证书,使其对外泄更脆弱。 **[Smallstep SSH CA](https://smallstep.com/)** 是一个轻量级 OIDC 集成的 SSH CA(类似于 `cmd/signer`)但没有执行代理或 MCP 层。 **[ssh-mcp](https://github.com/tufantunc/ssh-mcp)** 通过 MCP 公开 SSH 给 LLM 但使用**静态 SSH 密钥** — 正是此代理防止的漏洞。 **[CyberArk PAM](https://docs.cyberark.com/)** 提供可比较的 JIT 证书访问但是一个封闭的企业平台,供人类操作员使用,而不是 AI 工作负载。
**适用场景:**MCP 原生 AI 代理访问 + 内存中临时证书 + 单独签名者 + ASCIIcast 记录 + 链式审计,作为 Go 二进制文件的集合,无需集群。企业功能(Web UI、多区域 HA)正在路线图中(参见 [HANDOFF.md](docs/HANDOFF.md))。
## 快速入门
```bash
# 1. 构建(make 将 git 标签版本注入到每个二进制文件中)
make install # → ~/bin/{signer,broker,broker-ctl,mcp-broker,...}
# 或单个二进制文件: make signer
# (纯 `go build ./cmd/...` 也有效;它会报告 dev-<commit> 版本)
# 2. 启动签名服务(必须在代理之前运行)
./signer.sh start
# 3. 添加主机并重载
broker-ctl host add --name web01 --addr web01.example.com:22 --user deploy --scan \
--groups prod-web --sudo
broker-ctl reload
# (--config 是一个全局标志,在子命令之前;每个二进制文件都接受 --version)
broker-ctl --config /secure/path/signer.json host list
broker-ctl --version # 简短;添加 --verbose 获取构建详细信息
```
用客户端注册 stdio MCP:
```jsonc
// Claude Code — ~/.claude.json
"ssh-broker": { "type": "stdio", "command": "/Users/<you>/bin/mcp-broker",
"args": ["-config", "/secure/path/config.json"] }
// OpenCode — ~/.config/opencode/opencode.json (注意:类型 "local",命令是数组)
"ssh-broker": { "type": "local",
"command": ["/home/<you>/bin/mcp-broker", "-config", "/secure/path/config.json"],
"enabled": true }
```
完整的设置 — 本地或外部签名模式、远程 OAuth 前端、主机字段、sudoers、PKI 和 `broker-ctl` — 在 [OPERATIONS.md](docs/OPERATIONS.md) 中。模型工具用法在 [USAGE.md](docs/USAGE.md) 中。
## API
完整参考:[API.md](docs/API.md)。
| 服务 | 端点 | 认证 | 描述 |
|---|---|---|---|
| 签名者 | `POST /v1/sign` | mTLS | 请求临时 SSH 证书 |
| 签名者 | `GET /v1/hosts` | mTLS | 列出可访问的主机(按调用者组过滤) |
| 签名者 | `POST /v1/reload` | mTLS | 热重载 `signer.json` 而无需重启 |
| 控制平面 | `POST /v1/sign`, `/v1/approvals/{id}`, … | mTLS | 转发 + 人工审批 |
| 代理 HTTP | `POST /v1/ssh_run` | mTLS | 执行一次性 SSH 命令 |
| MCP HTTP | `/.well-known/oauth-protected-resource` | 无 | OAuth2 发现(RFC 9728) |
| MCP HTTP | 流式 HTTP | OIDC Bearer | MCP 工具 |
## 安全
安全姿态 — 信任边界、分层控制(RBAC、命令策略、审批门控、准入控制、源地址/TTL 固定、链式审计),以及**明确的非目标**(`mode=exec` 会话是代理预检但非主机强制执行,无 KRL,秘密日志记录原样,审计失败打开,…)— 在 [THREAT_MODEL.md](docs/THREAT_MODEL.md) 中记录。
报告漏洞,请参见 [SECURITY.md](docs/SECURITY.md)。CI 在每次推送和 PR 上强制执行 `gofmt`、`go vet`、`go test -race` 和 `govulncheck`。
## 测试
```bash
make test # go test -race ./... (证书构建、策略/RBAC/sudo/PTY 跳转,…)
bash lab/run_signer_lab.sh # 外部签名者:无 ca_key + 策略 + 拒绝的代理
bash lab/run_mcp_lab.sh # 堡垒 + 目标(ProxyJump)MCP 场景
bash lab/run_lab.sh # HTTP/mTLS 前端
```
## 许可证
Copyright (C) 2026 Luis González Fernández.
该程序是免费软件:您可以在 **GNU General Public License v3.0** 下重新分发和/或修改它,由 Free Software Foundation 发布。它被分发,希望它会有用,但**不提供任何保证**。有关完整文本,请参见 [LICENSE](LICENSE)。