duanjianxiu9400 2017-12-28 05:24
浏览 90

发送SSH命令以配置网络设备

I am writing a CLI for configuring Cisco access points through Cisco wireless controllers over SSH in Go 1.9.2. I am using the golang.org/x/crypto/ssh package to handle connecting to the wireless controllers. I am able to successfully SSH to the desired controller, but I'm running into problems when attempting to send commands to the controller. I know the problem is due to the controller's prompt and output to Stdout. When manually connecting to a controller, this is the output:

$ ssh <controller_ip>


(Cisco Controller)
User: username
Password:****************
(Cisco Controller) >

Everything I have read and all the code examples I have seen of similar problems use the bufio package to create a reader to deal with the prompts/output. I can get that to partially work, but the program hangs after printing the line (Cisco Controller) before the username prompt, like this:

$ go run main.go


(Cisco Controller)
# infinite blinking cursor

I know this is because the controller is expecting a username to be passed.

My question, then, is how do I correctly handle parsing the output and send commands to the controller? I'm new to GO and network programming in general, so any help is appreciated. Here is my full code so far:

const (
    HOST = "hostname"
)

func main() {
    hostKey, err := HostKeyCheck(HOST)
    if err != nil {
        log.Fatal(err)
    }

    key, err := ioutil.ReadFile("/Users/user/.ssh/id_rsa")
    if err != nil {
        log.Fatalf("unable to read private key: %v", err)
    }

    // Create the Signer for this private key.
    signer, err := ssh.ParsePrivateKey(key)
    if err != nil {
        log.Fatalf("unable to parse private key: %v", err)
    }

    // Create client config
    config := &ssh.ClientConfig{
        User: "username",
        Auth: []ssh.AuthMethod{
            ssh.Password("password"),
            // Use the PublicKeys method for remote authentication.
            ssh.PublicKeys(signer),
        },
        HostKeyCallback: ssh.FixedHostKey(hostKey),
        Timeout: time.Second * 5,
    }

    // Connect to the remote server and perform the SSH handshake.
    client, err := ssh.Dial("tcp", HOST+":22", config)
    if err != nil {
        log.Fatalf("unable to connect: %v", err)
    }
    defer client.Close()
    // Create a session
    session, err := client.NewSession()
    if err != nil {
        log.Fatal("Failed to create session: ", err)
    }
    defer session.Close()

    // Error occurs after this point
    var b bytes.Buffer
    session.Stdout = &b
    if err := session.Run("show"); err != nil {
        log.Fatalf("%v", err)
    }
    fmt.Println(b.String())        
}

func HostKeyCheck(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) {
            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
}

This is the output I get when running the program:

$ go run main.go
2017/12/28 14:13:28 ssh: command show failed
exit status 1
  • 写回答

1条回答 默认 最新

  • douhong4452 2017-12-29 00:30
    关注

    Here is an example: https://github.com/Scalingo/go-ssh-examples/blob/master/client.go

    Shouldn't you need to start a new session to initiate commands?

    Hope it helps.

    func connectToHost(user, host string) (*ssh.Client, *ssh.Session, error) {
        var pass string
        fmt.Print("Password: ")
        fmt.Scanf("%s
    ", &pass)
    
        sshConfig := &ssh.ClientConfig{
            User: user,
            Auth: []ssh.AuthMethod{ssh.Password(pass)},
        }
    
        sshConfig.HostKeyCallback = ssh.InsecureIgnoreHostKey()
    
        client, err := ssh.Dial("tcp", host, sshConfig)
        if err != nil {
            return nil, nil, err
        }
    
        session, err := client.NewSession()
        if err != nil {
            client.Close()
            return nil, nil, err
        }
    
        return client, session, nil
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型
  • ¥15 求学软件的前人们指明方向🥺
  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn