golang.org/x/crypto/ssh 新连接时怎么保存HOSTKEY到known_hosts文件

lkkk · 2018-01-27 11:52:42 · 1702 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2018-01-27 11:52:42 的主题,其中的信息可能已经有所发展或是发生改变。

使用golang.org/x/crypto/ssh 连接远程时, 如果是第一次连接, 且known_hosts文件中没有保存远程主机的KEY, 就报错: “no hostkey for 192.168.1.100” 怎么在第一次连接时自动保存key到known_hosts文件? 没有看到crypto/ssh源文件中有这样的方法。

###

 func getHostKey(host string) (ssh.PublicKey, error) {
        file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
        if err != nil {
                return nil, err
        }
        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 {
                                return nil, errors.New(fmt.Sprintf("error parsing %q: %v", fields[2], err))
                        }
                        break
                }
        }

        if hostKey == nil {
                return nil, errors.New(fmt.Sprintf("no hostkey for %s", host))
        }
        return hostKey, nil
}
func main() {

        hostKey, err := getHostKey("192.168.1.100")
        if err != nil {
                        panic(err)
        }

        config := &ssh.ClientConfig{
                User: "root",
                Auth: []ssh.AuthMethod{
                        ssh.Password("xxxxxx"),
                },
                //HostKeyCallback: ssh.InsecureIgnoreHostKey(),   //这个可以, 但是不够安全
                HostKeyCallback: ssh.FixedHostKey(hostKey),
                Timeout:         30 * time.Second,
        }
        client, err := ssh.Dial("tcp", "192.168.1.100:22", config)
        if err != nil {
                panic("Failed to dial: " + err.Error())
        }

        session, err := client.NewSession()
        if err != nil {
                panic("Failed to create session: " + err.Error())
        }
        defer session.Close()

        var b bytes.Buffer
        session.Stdout = &b
        if err := session.Run("ls"); err != nil {
                panic("Failed to run: " + err.Error())
        }
        fmt.Println(b.String())

}

###


有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1702 次点击  
加入收藏 微博
3 回复  |  直到 2020-08-29 20:05:56
channel
channel · #1 · 7年之前

路过~没玩过这个

GopherJ
GopherJ · #2 · 7年之前

应该是需要你预置的,就像ssh一样,第一次(本机known_hosts无远端主机公钥)总会显示对方的hostkey,问你是否信任,这个时候也很有可能是中间人给你发送的hostkey而非远端主机,那你还不是只能接受?

我觉得跳过,也就是默认信任这个hostkey的来源就行了。

bpxyz
bpxyz · #3 · 5年之前

这是出于安全角度考虑的,如同2楼所讲。 第一次连接时,你需要手动验证对端的pubkey并添加到known_hosts文件里

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传