如何让我的 GCloud Function 打开一个新的 SSH 连接来使用 SFTP 服务器?
How can I make my GCloud Function open a new SSH connection to consume a SFTP server?
我的设置需要一个 Google 函数来做一些事情并将结果上传到 SFTP 服务器。我目前正在使用基本的 sftp
和 crypto/ssh
包来实现这一点。在本地,经过一些调试,我能够检索到服务器的公钥。
当部署到 GCloud 时,当然没有任何效果。
这就是处理我函数上的连接的原因
func Connect(host string, port string, user string, password string) (*ssh.Client, error) {
hostKey := getHostKey(host)
var auths []ssh.AuthMethod
// Use password authentication if provided
if password != "" {
auths = append(auths, ssh.Password(password))
}
config := &ssh.ClientConfig{
User: user,
HostKeyCallback: ssh.FixedHostKey(hostKey),
Auth: auths,
}
cipherOrder := config.Ciphers
config.Ciphers = append(cipherOrder, "aes128-cbc", "3des-cbc")
sshConn, err := ssh.Dial("tcp", host+":"+port, config)
if err != nil {
return nil, err
}
return sshConn, nil
}
func getHostKey(host string) ssh.PublicKey {
file, err := os.Open("/root/.ssh/known_hosts")
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read known_hosts file: %v\n", err)
os.Exit(1)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var hostKey ssh.PublicKey
for scanner.Scan() {
fields := strings.Split(scanner.Text(), " ")
if len(fields) != 3 {
continue
}
if strings.Contains(fields[0], host) {
var err error
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing %q: %v\n", fields[2], err)
os.Exit(1)
}
break
}
}
if hostKey == nil {
fmt.Fprintf(os.Stderr, "No hostkey found for %s", host)
os.Exit(1)
}
return hostKey
}
known_hosts
文件不存在。我没有服务器的公钥,但使用 Filezilla 我可以很好地连接到它。
我必须指定那些密码,因为准系统 ssh hostname
会 return Unable to negotiate...
错误
还有其他方法吗?我正在考虑上传我自己的 known_hosts
文件,但这听起来不是一个很好的解决方案。
我可能设计过度了。
像这样设置 ssh.ClientConfig
解决了问题:
config := &ssh.ClientConfig{
User: user,
Auth: auths,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
无论如何我也找到了一个更好的包来轻松处理 SSH 连接,simplessh
。
conn, _ := simplessh.ConnectWithPassword(host, user, pass)
client, _ := sftp.NewClient(conn.SSHClient)
我的设置需要一个 Google 函数来做一些事情并将结果上传到 SFTP 服务器。我目前正在使用基本的 sftp
和 crypto/ssh
包来实现这一点。在本地,经过一些调试,我能够检索到服务器的公钥。
当部署到 GCloud 时,当然没有任何效果。
这就是处理我函数上的连接的原因
func Connect(host string, port string, user string, password string) (*ssh.Client, error) {
hostKey := getHostKey(host)
var auths []ssh.AuthMethod
// Use password authentication if provided
if password != "" {
auths = append(auths, ssh.Password(password))
}
config := &ssh.ClientConfig{
User: user,
HostKeyCallback: ssh.FixedHostKey(hostKey),
Auth: auths,
}
cipherOrder := config.Ciphers
config.Ciphers = append(cipherOrder, "aes128-cbc", "3des-cbc")
sshConn, err := ssh.Dial("tcp", host+":"+port, config)
if err != nil {
return nil, err
}
return sshConn, nil
}
func getHostKey(host string) ssh.PublicKey {
file, err := os.Open("/root/.ssh/known_hosts")
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read known_hosts file: %v\n", err)
os.Exit(1)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var hostKey ssh.PublicKey
for scanner.Scan() {
fields := strings.Split(scanner.Text(), " ")
if len(fields) != 3 {
continue
}
if strings.Contains(fields[0], host) {
var err error
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing %q: %v\n", fields[2], err)
os.Exit(1)
}
break
}
}
if hostKey == nil {
fmt.Fprintf(os.Stderr, "No hostkey found for %s", host)
os.Exit(1)
}
return hostKey
}
known_hosts
文件不存在。我没有服务器的公钥,但使用 Filezilla 我可以很好地连接到它。
我必须指定那些密码,因为准系统 ssh hostname
会 return Unable to negotiate...
错误
还有其他方法吗?我正在考虑上传我自己的 known_hosts
文件,但这听起来不是一个很好的解决方案。
我可能设计过度了。
像这样设置 ssh.ClientConfig
解决了问题:
config := &ssh.ClientConfig{
User: user,
Auth: auths,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
无论如何我也找到了一个更好的包来轻松处理 SSH 连接,simplessh
。
conn, _ := simplessh.ConnectWithPassword(host, user, pass)
client, _ := sftp.NewClient(conn.SSHClient)