【免费下载链接】kr
DEPRECATED A dev tool for SSH auth + Git commit/tag signing using a key stored in Krypton.
krd 是 kr 工具包的核心守护进程:它只是一个常驻的 Go 二进制文件,却同时管理三类 UNIX socket——控制通道、SSH agent 通道和主机认证通道,让 SSH 登录与 Git 签名请求都能安全地路由到手机上的 Krypton 应用。本文带你逐行看懂这个"一进程三 socket"的设计。
⚠️ 提示:kr 项目已标记为 DEPRECATED(开发已迁至 akr 项目),但 krd 的这套架构设计依然很有参考价值。
krd 启动流程:一个 main 函数串起三条监听线
krd 的入口在 src/krd/main.go,启动顺序非常清晰:
- 升级本地
~/.ssh/config中的旧配置(见 src/daemon/sshconfig.go) - 打开通知器并启动通知文件清理协程
- 依次调用
DaemonListen()、AgentListen()、HostAuthListen()打开三个 socket - 用两个 goroutine 分别托管 HTTP 控制服务和 SSH agent 服务,主协程阻塞等待退出信号
三类 socket 的文件名常量都定义在 src/common/socket/socket.go#L81-L118:
| socket 文件 | 常量 | 角色 | 客户端 |
|---|---|---|---|
~/.kr/krd.sock | DAEMON_SOCKET_FILENAME | 控制平面:HTTP 风格的命令通道 | krCLI、krgpg |
~/.kr/krd-agent.sock | AGENT_SOCKET_FILENAME | SSH agent:响应 List/Sign 等 agent 协议 | ssh(经IdentityAgent配置) |
~/.kr/krd-hostauth.sock | HOST_AUTH_FILENAME | 主机认证:接收主机公钥证据 | krssh代理 |
三个 socket 都放在~/.kr/目录下(目录权限 0700),并在每次监听前删除可能残留的旧 socket 文件,避免上次异常退出导致的"address in use"。
控制 socketkrd.sock:守护进程的大脑
krd.sock上跑的不是原始 TCP 协议,而是一个标准http.ServeMux,路由定义在 src/daemon/control/server.go#L44-L52:
GET /ping:健康检查,客户端用它判断 krd 是否存活GET /version:返回 krd 版本号,kr用它检测"是否有旧版 krd 仍在运行"GET/PUT/DELETE /pair:查询、发起、解除手机配对POST /enclave:把签名请求(SSH 签名、Git commit/tag 签名、hosts 校验)转发到"enclave",最终送达手机
这条通道的意义在于:kr命令行和krgpg(Git 签名接口)都不需要各自实现复杂协议,只要拨号 + 发一个 HTTP 请求即可。连接封装在 src/common/socket/socket.go#L153-L171 的DaemonDialWithTimeout中——先pingDaemon探活,5 秒超时则报ping timed out,探活成功后才真正建连。
客户端侧的调用示例见 src/daemon/client/client.go,例如RequestKrdVersion()就是拨号后发GET /version。
agent socketkrd-agent.sock:伪装成 SSH agent,把私钥留在手机上
这是最巧妙的一个设计。安装时 kr 会往~/.ssh/config写入如下配置(模板见 src/kr/sshconfig.go#L28-L36):
Host * IdentityAgent ~/.kr/krd-agent.sock ProxyCommand /usr/bin/krssh %h %pIdentityAgent是 OpenSSH 7.3+ 的选项,让ssh直接把 krd 当作本地 agent 使用。于是 SSH 认证时发生的事是:
ssh通过 agent 协议向 krd 发出Sign请求(要签的数据是 SSH 会话 ID)- krd 的 Agent.Sign 先尝试回落到你原有的
SSH_AUTH_SOCK(withOriginalAgent,见 src/daemon/ssh_agent.go#L36-L50),如果本地已有同一把公钥就直接用,行为透明 - 否则把
SignRequest通过 enclave 通道发到手机,由用户在 Krypton App 上点"允许"或"拒绝" - 签名原样返回给 ssh,私钥从未离开手机
agent 服务的主循环在 ServeKRAgent:每个新连接交给一个 goroutine 执行agent.ServeAgent,互不阻塞。
📌 顺带一提:krd 还有一套基于~/.kr/notify/krd-notify.log-*文件的"旁路通知"机制(src/common/socket/notify.go),因为 SSH 协议本身没有通道回传"手机已批准/已拒绝"这类消息,krd 就把提示写进通知文件,由krssh侧的读取协程实时打印到终端。
hostauth socketkrd-hostauth.sock:给主机身份"拍照存证"
第三个 socket 专门服务于 krssh 这个 SSH 代理。流程是:
krssh作为ProxyCommand启动,双向透传 SSH 流量,同时旁路解析 SSH 包- 当解析到 key exchange 的 KEX 应答报文(含主机公钥 + 签名,见 src/krssh/main.go#L65-L88 的
tryParse),就组装成一个HostAuthJSON - 通过
HostAuthDial()拨号krd-hostauth.sock把它发给 krd(src/krssh/main.go#L55-L63) - krd 收到后进入 onHostAuth:用主机公钥验证签名,写入最近的会话记录,并唤醒正在
awaitHostAuthFor等待的签名流程
这样,用户手机上批准签名时看到的就不只是"某台机器要签名",而是这台机器的真实公钥指纹——即使有人伪造了主机名,签名请求里携带的主机证据也会暴露不匹配,krd 会通知krssh直接终止会话(HOST_KEY_MISMATCH)。
单进程如何稳住三条线:并发模型与自愈
看懂三个 socket 后,再看 main.go 的整体并发结构就一目了然了:
main 协程 ├── goroutine: controlServer.Start() + HandleControlHTTP(daemonSocket) ├── goroutine: daemon.ServeKRAgent(enclaveClient, agentSocket, hostAuthSocket) │ └── 内部还有 goroutine 循环 Accept hostauth 连接 └── 阻塞 <-stopSignal(SIGTERM/SIGKILL/...),收到后 controlServer.Stop()几个工程细节值得学习:
- 信号统一收口:
signal.Notify监听os.Interrupt、SIGTERM等,退出前先停 enclave 客户端,保证配对状态干净落盘(见 src/krd/main.go#L90-L96) - 故障自愈:客户端拨号失败时会自动
pkill krd并用nohup krd重启后重试,见 src/common/socket/socket_unix.go#L15-L34 - 系统级托管:Linux 下用 systemd 单元(模板见 install/systemd-service-as-current-user.sh,
Restart=on-failure按当前用户运行),macOS 下用 LaunchAgent(install/macos/share_ext/co.krypt.krd.plist),配合make start一键装好(Makefile#L42-L47)
常见问题速查
| 现象 | 原因与处理 |
|---|---|
Could not connect to Krypton daemon | krd 没在运行,执行kr restart即可 |
ping timed out | krd 卡死或版本过旧,客户端会自动尝试重启 krd |
An old version of krd is still running | 新旧 krd 共存,kr restart后重试 |
终端出现Krypton ▶ Requesting SSH authentication from phone | 正常工作流:等待你在 Krypton App 中批准 |
关键源码文件导航
- 守护进程入口:src/krd/main.go
- socket 路径与拨号逻辑:src/common/socket/socket.go
- 自动重启逻辑(Linux/FreeBSD):src/common/socket/socket_unix.go
- 控制服务与 HTTP 路由:src/daemon/control/server.go
- SSH agent 实现:src/daemon/ssh_agent.go
- krssh 代理与主机证据采集:src/krssh/main.go
- krgpg Git 签名接口:src/krgpg/main.go
- 客户端请求封装:src/daemon/client/client.go
- 通知文件机制:src/common/socket/notify.go
总结
krd 用一个 Go 进程 + 三个职责分离的 UNIX socket,把"控制命令、SSH agent、主机证据回传"三条数据流解耦:CLI 工具走 HTTP 风格控制面,ssh 走标准 agent 协议,主机验证走轻量 JSON 通道。三者共享同一个 enclave 客户端,最终都汇聚到手机端的 Krypton App 做人工批准——这正是"私钥永不离开手机"这一安全模型的工程落点。
【免费下载链接】kr
DEPRECATED A dev tool for SSH auth + Git commit/tag signing using a key stored in Krypton.
相关推荐
fail2ban.client.csocket 源码解析:Fail2Ban 客户端与守护进程的 Unix Socket 通信协议
fail2ban.client.csocket 源码解析:Fail2Ban 客户端与守护进程的 Unix Socket 通信协议 导读 fail2ban.cli
网络安全运维microduck 机器人整体架构解析:七个守护进程、Unix Socket 控制面与更新安全路径
microduck 机器人整体架构解析:七个守护进程、Unix Socket 控制面与更新安全路径 本文基于 docs/design/architecture.
机器人嵌入式具身智能智能硬件明日方舟工具箱:你的终极干员培养助手,快速规划精英化材料
明日方舟工具箱:你的终极干员培养助手,快速规划精英化材料 如果你是明日方舟玩家,是否经常为计算干员精英化材料而头疼?是否在公开招募时犹豫不决?现在, 明日方舟工
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考