You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用正确私钥连接SFTP服务器超时(Golang)求助

Golang SFTP客户端公私钥连接异常排查

问题背景

用Golang开发SFTP客户端,服务器要求公私钥认证。已提交4096位公钥并获取用户名,通过FileZilla搭配私钥可正常连接,但Golang客户端在执行ssh.Dial时要么永久挂起,要么触发超时。

问题代码

keyFile := filepath.Join(dir, "id_rsa")
pkBytes, err := os.ReadFile(keyFile)
if err != nil {
    return err
}
signer, err := ssh.ParsePrivateKeyWithPassphrase(pkBytes, []byte("mysecret"))
if err != nil {
    return err
}

username := "my_username"
sftpDir := "/home/upload/"

keyFile = filepath.Join(dir, "id_rsa.pub")
pkBytes, err = os.ReadFile(keyFile)
if err != nil {
    return err
}

hostKey, _, _, _, err := ssh.ParseAuthorizedKey(pkBytes)
if err != nil {
    return err
}

clientConfig := &ssh.ClientConfig{
    User:            username,
    Auth:            []ssh.AuthMethod{ssh.PublicKeys(signer)},
    HostKeyCallback: ssh.FixedHostKey(hostKey),
    Timeout:         10 * time.Second,
}

conn, err := ssh.Dial("tcp", "sftp.trustyou.com:22", clientConfig)
// here we stop or hang forever.... :-( 
if err != nil {
    log.Fatalf("SSH DIAL FAILED:%v", err)
}
defer conn.Close()

排查与修复方案

  • 核心错误:HostKey配置错误
    你当前把自己的公钥当成服务器的HostKey来验证了!ssh.FixedHostKey(hostKey)需要传入的是服务器的公钥,而非本地的id_rsa.pub。
    解决:

    1. 从FileZilla的已信任服务器列表中导出服务器公钥;
    2. 测试阶段可临时用ssh.InsecureIgnoreHostKey()跳过HostKey验证(仅测试用,生产环境禁用)。
  • 验证私钥解析有效性
    虽然ParsePrivateKeyWithPassphrase未报错,可添加日志确认签名器生成正常,比如:

    log.Printf("生成的签名器类型:%T", signer)
    
  • 排查网络与超时问题

    1. 用telnet sftp.trustyou.com 22测试服务器端口是否可达;
    2. 检查本地防火墙是否拦截出站22端口;
    3. Timeout仅控制Dial阶段超时,若认证阶段卡住,需结合调试日志定位。
  • 兼容服务器SSH算法
    部分服务器仅支持特定SSH算法,Golang默认算法可能与FileZilla存在差异,可在ClientConfig中指定兼容算法:

    clientConfig := &ssh.ClientConfig{
        // 原有配置...
        Config: ssh.Config{
            Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr"},
            KeyExchanges: []string{"diffie-hellman-group-exchange-sha256", "diffie-hellman-group14-sha256"},
            MACs: []string{"hmac-sha2-256", "hmac-sha2-512"},
        },
    }
    
  • 开启SSH调试日志
    添加日志输出,查看握手过程细节,定位卡环节点:

    func init() {
        log.SetFlags(log.LstdFlags | log.Lshortfile)
        ssh.SetDebug(func(msg string) {
            log.Println("SSH DEBUG:", msg)
        })
    }
    

内容的提问来源于stack exchange,提问作者Igor Pigin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 16:41:32