带你一步步使用 Golang 实现 SSH 客户端
最佳答案 问答题库698位专家为你答疑解惑
SSH 全称为 Secure Shell,是一种用于安全地远程登录到网络上的其他计算机的网络协议。相信做后端开发的同学没有不了解 SSH的,比较常用的登录服务器的 shell 工具例如 Xshell、SecureCRT、iTerm2 等都是基于 SSH 协议实现的。Golang 中的的 crypto/ssh 包提供了实现 SSH 客户端的功能,本文接下来详细讲解下如何使用 Golang 实现 SSH 客户端。
创建 SSH 客户端配置
首先需要配置一下 SSH 客户端连接服务器的参数,最基本的配置包括用户名、认证方法和主机密钥回调。示例代码如下:
package mainimport "golang.org/x/crypto/ssh"func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}
}
在这个配置中,设置了用户名为"username",密码为"password"。使用 ssh.Password 函数来创建一个密码认证方法。HostKeyCallback 函数会在每次连接到一个新的主机时被调用,用于验证服务器的主机密钥。本例中使用了 ssh.InsecureIgnoreHostKey,意思是接受任何主机密钥。生产环境中不建议这么用,因为不验证主机密钥,存在安全风险。
连接到 SSH 服务器
使用 ssh.Dial 函数可以连接到远程的 SSH 服务器。需要三个参数:网络类型(通常是"tcp"),服务器的地址和端口,以及之前创建的配置对象。示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}
}
连接到 IP 为192.168.3.111服务器的22端口(SSH协议的默认端口),如果连接失败,将返回一个错误,可以使用 log.Fatal 打印错误并退出程序。
创建 SSH 会话
建立了 SSH 连接后就可以创建 SSH 会话了,可以通过会话与服务器进行通信。示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}session, err := client.NewSession()if err != nil {log.Fatal("Failed to create session: ", err)}defer session.Close()
}
使用 client.NewSession 方法创建一个新的会话,如果创建失败,将返回一个错误。使用 defer 关键字来确保会话在操作结束后被关闭。
创建伪终端
SSH 协议可以创建伪终端(pseudo terminal),伪终端模拟了一个真实的终端行为,可以运行交互式命令,如 shell 或文本编辑器等。示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}session, err := client.NewSession()if err != nil {log.Fatal("Failed to create session: ", err)}defer session.Close()modes := ssh.TerminalModes{ssh.ECHO: 0, // disable echoingssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaudssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud}if err := session.RequestPty("linux", 80, 40, modes); err != nil {log.Fatal("request for pseudo terminal failed: ", err)}
}
使用 session.RequestPty 方法请求一个伪终端,需要四个参数:终端类型(这里使用"xterm"),终端的宽度和高度,以及一个设置终端模式的 map。在这个 map 中设置了 ssh.ECHO 为0,这将禁止回显,还设置了输入和输出的速度为14.4 kbaud。
设置输入输出
指定远程 shell 的标准输入和输出,示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log""os"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}session, err := client.NewSession()if err != nil {log.Fatal("Failed to create session: ", err)}defer session.Close()modes := ssh.TerminalModes{ssh.ECHO: 0, // disable echoingssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaudssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud}if err := session.RequestPty("linux", 80, 40, modes); err != nil {log.Fatal("request for pseudo terminal failed: ", err)}//设置输入输出session.Stdout = os.Stdoutsession.Stdin = os.Stdinsession.Stderr = os.Stderr
}
启动远程 shell
一个远程 shell 已经准备就绪了,可以使用 session.Shell 方法启动一个默认的 shell,或者使用 session.Run 方法来运行一个指定的命令。示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}session, err := client.NewSession()if err != nil {log.Fatal("Failed to create session: ", err)}defer session.Close()modes := ssh.TerminalModes{ssh.ECHO: 0, // disable echoingssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaudssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud}if err := session.RequestPty("linux", 80, 40, modes); err != nil {log.Fatal("request for pseudo terminal failed: ", err)}//设置输入输出session.Stdout = os.Stdoutsession.Stdin = os.Stdinsession.Stderr = os.Stderrif err := session.Shell(); err != nil {log.Fatal("failed to start shell: ", err)}
}
启动了一个默认的 shell,如果启动失败,将返回一个错误。
等待会话结束
使用 session.Wait 方法来阻塞,直到会话结束。示例代码如下:
package mainimport ("golang.org/x/crypto/ssh""log""os"
)func main() {config := &ssh.ClientConfig{User: "username",Auth: []ssh.AuthMethod{ssh.Password("password"),},HostKeyCallback: ssh.InsecureIgnoreHostKey(),}client, err := ssh.Dial("tcp", "192.168.3.111:22", config)if err != nil {log.Fatal("Failed to dial: ", err)}session, err := client.NewSession()if err != nil {log.Fatal("Failed to create session: ", err)}defer session.Close()modes := ssh.TerminalModes{ssh.ECHO: 0, // disable echoingssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaudssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud}if err := session.RequestPty("linux", 80, 40, modes); err != nil {log.Fatal("request for pseudo terminal failed: ", err)}//设置输入输出session.Stdout = os.Stdoutsession.Stdin = os.Stdinsession.Stderr = os.Stderrif err := session.Shell(); err != nil {log.Fatal("failed to start shell: ", err)}err = session.Wait()if err != nil {log.Fatal("Failed to run: " + err.Error())}
}
到这里,就完成了一个基本的 SSH 客户端的实现了。这个客户端可以连接到一个 SSH 服务器并启动一个远程 shell,然后等待会话结束。
小结
本文实现的 SSH 客户端只是提供了最基本的功能,要实现一个功能完备、体验良好的 SSH 客户端需要注意很多的细节处理,例如错误处理、重新连接、超时、信号处理等。
99%的人还看了
相似问题
- 当前系统并无桌面环境,或无显示器,无法显示远程桌面,您需要自行安装X11桌面环境,或者使用终端文件功能
- iTerm2+oh-my-zsh搭个Mac电脑上好用好看终端
- 终端仿真软件 SecureCRT v9.4.2
- vscode终端npm install报错
- 基于RK3588全高端智能终端机器人主板
- 智慧能源太阳能光伏数据采集终端钡铼技术4G无线RTU
- vue网页使用远程终端加终端多开
- 【启扬方案】启扬安卓屏一体机在医疗自助服务终端上的应用解决方案
- Cisco Packet Tracer路由器连接终端设备怎么配置?思科路由器连接终端设备怎么配置?
- 使用 Wireshark 抓包工具快速分析 IoT 物联网终端设备的网络通信行为
猜你感兴趣
版权申明
本文"带你一步步使用 Golang 实现 SSH 客户端":http://eshow365.cn/6-35858-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!
- 上一篇: python+robotframework接口自动化测试
- 下一篇: 06.Oracle数据备份与恢复