func (s *SftpSession) Connect() error { addr := fmt.Sprintf("%s:%d", s.section.Server, s.section.Port) var err error if s.section.ProxyServer != "" { paddr := fmt.Sprintf("%s:%d", s.section.ProxyServer, s.section.ProxyPort) log.Printf("connect to proxy %s", paddr) conn, err := net.Dial("tcp", paddr) if err != nil { return err } // http connect connstr := []byte("CONNECT " + addr + " HTTP/1.1\r\nHost: " + addr + "\r\n\r\n") if _, err := conn.Write(connstr); err != nil { return errors.New("failed to write connect to http proxy at " + paddr + ": " + err.Error()) } status, err := bufio.NewReader(conn).ReadString('\n') if err != nil { log.Printf("response: \n%s\n", status) return errors.New("failed to read response from http proxy at " + paddr + ": " + err.Error()) } if !strings.Contains(status, " 200 ") { return errors.New("error response from http proxy at " + paddr + ": " + status) } // CONNECT www.google.com.au:443 HTTP/1.1 // Host: www.google.com.au:443 // // HTTP/1.0 200 Connection Established // Proxy-agent: Apache sshconn, inch, inrq, err := ssh.NewClientConn(conn, paddr, &s.sshConfig) if err != nil { return err } s.connection = ssh.NewClient(sshconn, inch, inrq) } else { log.Printf("connect to %s", addr) s.connection, err = ssh.Dial("tcp", addr, &s.sshConfig) if err != nil { return err } } // start sftp s.client, err = sftp.NewClient(s.connection) if err != nil { return fmt.Errorf("unable to start sftp subsytem: %v", err) } return nil }
// Create an SSH session that can connect to an XR router and run one // potentially long-lived command, interacting over stdin/stdout func NewXrSession(host string, creds *Creds, cmd string) (*XrSession, error) { auth, err := get_auth(creds) if err != nil { return nil, err } sshConfig := &ssh.ClientConfig{ User: creds.User, Auth: auth, Config: ssh.Config{Ciphers: []string{"aes128-ctr", "aes128-cbc"}}, } client, err := ssh.Dial("tcp", host, sshConfig) if err != nil { return nil, errors.New("Can't connect: " + err.Error()) } session, err := client.NewSession() if err != nil { return nil, errors.New("Can't create session: " + err.Error()) } stdin, err := session.StdinPipe() if err != nil { return nil, errors.New("Can't create stdin pipe: " + err.Error()) } stdout, err := session.StdoutPipe() if err != nil { return nil, errors.New("Can't create stdout pipe: " + err.Error()) } err = session.Start(cmd) if err != nil { return nil, errors.New("Can't start command: " + err.Error()) } xrsession := &XrSession{ session: session, stdin: &stdin, stdout: &stdout, ready: false, } // Swallow the preamble of a couple of blank lines and a date go func() { buf := make([]byte, 128) // just needs to be big enough _, err := stdout.Read(buf) if err != nil { panic("Can't read preamble: " + err.Error()) } xrsession.ready = true }() return xrsession, nil }