使用正确私钥连接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。
解决:- 从FileZilla的已信任服务器列表中导出服务器公钥;
- 测试阶段可临时用
ssh.InsecureIgnoreHostKey()跳过HostKey验证(仅测试用,生产环境禁用)。
验证私钥解析有效性
虽然ParsePrivateKeyWithPassphrase未报错,可添加日志确认签名器生成正常,比如:log.Printf("生成的签名器类型:%T", signer)排查网络与超时问题
- 用
telnet sftp.trustyou.com 22测试服务器端口是否可达; - 检查本地防火墙是否拦截出站22端口;
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
相关产品推荐
相关产品推荐

