如何让Google Cloud Function建立SSH连接访问SFTP服务器
解决方案
方案1:硬编码主机公钥(最推荐,无额外依赖,安全性最高)
主机公钥本身是公开信息,直接硬编码到代码中完全不存在安全风险,也不需要额外部署文件或配置,适配Cloud Function无状态运行环境,步骤如下:
- 本地执行命令获取目标SFTP服务器的公钥:
ssh-keyscan -p <你的SFTP端口> <你的SFTP主机地址>
从输出中找到对应主机的条目,复制第三个字段的公钥字符串。 - 替换原有逻辑,去掉读known_hosts的逻辑,直接解析硬编码的公钥,修改后的代码示例:
// 直接硬编码你从ssh-keyscan拿到的公钥字符串 const sftpHostPubKey = "你复制的公钥字符串" func Connect(host string, port string, user string, password string) (*ssh.Client, error) { // 解析硬编码的主机公钥 hostKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(sftpHostPubKey)) if err != nil { return nil, err } var auths []ssh.AuthMethod if password != "" { auths = append(auths, ssh.Password(password)) } config := &ssh.ClientConfig{ User: user, HostKeyCallback: ssh.FixedHostKey(hostKey), Auth: auths, } // 原有追加加密算法的逻辑保留,解决negotiate错误 cipherOrder := config.Ciphers config.Ciphers = append(cipherOrder, "aes128-cbc", "3des-cbc") return ssh.Dial("tcp", host+":"+port, config) }
方案2:用环境变量存储公钥(灵活性更高)
如果公钥可能会变更,不想每次改代码重新部署,可以将公钥字符串配置到Google Cloud Function的环境变量中,代码中直接读取环境变量解析即可:
func Connect(host string, port string, user string, password string) (*ssh.Client, error) { pubKeyStr := os.Getenv("SFTP_HOST_PUBKEY") hostKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(pubKeyStr)) if err != nil { return nil, err } // 后续配置和拨号逻辑和方案1完全一致,省略 }
部署时在Cloud Function的环境变量配置页新增SFTP_HOST_PUBKEY,值填你拿到的公钥字符串即可。
不推荐临时方案:跳过主机密钥校验
如果仅做临时测试,不需要考虑中间人攻击风险,可以直接将HostKeyCallback设置为ssh.InsecureIgnoreHostKey(),完全不需要处理公钥逻辑,但生产环境禁止使用:
config := &ssh.ClientConfig{ User: user, HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 跳过校验,生产环境禁用 Auth: auths, }
你原有追加aes128-cbc、3des-cbc加密算法的逻辑完全可以保留,不需要修改,即可解决Unable to negotiate的报错。
内容的提问来源于stack exchange,提问作者antipopp
相关产品推荐
相关产品推荐

