内容简介:使用ssh打个隧道,是我一直想做的事情。出发点是:在公司内部经常有些机器访问不到,只能通过公司提供的开发机,但是开发机我们可以在内网访问到,这个SSH是一种网络协议,用于计算机之间的加密登录,流程大致是:上面这个过程中很容易受到攻击的就是第一步,我们怎么知道收到的公钥是真正的主机的,体现在实际登陆中,就是会出现:
使用ssh打个隧道,是我一直想做的事情。出发点是:在公司内部经常有些机器访问不到,只能通过公司提供的开发机,但是开发机我们可以在内网访问到,这个
基础知识
SSH是一种网络协议,用于计算机之间的加密登录,流程大致是:
- 远程主机收到用户的登录请求,把自己的公钥发给用户。
- 用户使用这个公钥,将登录密码加密后,发送回来。
- 远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。
上面这个过程中很容易受到攻击的就是第一步,我们怎么知道收到的公钥是真正的主机的,体现在实际登陆中,就是会出现:
$ ssh user@host The authenticity of host 'host (12.18.429.21)' can't be established. RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. Are you sure you want to continue connecting (yes/no)? 复制代码
此处 RSA key fingerprint
就是对128公钥的MD5签名,当输入yes后,就会保存到$HOME/.ssh/known_hosts,说明是对公钥的认可。
解决了信任问题后,下一个不好的是每次都需要输入密码,于是就有了 公钥登陆 ,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求密码。
所以总结起来 ssh 认证的方式有两种:
- 用户名 + 证书
- 用户名 + 密码
下面我们来看 go 中相应的操作方法
golang 实现 ssh client
go get -u golang.org/x/crypto/... 复制代码
先来说2种认证方式,显示密码,通过 ssh.Password
来传入密码
sshConfig := &ssh.ClientConfig{
User: "your_user_name",
Auth: []ssh.AuthMethod{
ssh.Password("your_password")
},
}
复制代码
第二种是证书的方式,这又细分为两种,一种是我们直接读取自己的私钥,另一种是从ssh-agent读取,ssh-agent是用来帮助我们管理私钥的程序,它的出现主要是为了解决当我们访问不同的主机使用不同的私钥-公钥对,同时解决如果设置了私钥的密码,需要每次都手动设置的问题。 ps:ssh-agent的管理
eval `ssh-agent` 启动agent代理 ssh-add /path/to/key/key_name 添加指定私钥 ssh-agent -k 关闭 agent ssh-add -l 查看代理中私钥 ssh-add -L 查看代理中私钥对应的公钥 ssh-add -d /path/to/key/key_name 移除指定私钥 ssh-add -D 删除管理的所有私钥 复制代码
从文件读取
func PublicKeyFile(file string) ssh.AuthMethod {
buffer, err := ioutil.ReadFile(file)
if err != nil {
return nil
}
key, err := ssh.ParsePrivateKey(buffer)
if err != nil {
return nil
}
return ssh.PublicKeys(key)
}
复制代码
从 ssh-agent 读取
func SSHAgent() ssh.AuthMethod {
if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
return ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)
}
return nil
}
复制代码
client生成
当我们有了认证方式后,下面就是生成ssh-client
sshClient, err := ssh.Dial("tcp", "host:port", sshConfig)
if err != nil {
return nil, fmt.Errorf("Failed to dial: %s", err)
}
复制代码
建立连接后,我们要创建一个命令执行的session,一个session就是一次命令执行,在开始执行命令之前,我们还要建立一个伪终端,方便输入输出
modes := ssh.TerminalModes{
ssh.ECHO: 0, // disable echoing
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
session.Close()
return nil, fmt.Errorf("request for pseudo terminal failed: %s", err)
}
复制代码
再然后我们就可以开始执行代码,完整代码见 ssh_client
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机程序设计艺术
Donald E. Knuth / 李伯民、范明、蒋爱军 / 人民邮电出版社 / 2016-1-1 / 198
《计算机程序设计艺术》系列是公认的计算机科学领域经典之作,深入阐述了程序设计理论,对计算机领域的发展有着极为深远的影响。本书是该系列的第 1 卷,讲解基本算法,其中包含了其他各卷都需用到的基本内容。本卷从基本概念开始,然后讲述信息结构,并辅以大量的习题及答案。一起来看看 《计算机程序设计艺术》 这本书的介绍吧!