把SSH私钥交给Bitwarden:为人工与智能体连接建立授权边界

当智能体开始替我检查服务器、部署服务和建立 SSH 隧道时,一个问题变得非常具体:它应该怎样获得登录服务器的能力?

过去的办法很直接:把私钥放在电脑的 .ssh 目录里,再让终端或工具读取。连接方便,但同一个账户下运行的程序也可能读取这些文件。尤其是没有设置口令的私钥,一旦被复制走,攻击者就可能从另一台机器登录仍然信任这把密钥的服务器。

我希望保留智能体的执行效率,同时把“是否允许使用服务器身份”的决定留在自己手中。我的选择是:用 Bitwarden 统一保管人工 SSH 私钥,通过 SSH Agent 提供签名,并把使用授权设置为“始终”提示。

本文结合我的服务器 SSH 认证改造,整理一套可复用的方法:从密钥保管、客户端接入,到迁移验收,以及如何将它写进个人智能体基座的治理规则。文中的域名、账号、端口和密钥名称均为虚构示例,不对应实际连接信息。

私钥文件带来的问题

SSH 公钥认证依靠一对密钥:服务器保存公钥,客户端证明自己能够使用对应的私钥。服务器不需要收到私钥本身。

但私钥文件的管理很容易变成一件分散的事:Windows 存一份,Mac 存一份,终端工具导入一份,换电脑时再复制一份。副本越多,越难回答“还有谁能够使用这把密钥”和“旧电脑上是否已经清理干净”。

文件权限和私钥口令都有价值。文件权限可以约束其他用户,口令可以保护被复制的私钥文件。不过,当恶意程序已经在我的用户身份下运行时,单靠目录权限很难建立足够清晰的隔离。对智能体而言,把私钥文件交给执行环境,也容易让凭据保管与任务执行混在一起。

我因此改变了默认流程:在 Bitwarden 中生成密钥,只把公钥部署到服务器,日常连接通过 Agent 完成。

SSH Agent 如何让客户端使用密钥

Agent 是 SSH 客户端和私钥之间的一层接口。客户端向它请求公开身份或签名结果,Agent 使用私钥完成签名,再把结果返回给客户端,服务器用公钥校验。

Bitwarden 桌面应用可以提供这个接口。接入后,支持该接口的 SSH 工具向 Bitwarden 请求签名,是否弹出授权由设置决定。原理和密钥类型可查阅Bitwarden 的 SSH 说明。

我的工作流是:

我或智能体发起 SSH 连接
        ↓
SSH 客户端请求身份签名
        ↓
Bitwarden 提示授权使用指定密钥
        ↓
我批准 → Agent 返回签名 → 服务器验证公钥
我拒绝 → 本次签名无法完成

这里有一个容易混淆的细节:批准的是密钥签名请求,不是对后续每条远程命令逐条审批。 一旦 SSH 会话建立,工具就能在该账号权限内继续工作。对同一任务的连续操作,我会复用一个会话,完成后退出;涉及删除、发布等操作的业务授权,仍由任务规则单独约束。

Bitwarden 弹窗请求批准 SSH 密钥使用,背景身份信息已移除

配图由我的实际界面经 AI 辅助脱敏编辑而成,服务器标识已替换为示例,背景密钥信息已遮盖;用于展示授权交互,不作为原始认证日志。

让 Windows 和 macOS 接入同一个密钥来源

先在 Bitwarden 桌面应用中创建 SSH 密钥条目,命名为自己能够辨认的身份,例如“示例服务器 SSH”。再开启 SSH Agent,将“使用 SSH 代理时提示授权”设为“始终”,并保持应用在后台运行。

服务器只安装条目中的公钥,不接收私钥。客户端配置会随安装渠道而不同;以下接入步骤参考Bitwarden 官方配置文档,实际使用时应核对当前版本。

Windows:处理原生 Agent 冲突

官方要求禁用 Windows 的 OpenSSH Authentication Agent 服务,避免原生 Agent 与 Bitwarden 争用接口。可以在服务管理器中停止它并把启动类型改为“禁用”。这是客户端认证代理,不是服务器的 sshd 服务。

打开新的 PowerShell 窗口,检查 Agent 提供的公钥:

ssh-add -L

