使用golang.org/x/crypto/ssh 连接远程时, 如果是第一次连接, 且known_hosts文件中没有保存远程主机的KEY, 就报错:
“no hostkey for 192.168.1.100”
怎么在第一次连接时自动保存key到known_hosts文件? 没有看到crypto/ssh源文件中有这样的方法。
###
```go
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
}```
```go
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())
}```
###
更多评论
应该是需要你预置的,就像ssh一样,第一次(本机known_hosts无远端主机公钥)总会显示对方的hostkey,问你是否信任,这个时候也很有可能是中间人给你发送的hostkey而非远端主机,那你还不是只能接受?
我觉得跳过,也就是默认信任这个hostkey的来源就行了。
#2