// sendSshKeepAlive is a helper which sends a [email protected] request // on the specified SSH connections and returns true of the request succeeds // within a specified timeout. func sendSshKeepAlive( sshClient *ssh.Client, conn net.Conn, timeout time.Duration) error { errChannel := make(chan error, 2) if timeout > 0 { time.AfterFunc(timeout, func() { errChannel <- TimeoutError{} }) } go func() { // Random padding to frustrate fingerprinting _, _, err := sshClient.SendRequest( "*****@*****.**", true, MakeSecureRandomPadding(0, TUNNEL_SSH_KEEP_ALIVE_PAYLOAD_MAX_BYTES)) errChannel <- err }() err := <-errChannel if err != nil { sshClient.Close() conn.Close() } return ContextError(err) }
func (n *SSHNode) getClientAndSession() (*ssh.Client, *ssh.Session, error) { var client *ssh.Client var s *ssh.Session var err error // Retry few times if ssh connection fails for i := 0; i < MaxSSHRetries; i++ { client, err = n.dial() if err != nil { time.Sleep(SSHRetryDelay) continue } s, err = client.NewSession() if err != nil { client.Close() time.Sleep(SSHRetryDelay) continue } return client, s, nil } return nil, nil, err }
func NewClient(conn *ssh.Client, readLimitBytesPerSecond, writeLimitBytesPerSecond int64, opts ...func(*sftp.Client) error) (*sftp.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 } if readLimitBytesPerSecond > 0 { pr = flowrate.NewReader(pr, readLimitBytesPerSecond) } if writeLimitBytesPerSecond > 0 { pw = flowrate.NewWriter(pw, writeLimitBytesPerSecond) } return sftp.NewClientPipe(pr, pw, opts...) }
func CopyLocalFileToRemote(client *ssh.Client, localFilePath string, filename string) error { // Each ClientConn can support multiple interactive sessions, // represented by a Session. session, err := client.NewSession() if err != nil { log.Fatal("Failed to create session: " + err.Error()) } defer session.Close() writer, err := session.StdinPipe() if err != nil { return err } defer writer.Close() go func() { fileContents, _ := ioutil.ReadFile(localFilePath + "/" + filename) content := string(fileContents) fmt.Fprintln(writer, "C0644", len(content), filename) fmt.Fprint(writer, content) fmt.Fprintln(writer, "\x00") // transfer end with \x00\ }() session.Run("/usr/bin/scp -t ./") return nil }
func handleLocalSshConn(lnConn net.Conn) { defer func() { if Config.Ssh_Reverse_Proxy.Exit_On_Panic { return } if r := recover(); r != nil { Log.Error("Recovered from panic in connection from "+ lnConn.RemoteAddr().String()+":", r) } }() Log.Info("Received connection from", lnConn.RemoteAddr()) var sClient *ssh.Client psConfig := getProxyServerSshConfig(&sClient) psConn, psChans, psReqs, err := ssh.NewServerConn(lnConn, psConfig) if err != nil { Log.Info("Could not establish connection with " + lnConn.RemoteAddr().String() + ": " + err.Error()) return } defer psConn.Close() defer sClient.Close() go ssh.DiscardRequests(psReqs) for newChannel := range psChans { handleChannel(newChannel, sClient) } Log.Info("Lost connection with", lnConn.RemoteAddr()) }
func ExecuteCmd(client *ssh.Client, command string, stdout *string, stderr *string) error { session, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer session.Close() //session.Setenv("PATH", "/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin") //apparently needs serverside support // Once a Session is created, you can execute a single command on // the remote side using the Run method. var b bytes.Buffer var a bytes.Buffer session.Stdout = &b session.Stderr = &a log.Printf("CMD: %s\n", command) if err := session.Run(command); err != nil { return err } if stdout != nil { *stdout = b.String() } if stderr != nil { *stderr = a.String() } return err }
func tunnelConnectionToPortUsingClient(localConn net.Conn, rport int, client *ssh.Client) { addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:"+strconv.Itoa(rport)) if err != nil { panic(err) } remoteConn, err := client.DialTCP("tcp", nil, addr) if err != nil { panic(err) } wg := sync.WaitGroup{} wg.Add(2) copyConn := func(writer, reader net.Conn) { defer wg.Done() CopyAndMeasureThroughput(writer, reader) } go copyConn(localConn, remoteConn) go copyConn(remoteConn, localConn) go func() { wg.Wait() localConn.Close() remoteConn.Close() }() }
func (n *SSHNode) getClientAndSession() (*ssh.Client, *ssh.Session, error) { var client *ssh.Client var s *ssh.Session var err error // Retry few times if ssh connection fails for i := 0; i < MaxSSHRetries; i++ { client, err = n.dial() if err != nil { time.Sleep(SSHRetryDelay) continue } s, err = client.NewSession() if err != nil { client.Close() time.Sleep(SSHRetryDelay) continue } modes := ssh.TerminalModes{ ssh.ECHO: 0, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400, } // Request pseudo terminal if err := s.RequestPty("xterm", 40, 80, modes); err != nil { return nil, nil, fmt.Errorf("failed to get pseudo-terminal: %v", err) } return client, s, nil } return nil, nil, err }
func CopyFile(conn *ssh.Client, FileName, DirectoryPath string) bool { defer conn.Close() if !strings.HasSuffix(DirectoryPath, "/") { DirectoryPath = DirectoryPath + "/" } con, err := sftp.NewClient(conn, sftp.MaxPacket(5e9)) if err != nil { color.Red("%s传输文件新建会话错误: %s\n", conn.RemoteAddr(), err) return false } sFile, _ := os.Open(FileName) defer sFile.Close() dFile := DirectoryPath + FileName fmt.Printf("%s 目标路径:%s\n", conn.RemoteAddr(), dFile) File, err := con.OpenFile(dFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR) if err != nil { color.Red("%s 创建文件%s错误: %s \n", conn.RemoteAddr(), dFile, err) return false } defer File.Close() for { buf := make([]byte, 1024) n, err := sFile.Read(buf) if err != nil { if err.Error() == "EOF" { break } return false } File.Write(buf[:n]) } Result <- fmt.Sprintf("上传%s到%s成功.\n", FileName, conn.RemoteAddr()) return true }
func tailFilesOnClient(client *ssh.Client, files []string, sudo bool, linec chan<- string, errc chan<- error) { var sessions []*ssh.Session closeSessions := func() { for _, session := range sessions { _ = session.Signal(ssh.SIGKILL) _ = session.Close() } } var wg sync.WaitGroup for _, file := range files { session, err := client.NewSession() if err != nil { closeSessions() errc <- fmt.Errorf("can't open session: %v", err) return } sessions = append(sessions, session) wg.Add(1) go func(file string) { defer wg.Done() err := tailFile(session, file, sudo, linec) if err != nil { errc <- err } }(file) } wg.Wait() }
func scpAndRun(client ssh.Client) { scpSession, err := client.NewSession() if err != nil { panic("Failed to create SCP session: " + err.Error()) } defer scpSession.Close() scriptContents := `#!/bin/bash echo "this script is located at $dirname $0" ` scriptReader := strings.NewReader(scriptContents) scpError := copy(int64(len(scriptContents)), os.FileMode(0777), "test-script", scriptReader, "/tmp/scripts/", scpSession) if scpError != nil { panic(scpError) } execSession, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer execSession.Close() var stdoutBytes bytes.Buffer execSession.Stdout = &stdoutBytes if err := execSession.Run("/tmp/scripts/test-script"); err != nil { panic("Failed to run: " + err.Error()) } }
func (p *Project) installOnRemote(step int, conn *ssh.Client) { // Git and some other programs can send us an unsuccessful exit (< 0) // even if the command was successfully executed on the remote shell. // On these cases, we want to ignore those errors and move onto the next step. ignoredError := "Reason was: ()" // Creates a session over the ssh connection to execute the commands session, err := conn.NewSession() if err != nil { log.Fatal("Failed to build session: ", err) } defer session.Close() var stdoutBuf bytes.Buffer session.Stdout = &stdoutBuf fmt.Println(p.typ.program.setup[step]) err = session.Run(p.typ.program.setup[step]) if err != nil && !strings.Contains(err.Error(), ignoredError) { log.Printf("Command '%s' failed on execution", p.typ.program.setup[step]) log.Fatal("Error on command execution: ", err.Error()) } }
//Execute ssh commands until "exit" is entered func runCommands(client *ssh.Client) { var cmd string for strings.ToLower(cmd) != "exit" { //Creates a new session. Only one command per session session, err := client.NewSession() if err != nil { panic("Failed to create session: " + err.Error()) } defer session.Close() fmt.Scanf("%s", &cmd) var b bytes.Buffer session.Stdout = &b err1 := session.Run(cmd) if err1 != nil { fmt.Print("You used an invalid command.") err1 = nil } fmt.Println(b.String()) } //clear the terminal and display conn closed clear := exec.Command("clear") clear.Stdout = os.Stdout clear.Run() fmt.Println("\n\nConnection Closed") }
func sshExec(client *ssh.Client, cmd string) (string, string, int, error) { framework.Logf("Executing '%s' on %v", cmd, client.RemoteAddr()) session, err := client.NewSession() if err != nil { return "", "", 0, fmt.Errorf("error creating session to host %s: '%v'", client.RemoteAddr(), err) } defer session.Close() // Run the command. code := 0 var bout, berr bytes.Buffer session.Stdout, session.Stderr = &bout, &berr err = session.Run(cmd) if err != nil { // Check whether the command failed to run or didn't complete. if exiterr, ok := err.(*ssh.ExitError); ok { // If we got an ExitError and the exit code is nonzero, we'll // consider the SSH itself successful (just that the command run // errored on the host). if code = exiterr.ExitStatus(); code != 0 { err = nil } } else { // Some other kind of error happened (e.g. an IOError); consider the // SSH unsuccessful. err = fmt.Errorf("failed running `%s` on %s: '%v'", cmd, client.RemoteAddr(), err) } } return bout.String(), berr.String(), code, err }
func connectProxy(sshc *ssh.Client, h http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method != "CONNECT" { h.ServeHTTP(w, r) return } host := r.URL.Host if strings.Index(host, ":") < 0 { host += ":80" } sconn, err := sshc.Dial("tcp", host) if err != nil { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusBadGateway) w.Write([]byte(err.Error())) return } w.WriteHeader(http.StatusOK) cconn, _, err := w.(http.Hijacker).Hijack() if err != nil { cconn.Close() sconn.Close() log.Print("CONNECT hijack error: ", err) return } go proxyconn(cconn, sconn) go proxyconn(sconn, cconn) } }
func newSSHListener(sshClient *ssh.Client, exposedBind string, exposedPort int) (net.Listener, error) { sshListener, err := sshClient.Listen("tcp", joinHostPort(exposedBind, exposedPort)) if err != nil { return nil, err } return sshListener, nil }
func sshExecNative(c conf.ServerInfo, cmd string, sudo bool) (result execResult) { result.Servername = c.ServerName result.Host = c.Host result.Port = c.Port var client *ssh.Client var err error if client, err = sshConnect(c); err != nil { result.Error = err result.ExitStatus = 999 return } defer client.Close() var session *ssh.Session if session, err = client.NewSession(); err != nil { result.Error = fmt.Errorf( "Failed to create a new session. servername: %s, err: %s", c.ServerName, err) result.ExitStatus = 999 return } defer session.Close() // http://blog.ralch.com/tutorial/golang-ssh-connection/ 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 } if err = session.RequestPty("xterm", 400, 256, modes); err != nil { result.Error = fmt.Errorf( "Failed to request for pseudo terminal. servername: %s, err: %s", c.ServerName, err) result.ExitStatus = 999 return } var stdoutBuf, stderrBuf bytes.Buffer session.Stdout = &stdoutBuf session.Stderr = &stderrBuf cmd = decolateCmd(c, cmd, sudo) if err := session.Run(cmd); err != nil { if exitErr, ok := err.(*ssh.ExitError); ok { result.ExitStatus = exitErr.ExitStatus() } else { result.ExitStatus = 999 } } else { result.ExitStatus = 0 } result.Stdout = stdoutBuf.String() result.Stderr = stderrBuf.String() result.Cmd = strings.Replace(cmd, "\n", "", -1) return }
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) }
func RunCommand(c *ssh.Client, cmd string) error { s, err := c.NewSession() defer s.Close() if err != nil { return errors.Wrap(err, "Error creating new session for ssh client") } return s.Run(cmd) }
func RunCommand(c *ssh.Client, cmd string) error { s, err := c.NewSession() defer s.Close() if err != nil { return err } return s.Run(cmd) }
func createSession(client *ssh.Client) (*ssh.Session, error) { fmt.Println("Creating new session") session, err := client.NewSession() if err != nil { fmt.Println("Failed to create session") fmt.Println("Error : ", err.Error()) return nil, err } return session, nil }
// NewPty creates a new SSH session to the client using inCh as stdin, and quiting on a receive to quit. // Returns stdout, stderr channels and error channel func NewPty(client *ssh.Client, inCh <-chan []byte, quit <-chan struct{}) (<-chan []byte, <-chan []byte, <-chan error) { errCh := make(chan error, 1) // Create a new session from the given configuration func. session, err := client.NewSession() if err != nil { errCh <- err return nil, nil, nil } // Get session std in/out/err stdin, stdout, stderr, err := sessionStreams(session) if err != nil { errCh <- err return nil, nil, nil } // Stream from readers to channels stdoutCh := make(chan []byte) stderrCh := make(chan []byte) go streamToChan(stdout, stdoutCh, errCh) go streamToChan(stderr, stderrCh, errCh) // Set terminal modes modes := ssh.TerminalModes{ ssh.VREPRINT: 0, ssh.CS8: 1, ssh.ECHOE: 1, ssh.ECHOCTL: 0, } // Request pseudo terminal err = session.RequestPty("xterm", 24, 80, modes) //err = session.RequestPty("vt100", 24, 80, modes) if err != nil { errCh <- err return nil, nil, nil } // Invoke SSH shell err = session.Shell() if err != nil { errCh <- err return nil, nil, nil } // Listen for input/quit go func() { for { select { case b := <-inCh: stdin.Write(b) case <-quit: session.Close() return } } }() return stdoutCh, stderrCh, errCh }
func ChangeDir(client *ssh.Client, dir string) error { session, err := client.NewSession() if err != nil { return err } defer session.Close() err = session.Run(`bash -c "cd ` + dir + `"`) if err != nil { return err } return nil }
func Mkdir(client *ssh.Client, destDir string) error { session, err := client.NewSession() if err != nil { return err } defer session.Close() err = session.Run(`bash -c "mkdir -p ` + destDir + `"`) if err != nil { return err } 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 NewSession(conn *ssh.Client, deadline *time.Time, idleTimeout int) (ss *SshSession, err error) { session, err := conn.NewSession() if err != nil { return nil, err } sshSession := new(SshSession) sshSession.session = session sshSession.deadline = deadline sshSession.idleTimeout = idleTimeout sshSession.id = Rand().Hex() //check session timeout go sshSession.checkSessionTimeout() return sshSession, nil }
func Pwd(client *ssh.Client) (string, error) { session, err := client.NewSession() if err != nil { return "", err } defer session.Close() output, err := session.CombinedOutput(`bash -c "pwd"`) if err != nil { return "", err } return string(output), nil }
func runRemoteCmd(client *ssh.Client, cmd string, args ...string) (string, error) { session, err := client.NewSession() if err != nil { return "", fmt.Errorf("failed to create session: %s", err) } defer session.Close() var out bytes.Buffer session.Stdout = &out session.Stderr = &out fullCmd := shellJoin(cmd, args) if err := session.Run(fullCmd); err != nil { return "", fmt.Errorf("failed to run %s: %s", fullCmd, err) } return out.String(), nil }
func readSecret(client *ssh.Client) (string, error) { session, err := client.NewSession() if err != nil { return "", err } defer session.Close() var b bytes.Buffer session.Stdout = &b if err := session.Run("cat /etc/openvpn/secret.key"); err != nil { return "", err } return b.String(), nil }
func sendFileToRemoteHost(client *ssh.Client, limit int64, sourceFile, targetUser, targetHost, targetFile string) { session, err := client.NewSession() if err != nil { log.Fatalln("Failed to create session: " + err.Error()) } defer session.Close() go func() { iw, err := session.StdinPipe() if err != nil { log.Fatalln("Failed to create input pipe: " + err.Error()) } w := flowrate.NewWriter(iw, limit) src, srcErr := os.Open(sourceFile) if srcErr != nil { log.Fatalln("Failed to open source file: " + srcErr.Error()) } srcStat, statErr := src.Stat() if statErr != nil { log.Fatalln("Failed to stat file: " + statErr.Error()) } fmt.Fprintln(w, "C0644", srcStat.Size(), filepath.Base(sourceFile)) if srcStat.Size() > 0 { bar := pb.New(int(srcStat.Size())) bar.Units = pb.U_BYTES bar.ShowSpeed = true bar.Start() wp := io.MultiWriter(w, bar) fmt.Printf("Transferring %s to %s@%s:%s\n", sourceFile, targetUser, targetHost, targetFile) fmt.Printf("Speed limited to %d bytes/sec\n", limit) io.Copy(wp, src) bar.Finish() fmt.Fprint(w, "\x00") w.Close() } else { fmt.Printf("Transferred empty file %s to %s@%s:%s\n", sourceFile, targetUser, targetHost, targetFile) fmt.Fprint(w, "\x00") w.Close() } }() if err := session.Run(fmt.Sprintf("scp -t %s", targetFile)); err != nil { log.Fatalln("Failed to run: " + err.Error()) } }