这个命令返回公开身份,不会导出私钥。能列出公钥只证明接口可访问,完整验收还要实际连接服务器并批准签名。

macOS:配置 socket 并持久化

Mac App Store 版在 ~/.zshrc 中加入:

export SSH_AUTH_SOCK="$HOME/Library/Containers/com.bitwarden.desktop/Data/.bitwarden-ssh-agent.sock"

官网下载的 .dmg 版使用另一条路径:

export SSH_AUTH_SOCK="$HOME/.bitwarden-ssh-agent.sock"

根据安装来源选择一条即可。保存后重新打开 Terminal,再执行 ssh-add -L。写进 ~/.zshrc 的配置会由新的交互式 zsh 加载;它不意味着所有从桌面启动的 GUI 应用都会自动继承同样的环境。

终端能连接,不代表所有工具已经接入

Windows、Mac 的终端验证成功之后,WindTerm、Git 和其他 GUI 工具仍要逐个核对它们使用的 SSH 客户端、Agent 与身份文件配置。支持 Agent 的工具应指向 Bitwarden,并实际观察签名授权与连接结果。

Bitwarden 的密码库 CLI 与桌面 SSH Agent 也是不同能力。日常 SSH 登录可以直接使用系统的 ssh 命令,无需编写脚本从密码库取出私钥。

已有服务器如何迁移

我采用的迁移顺序是先建立新身份,再撤销旧身份:

  1. 保留当前有效 SSH 会话,并确认一个独立恢复入口可用。
  2. 在 Bitwarden 中生成新密钥,向目标账号追加新公钥。
  3. 用另一个窗口通过 Bitwarden Agent 新建连接,核对服务器与登录账号。
  4. 精确删除旧的人工公钥,保留仍被其他合法服务使用的授权。
  5. 再次通过新密钥登录,验证旧身份已经无法认证。
  6. 根据服务器用途关闭密码和键盘交互认证,检查配置并重新验证。
  7. 清理客户端旧私钥及其导出副本,更新连接与恢复说明。

其中最重要的是“精确撤销”。authorized_keys 中可能同时有人的登录身份和服务专用身份,直接清空文件可能影响其他工作。

删除本地私钥只能减少未来暴露,无法让已经被复制出去的旧私钥失效。让旧身份失效的是服务器撤销对应公钥。 如果担心过去的私钥副本,我更倾向于在 Bitwarden 中生成新密钥并轮换,而不是仅把原文件导入密码库。

密码入口也要检查服务器实际生效的配置,包括键盘交互认证和 Match 例外。只改某一行配置,不能证明所有入口都已经关闭。保留恢复入口后再执行这些变更,避免把自己锁在门外。

怎样证明连接确实经过 Bitwarden

以下命令中的 operator、域名和端口需替换为自己的连接信息:

ssh -p 43871 operator@server.example.com

简单命令本身不会保证使用 Bitwarden:SSH 还会读取客户端配置,可能尝试其他身份。因此,我验收时会加上调试输出:

ssh -v -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -p 43871 operator@server.example.com

检查接受的公钥指纹与 Bitwarden 条目是否对应、认证是否由公钥完成,并确认出现预期授权提示。首次连接还要通过可信渠道核对服务器主机指纹;主机指纹与自己的登录公钥指纹是两种不同标识。

在我的实际连接测试中,关闭 Bitwarden SSH Agent 后,新连接返回 Permission denied (publickey);重新打开后,批准签名即可登录。结合本地旧私钥清理、新身份核对和服务器密码入口关闭,这些证据支持“该连接依赖 Bitwarden Agent”的判断。

这仍然是对已测试客户端和服务器的验收结果,不能自动推广到所有电脑、所有 SSH 工具或所有服务器。

多把密钥为什么会导致认证次数耗尽

密码库中保存多把 SSH 密钥后,客户端可能依次尝试候选公钥。目标服务器若限制认证尝试次数,正确密钥尚未轮到,就可能返回:

Too many authentication failures

一个可控办法是用公钥文件作为身份选择器:私钥继续留在 Bitwarden,本地只保留目标身份的公钥。例如:

ssh -i ~/.ssh/example-server.pub -o IdentitiesOnly=yes -p 43871 operator@server.example.com

