英文:
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
// 如果提供了密码,则使用密码身份验证
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, "无法读取known_hosts文件:%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, "解析%q时出错:%v\n", fields[2], err)
os.Exit(1)
}
break
}
}
if hostKey == nil {
fmt.Fprintf(os.Stderr, "找不到%s的主机密钥", host)
os.Exit(1)
}
return hostKey
}
known_hosts
文件不存在。我没有服务器的公钥,但是使用Filezilla我可以正常连接到它。
我不得不指定这些密码,因为一个简单的ssh hostname
命令会返回无法协商...
错误。
有其他的方法可以做到这一点吗?我在考虑上传自己的known_hosts
文件,但这听起来不是一个好的解决方案。
英文:
My setup requires a Google Function to do some stuff and upload the result to a SFTP server. I'm currently using the basic sftp
and crypto/ssh
packages to achieve this. Locally, after some debugging, I was able to retrieve the server's pubkey.
When deploying to GCloud nothing works, of course.
This is what handles the connection on my function
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
}
The known_hosts
file doesn't exist. I don't have the pubkey of the server, but with Filezilla I can connect to it just fine.
I had to specify those cyphers because a barebone ssh hostname
would return Unable to negotiate...
error
Is there any other way to do this? I'm thinking about uploading my own known_hosts
file but it doesn't sound like a great solution.
答案1
得分: 0
我可能过度工程化了。
像这样设置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)
英文:
I was probably over engineering it.
Setting the ssh.ClientConfig
like this solved the problem:
config := &ssh.ClientConfig{
User: user,
Auth: auths,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
Anyway I also found a nicer package to easily handle SSH connection, simplessh
.
conn, _ := simplessh.ConnectWithPassword(host, user, pass)
client, _ := sftp.NewClient(conn.SSHClient)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论