//transfer a directory to remote host,with single tcp and tar.gz format //Stdout will be ignore. //Stderr will treat as an error from remote command func CopyDirectory(client *ssh.Client, selfPath string, remotePath string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[CopyDirectory]Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } defer w.Close() errBuf := &bytes.Buffer{} session.Stderr = errBuf escapedRemotePath := kmgCmd.BashEscape(remotePath) err = session.Start(fmt.Sprintf("mkdir -p %s;tar -xz -C %s", escapedRemotePath, escapedRemotePath)) if err != nil { return fmt.Errorf("[CopyDirectory] Failed to Run: %s", err.Error()) } err = kmgTar.PackageDirectoryTarGz(selfPath, w) if err != nil { return } err = w.Close() if err != nil { return } err = session.Wait() if err != nil { return fmt.Errorf("[CopyDirectory] session.Wait() err:%s", err.Error()) } if errBuf.Len() != 0 { return fmt.Errorf("[CopyDirectory] remote: %s", string(errBuf.Bytes())) } return nil }
func (p *Jobs) runCmd(i int, cmd string, client *ssh.Client, outfile *os.File) { session, err := client.NewSession() if err != nil { log.Fatal("Failed to create SSH session to server [" + p.Servers[i] + "] with error: " + err.Error()) } defer session.Close() session.Stdout = outfile session.Stderr = outfile // Set up terminal modes 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 } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { log.Fatalf("request for pseudo terminal failed: %s", err) } err = session.Start(cmd) if err != nil { log.Fatal("run command ["+cmd+"] on server ("+p.Servers[i]+") failed with -> ", err) } err = session.Wait() // TODO: make cmd not longer than 80 if err == nil { log.Printf("[%15s] %-80s %s%s%s", p.Servers[i], cmd, CLR_G, "√", CLR_N) } else { log.Printf("[%15s] %-80s %s%s%s", p.Servers[i], cmd, CLR_R, "✗", CLR_N) } }
// New creates a new SFTP client on conn. func NewClient(conn *ssh.Client) (*Client, error) { s, err := conn.NewSession() if err != nil { return nil, err } if err := s.RequestSubsystem("sftp"); err != nil { return nil, err } pw, err := s.StdinPipe() if err != nil { return nil, err } pr, err := s.StdoutPipe() if err != nil { return nil, err } sftp := &Client{ w: pw, r: pr, } if err := sftp.sendInit(); err != nil { return nil, err } return sftp, sftp.recvVersion() }
func cmdExecRemote(sshc *ssh.Client, args ...string) { cmd := strings.Join(args, " ") log.Printf("Executing (remotely) %s", cmd) if DUMMY { return } sshs, err := sshc.NewSession() if err != nil { log.Fatalf("Could not create ssh session: %v", err) } defer sshs.Close() stdout, err := sshs.StdoutPipe() if err != nil { log.Fatalf("Could not get stdout of ssh session: %v", err) } stderr, err := sshs.StderrPipe() if err != nil { log.Fatalf("Could not get stderr of ssh session: %v", err) } err = sshs.Start(cmd) if err != nil { log.Fatalf("Could not execute command: %v", err) } go io.Copy(os.Stdout, stdout) go io.Copy(os.Stderr, stderr) err = sshs.Wait() if err != nil { log.Fatalf("Error executing (remote) command: %v", err) } }
func combined(c *ssh.Client, cmd string) ([]byte, error) { s, err := c.NewSession() if err != nil { return nil, err } defer s.Close() return s.CombinedOutput(cmd) }
//transfer a file to remote host,with single tcp and gz format //Stdout will be ignore. //Stderr will treat as an error from remote command //TODO test func CopyFile(client *ssh.Client, selfPath string, remotePath string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[CopyFile]Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } defer w.Close() errReader, err := session.StderrPipe() if err != nil { return } escapedRemotePath := kmgCmd.BashEscape(remotePath) escapedRemoteDir := kmgCmd.BashEscape(path.Dir(remotePath)) err = session.Start(fmt.Sprintf("mkdir -p %s;cat > %s", escapedRemoteDir, escapedRemotePath)) if err != nil { return fmt.Errorf("[CopyFile] Failed to Start: %s", err.Error()) } f, err := os.Open(selfPath) if err != nil { return } defer f.Close() //gzipW := gzip.NewWriter(w) //defer gzipW.Close() _, err = io.Copy(w, f) if err != nil { return fmt.Errorf("[CopyFile] io.Copy: %s", err) } //err = gzipW.Close() //if err!=nil{ // return //} err = w.Close() if err != nil { return } errBytes, err := ioutil.ReadAll(errReader) if err != nil { return } if len(errBytes) != 0 { return fmt.Errorf("[CopyFile] remote: %s", string(errBytes)) } err = session.Wait() if err != nil { return fmt.Errorf("[CopyFile] session.Wait() err:%s", err.Error()) } return nil }
func Hop(through *ssh.Client, toaddr string, c *ssh.ClientConfig) (*ssh.Client, error) { hopconn, err := through.Dial("tcp", toaddr) if err != nil { return nil, err } conn, chans, reqs, err := ssh.NewClientConn(hopconn, toaddr, c) if err != nil { return nil, err } return ssh.NewClient(conn, chans, reqs), nil }
func (v *vm) Run(command string, attempts attempt.Strategy, out io.Writer, stderr io.Writer) error { var sc *ssh.Client err := attempts.Run(func() (err error) { fmt.Fprintf(stderr, "Attempting to ssh to %s:22...\n", v.IP()) sc, err = v.DialSSH() return }) if err != nil { return err } defer sc.Close() sess, err := sc.NewSession() sess.Stdin = bytes.NewBufferString(command) sess.Stdout = out sess.Stderr = stderr if err := sess.Run("bash"); err != nil { return fmt.Errorf("failed to run command on %s: %s", v.IP(), err) } return nil }
func NewTunnelledSSHClient(user, tunaddr, tgtaddr string, checker *HostKeyChecker, agentForwarding bool, timeout time.Duration) (*SSHForwardingClient, error) { clientConfig, err := sshClientConfig(user, checker) if err != nil { return nil, err } tunaddr = maybeAddDefaultPort(tunaddr) tgtaddr = maybeAddDefaultPort(tgtaddr) var tunnelClient *gossh.Client dialFunc := func(echan chan error) { var err error tunnelClient, err = gossh.Dial("tcp", tunaddr, clientConfig) echan <- err } err = timeoutSSHDial(dialFunc, timeout) if err != nil { return nil, err } var targetConn net.Conn dialFunc = func(echan chan error) { tgtTCPAddr, err := net.ResolveTCPAddr("tcp", tgtaddr) if err != nil { echan <- err return } targetConn, err = tunnelClient.DialTCP("tcp", nil, tgtTCPAddr) echan <- err } err = timeoutSSHDial(dialFunc, timeout) if err != nil { return nil, err } c, chans, reqs, err := gossh.NewClientConn(targetConn, tgtaddr, clientConfig) if err != nil { return nil, err } return newSSHForwardingClient(gossh.NewClient(c, chans, reqs), agentForwarding) }
// ForwardToAgent routes authentication requests to the given keyring. func ForwardToAgent(client *ssh.Client, keyring Agent) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go func() { ServeAgent(keyring, channel) channel.Close() }() } }() return nil }
func copyFile(c *ssh.Client, r io.Reader, path string) error { s, err := c.NewSession() if err != nil { return err } defer s.Close() w, err := s.StdinPipe() if err != nil { return err } s.Start("tee " + path) _, err = io.Copy(w, r) if err != nil { return err } w.Close() return s.Wait() }
//run sudo a command in remote and ask password in current console, //Stdout will goto current console too. //Stderr will treat as an error from remote command func SudoCommand(client *ssh.Client, cmd string) (err error) { session, err := client.NewSession() if err != nil { return fmt.Errorf("[SudoCommand] Failed to create session: %s", err.Error()) } defer session.Close() w, err := session.StdinPipe() if err != nil { return } session.Stdout = os.Stdout errBuf := &bytes.Buffer{} session.Stderr = errBuf // Set up terminal modes 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 } // Request pseudo terminal if err := session.RequestPty("xterm", 80, 40, modes); err != nil { return fmt.Errorf("[SudoCommand] request for pseudo terminal failed: %s", err) } err = session.Start(cmd) if err != nil { return fmt.Errorf("[SudoCommand] Failed to Start: %s", err.Error()) } pass := gopass.GetPasswd() w.Write(append(pass, byte('\n'))) err = session.Wait() if err != nil { return fmt.Errorf("[SudoCommand] session.Wait err: %s", err.Error()) } if errBuf.Len() != 0 { return fmt.Errorf("[SudoCommand] remote err: %s", err.Error()) } return nil }
// ForwardToRemote routes authentication requests to the ssh-agent // process serving on the given unix socket. func ForwardToRemote(client *ssh.Client, addr string) error { channels := client.HandleChannelOpen(channelType) if channels == nil { return errors.New("agent: already have handler for " + channelType) } conn, err := net.Dial("unix", addr) if err != nil { return err } conn.Close() go func() { for ch := range channels { channel, reqs, err := ch.Accept() if err != nil { continue } go ssh.DiscardRequests(reqs) go forwardUnixSocket(channel, addr) } }() return nil }
func createPipeNet(client *ssh.Client, cmd string) (pn *PipeNet, err error) { session, err := client.NewSession() if err != nil { return } pn = &PipeNet{ wa: session, c: client, name: "ssh", } pn.w, err = session.StdinPipe() if err != nil { return } pn.r, err = session.StdoutPipe() if err != nil { return } err = session.Start(cmd) return }
// Start port forwarding for the given SSH client: func loop(sshClient *ssh.Client, localToRemote, remoteToLocal []PortForward) { done := make(chan bool, 1) // Intercept termination signals: sigc := make(chan os.Signal, 1) signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM, syscall.SIGQUIT) go func() { sig := <-sigc log.Printf("Caught signal: %s\n", sig) done <- true }() // Forward all the local-to-remote ports: for _, fwd := range localToRemote { // Set up forwarding addresses: localAddr := fwd.LocalAddr remoteAddr := fwd.RemoteAddr log.Printf("Forwarding connections from local %s to remote %s\n", localAddr, remoteAddr) go func() { localListener, err := net.Listen("tcp", localAddr) if err != nil { log.Printf("unable to listen: %s\n", err) done <- true return } defer localListener.Close() log.Printf("Listening...\n") // Begin accepting new connections from the SSH tunnel: for { // Accept a new local connection: local, err := localListener.Accept() if err != nil { log.Printf("Accept: %s\n", err) break } logContext := local.RemoteAddr().String() log.Printf("%s: Accepted local connection.\n", logContext) // Connect to the remote RDP service: remote, err := sshClient.Dial("tcp", remoteAddr) if err != nil { log.Printf("%s: Unable to connect via SSH: %s\n", logContext, err) local.Close() continue } defer remote.Close() // Start forwarding data back 'n forth: go forward(local, remote, logContext) } }() } // Forward all remote-to-local ports: for _, fwd := range remoteToLocal { // Set up forwarding addresses: localAddr := fwd.LocalAddr remoteAddr := fwd.RemoteAddr // Resolve local address: var err error localTCPAddr, err := net.ResolveTCPAddr("tcp", localAddr) if err != nil { log.Printf("unable to resolve local address: %s\n", err) done <- true return } log.Printf("Forwarding connections from remote %s to local %s\n", remoteAddr, localAddr) go func() { // Request the remote side to open a port for forwarding: l, err := sshClient.Listen("tcp", remoteAddr) if err != nil { log.Printf("unable to register tcp forward: %s\n", err) return } log.Printf("Listening...\n") defer l.Close() // Begin accepting new connections from the SSH tunnel: for { // Accept a new remote connection from SSH: remote, err := l.Accept() if err != nil { log.Printf("Accept: %s\n", err) done <- true break } logContext := remote.RemoteAddr().String() log.Printf("%s: Accepted new SSH tunnel connection.\n", logContext) // Connect to the local RDP service: local, err := net.DialTCP("tcp", nil, localTCPAddr) if err != nil { log.Printf("%s: Could not open local connection to: %s\n", logContext, localTCPAddr) remote.Close() continue } // Start forwarding data back 'n forth: go forward(local, remote, logContext) } }() } <-done }