Go语言网络编程:SSH连接
旨在提升Go语言网络编程能力
SSH是什么?
SSH 为 Secure Shell 的缩写,为建立在应用层基础上的安全协议。SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
通过使用SSH,可以把所有传输的数据进行加密,这样"中间人"这种攻击方式就不可能实现了,而且也能够防止DNS欺骗和IP欺骗。使用SSH,还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。
SSH如何工作?
SSH由服务器和客户端组成,在整个通信过程中,为建立安全的SSH通道,会经历如下几个阶段:
- 连接建立
SSH服务器在指定的端口侦听客户端的连接请求,在客户端向服务器发起连接请求后,双方建立一个TCP连接。
- 版本协商
SSH协议目前存在SSH1.X(SSH2.0之前的版本)和SSH2.0版本。SSH2.0协议相比SSH1.X协议来说,在结构上做了扩展,可以支持更多的认证方法和密钥交换方法,同时提高了服务能力。SSH服务器和客户端通过协商确定最终使用的SSH版本号。
- 算法协商
SSH支持多种加密算法,双方根据各自支持的算法,协商出最终用于产生会话密钥的密钥交换算法、用于数据信息加密的加密算法、用于进行数字签名和认证的公钥算法以及用于数据完整性保护的HMAC算法。
- 密钥交换
服务器和客户端通过密钥交换算法,动态生成共享的会话密钥和会话ID,建立加密通道。会话密钥主要用于后续数据传输的加密,会话ID用于在认证过程中标识该SSH连接。
- 用户认证
SSH客户端向服务器端发起认证请求,服务器端对客户端进行认证。SSH支持以下几种认证方式:
- 密码(password)认证:客户端通过用户名和密码的方式进行认证,将加密后的用户名和密码发送给服务器,服务器解密后与本地保存的用户名和密码进行对比,并向客户端返回认证成功或失败的消息。
- 密钥(publickey)认证:客户端通过用户名,公钥以及公钥算法等信息来与服务器进行认证。
- password-publickey认证:指用户需要同时满足密码认证和密钥认证才能登录。
- all认证:只要满足密码认证和密钥认证其中一种即可。
- 会话请求
认证通过后,SSH客户端向服务器端发送会话请求,请求服务器提供某种类型的服务,即请求与服务器建立相应的会话。
- 会话交互
会话建立后,SSH服务器端和客户端在该会话上进行数据信息的交互。
代码实现
可以使用Go语言的ssh包
go get golang.org/x/crypto/ssh
首先是向服务器发起请求,建立连接。这里使用ssh.Dial函数,
func Dial(network string, addr string, config *ClientConfig) (*Client, error)
SSH是基于TCP的,所以对该函数的第一个参数传入"TCP",第二个参数指定为IP地址,第三个参数是客户端配置信息。
ClientConfig结构如下:
type ClientConfig struct { Config User string Auth []AuthMethod HostKeyCallback HostKeyCallback BannerCallback BannerCallback ClientVersion string HostKeyAlgorithms []string Timeout time.Duration }
在该结构中首先要指定User,即用户名。Auth,同样要被指定,这个参数包含了可用于服务器的身份验证方法。最后要指定HostKeyCallBack,在加密握手期间调用HostKeyCallback以验证服务器的主机密钥。
上述函数包含了从建立连接到用户认证的过程,下面要创建一个会话。调用NewSession方法可以创建会话。
func (c *Client) NewSession() (*Session, error)
然后发起会话请求,使用如下函数
func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error
pty是伪终端,伪终端由终端模拟器提供,终端模拟器是一个运行在用户态的应用程序。
该函数的第四个参数是终端模式,这是一个map,可以传入一些键值,进行设置。
type TerminalModes map[uint8]uint32
最后要将会话的输入输出设置为系统的标准输入输出,使得用户可以直接从终端输入指令。
完整代码
package main import ( "golang.org/x/crypto/ssh" "log" "os" ) // 基本信息 const ( address = "xx.xx.xx.xx" username = "username" password = "password" ) func main() { // 设置配置信息 config := ssh.ClientConfig{ User: username, Auth: []ssh.AuthMethod{ssh.Password(password)}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 用于简单的认证 } // 与服务器建立连接 client, err := ssh.Dial("tcp", address, &config) if err != nil { log.Println(err) return } // 创建一个会话 session, _ := client.NewSession() defer session.Close() // 设置Terminal Mode modes := ssh.TerminalModes{ ssh.ECHO: 0, // 关闭回显 ssh.TTY_OP_ISPEED: 14400, // 设置传输速率 ssh.TTY_OP_OSPEED: 14400, } // 请求伪终端 err = session.RequestPty("linux", 32, 160, modes) if err != nil { log.Println(err) return } // 设置输入输出 session.Stdout = os.Stdout session.Stdin = os.Stdin session.Stderr = os.Stderr session.Shell() // 启动shell session.Wait() // 等待退出 }
运行
Activate the web console with: systemctl enable --now cockpit.socket Last login: Wed May 18 18:18:03 2022 [root@VM-4-16-centos ~]# uname Linux
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具