OpenSSH 明确支持用公钥文件匹配 Agent 中的私钥,详见IdentityFile 与 IdentitiesOnly 的说明。公钥选择器不违反“私钥不落磁盘”的约定;如果希望完全不依赖本地身份文件,也可以继续使用直接连接命令,但需要接受多候选身份可能导致失败的情况。

提高服务器的 MaxAuthTries 也是一种配置选择,需要结合实际身份数量和服务器策略评估。它解决的是候选尝试次数,不会让客户端更准确地选择密钥。

文件被窃取时,它保护了什么

“私钥只保留在 Bitwarden”描述的是统一的管理来源,并不表示数据物理上只存在一个位置。密码库会同步到设备,设备也会保留加密缓存。

官方数据存储说明指出,本地密码库数据以加密形式保存,解锁后的解密数据存于内存。相比把无口令私钥文件放在普通目录中,这能减少“复制一个文件就获得可直接使用私钥”的风险。

但需要把两种情形分开:攻击者只窃取磁盘文件,与攻击者已经控制正在使用的电脑,并不是同一威胁。如果恶意程序能够读取进程内存、截获输入、操纵界面或利用已建立的远程会话,密码库和 Agent 仍然不能独自解决全部问题。

它显著缩小了普通文件泄露的攻击面,并为新签名请求增加了人的确认,但终端安全仍然是基础。

授权弹窗中的 ssh.exe 名称帮助我辨认请求,不能证明进程一定可信。条目名称也是我自己填写的标签,不等于目标服务器已经经过密码学核验。不明来源的请求应拒绝,服务器主机校验仍要保留。

在个人智能体基座中落实单一职责

我在此前的《从聊天机器人到个人AI操作系统:个人智能体基座完整技术拆解》中,介绍了如何把长期规则、项目上下文、工具和身份路由组织成一套持续工作的基础设施。本文的 SSH 改造,则将其中的身份管理进一步落实到密钥保管与签名授权。

我把这套方法写入了自己维护的个人智能体基座 GLOBAL 规则:人工 SSH 连接,包括 SSH 隧道,默认使用 Bitwarden Agent;每次签名提示授权;不默认创建或导出磁盘私钥。Agent 无法认证时应等待授权或报告原因,不能自行回退为密码登录或导出私钥。

这体现了一个清晰的职责划分:

组件 负责的事情 边界
Bitwarden 保管 SSH 私钥,提供签名和使用授权 不审批已经建立的会话中的每一条命令
SSH 客户端 建立连接、校验主机、向 Agent 请求签名 需要实际配置并验证 Agent 接入
服务器 校验公钥,限制账号权限和认证方式 客户端批准签名不会替代服务端权限控制
GLOBAL 与项目规则 记录身份路由、任务授权、恢复入口和验收要求 文字规范需要执行与核验才能生效

这样,智能体可以知道“该连接哪台服务器、以哪个账号工作”,却不需要拿到私钥正文。私钥保管、身份签名和任务执行被分配给不同组件,换电脑或换 Agent 宿主时,也无需把私钥文件复制进新的工作目录。

这套基座的公开结构可在Personal Agent Foundation 仓库中了解。本文描述的接入与验收来自我自己的环境;读者仍需在自己的终端、密码库和服务器上完成配置。

同时,所谓“智能体连接受到 Bitwarden 控制”,必须限定为已经接入该 Agent 的密钥签名路径。如果机器还保留另一把可用私钥、密码入口或其他凭据,工具就可能存在另一条认证路径。治理规则应覆盖这些来源,而不能只看一次授权弹窗。

我最终保留的连接方式

日常使用时,我仍然可以输入简洁的 ssh -p 端口 用户@域名,让 Bitwarden 请求使用授权。新的电脑登录密码库、开启 Agent 并完成系统配置后,就能使用同一套受管身份,不需要从旧电脑拷贝私钥。

恢复说明保留服务器地址、端口、账号、公钥和主机指纹核验方法;独立恢复入口也需要维护。把私钥交给 Bitwarden,意味着要认真保护密码库账户及其恢复能力。

这次改造给我的价值是具体的:私钥来源更统一,旧身份可以明确撤销,智能体的新连接需要我批准签名,换设备的恢复步骤也更清晰。能力仍然可以高效执行,而身份使用的决定留在人手中。

除特殊说明,博客文章均为东篱原创,依据 CC BY-SA 4.0 许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