feat: 增强 ssh-agent 认证与转发可靠性

- 拆分 ssh-agent 认证、连接与 endpoint 解析逻辑
- 新增 IdentityAgent、SSHAgentTimeout、SSHAgentForwardTimeout 和调试事件
- 为 agent list/sign 操作增加独立 deadline,避免硬件 agent 卡死登录
- 支持 agent signer 失败后跳过坏 key 并重试后续 key
- 优先处理 RSA-SHA2 签名,兼容现代 OpenSSH 认证要求
- 增强 agent forwarding 的探测、通道空闲超时和关闭清理
- 补充 Windows OpenSSH pipe 与 GPG S.gpg-agent.ssh socket 文件支持
- 增加相关回归测试和 Windows 编译验证覆盖
This commit is contained in:
2026-05-27 13:10:35 +08:00
parent ad7c8b0587
commit 0c23e7d4bf
10 changed files with 2173 additions and 294 deletions
+33 -3
View File
@@ -16,6 +16,7 @@ import (
const (
defaultSSHPort = 22
defaultLoginTimeout = 5 * time.Second
defaultSSHAgentTimeout = 2 * time.Minute
defaultKeepAliveTimeout = 3 * time.Second
defaultShellPollInterval = 120 * time.Millisecond
defaultShellSetupDelay = 200 * time.Millisecond
@@ -58,6 +59,20 @@ const (
AuthMethodSSHAgent AuthMethodKind = "ssh_agent"
)
type SSHAgentDebugFunc func(SSHAgentDebugEvent)
type SSHAgentDebugEvent struct {
Step string
Source string
Endpoint string
Network string
Phase string
Status string
Duration time.Duration
KeyCount int
Err error
}
type StarSSH struct {
stateMu sync.RWMutex
Client *ssh.Client
@@ -92,15 +107,30 @@ type LoginInput struct {
DisableSSHAgent bool
ForwardSSHAgent bool
AuthOrder []AuthMethodKind
Addr string
Port int
// IdentityAgent overrides the local ssh-agent endpoint used for authentication
// and agent forwarding. Empty uses SSH_AUTH_SOCK, or the platform default where
// one exists.
IdentityAgent string
Addr string
Port int
// Timeout limits the SSH handshake/authentication phase after a TCP connection has
// already been established. Zero means no authentication timeout.
Timeout time.Duration
// DialTimeout limits outbound dial steps such as TCP connect, proxy connect, and
// local ssh-agent socket connect. Zero falls back to Timeout when set, otherwise
// uses the package default dial timeout. Negative disables the default dial timeout.
DialTimeout time.Duration
DialTimeout time.Duration
// SSHAgentTimeout limits ssh-agent protocol operations such as listing keys and
// signing challenges. Zero uses the package default, and negative disables the
// per-operation deadline. This is intentionally separate from Timeout and
// DialTimeout because hardware-backed agents may require a PIN or touch confirmation.
SSHAgentTimeout time.Duration
// SSHAgentForwardTimeout limits idle reads and writes on forwarded agent
// channels. Zero or negative leaves forwarded channels without an idle deadline.
SSHAgentForwardTimeout time.Duration
// SSHAgentDebug receives structured ssh-agent dial/protocol events. It is nil by
// default and must not log private key material.
SSHAgentDebug SSHAgentDebugFunc
DialContext DialContextFunc
Proxy *ProxyConfig
Jump *LoginInput