// 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 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 (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 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 (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 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 Run(Con *ssh.Client, cmd string) { defer Con.Close() s, err := Con.NewSession() if err != nil { color.Red("%s:新建会话失败.命令未执行.", Con.RemoteAddr()) return } fmt.Printf("成功连接:%s\n", Con.RemoteAddr()) buf, err := s.Output(cmd) if err != nil { color.Red("%s:命令执行失败.", Con.RemoteAddr()) return } str := fmt.Sprintf("%s 的执行结果:\n%s\n", Con.RemoteAddr().String(), string(buf)) fmt.Println(str) Result <- str }
func client(info cmd_info, result chan string, num chan int32, returnnum *int32) { defer func() { time.Sleep(1e9) num <- atomic.AddInt32(returnnum, -1) }() config := &ssh.ClientConfig{ User: info.user, Auth: []ssh.AuthMethod{ ssh.Password(info.passwd), }, } var client *ssh.Client var err error for i := 0; i < 5; i++ { client, err = ssh.Dial("tcp", info.ip, config) if err == nil { break } } if err != nil { fmt.Printf("%s 建立连接: %s\n", info.ip, err) return } defer client.Close() for _, v := range info.cmds { session, err := client.NewSession() if err != nil { fmt.Println("%s 创建Session出错: %s\n", info.ip, err) return } defer session.Close() buf, err := session.Output(v) if err != nil { fmt.Printf("%s 执行命令:%s出错:%s\n", info.ip, v, err) continue } result <- fmt.Sprintf("remote_PC:%s CMD:%s\n%s", info.ip, v, buf) } }
func TtyClient(Con *ssh.Client) error { defer Con.Close() session, err := Con.NewSession() if err != nil { return err } session.Stdout = os.Stdout session.Stderr = os.Stderr session.Stdin = os.Stdin modes := ssh.TerminalModes{ ssh.ECHO: 0, ssh.TTY_OP_ISPEED: 14400, ssh.TTY_OP_OSPEED: 14400, } err = session.RequestPty("xterm", 25, 100, modes) if err != nil { return err } session.Shell() return session.Wait() }
func scp(Client *ssh.Client, File io.Reader, size int64, path string) { filename := filepath.Base(path) dirname := strings.Replace(filepath.Dir(path), "\\", "/", -1) defer Client.Close() session, err := Client.NewSession() if err != nil { fmt.Println("创建Session失败:", err) return } go func() { w, _ := session.StdinPipe() fmt.Fprintln(w, "C0644", size, filename) io.CopyN(w, File, size) fmt.Fprint(w, "\x00") w.Close() }() if err := session.Run(fmt.Sprintf("/usr/bin/scp -qrt %s", dirname)); err != nil { fmt.Println("执行scp命令失败:", err) session.Close() return } else { fmt.Printf("%s 发送成功.\n", Client.RemoteAddr()) session.Close() } if session, err = Client.NewSession(); err == nil { defer session.Close() buf, err := session.Output(fmt.Sprintf("/usr/bin/md5sum %s", path)) if err != nil { fmt.Println("检查md5失败:", err) return } fmt.Printf("%s 的MD5:\n%s\n", Client.RemoteAddr(), string(buf)) } }
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 { if debug { fmt.Println(err) } return false } sFile, _ := os.Open(FileName) defer sFile.Close() dFile := DirectoryPath + FileName File, err := con.OpenFile(dFile, os.O_CREATE|os.O_TRUNC|os.O_RDWR) if err != nil { if debug { fmt.Println(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]) } return true }
// NewSession will open an ssh session using the provided connection func NewSession(client *ssh.Client) (*Session, error) { session, err := client.NewSession() if err != nil { return nil, err } s := &Session{ssh: session, client: client} // Set up terminal modes modes := ssh.TerminalModes{ ssh.ECHO: 0, // disable echoing ssh.TTY_OP_ISPEED: 115200, // input speed = 115.2kbps ssh.TTY_OP_OSPEED: 115200, // output speed = 115.2kbps } // Request pseudo terminal if err := session.RequestPty(termType, 80, 40, modes); err != nil { client.Close() return nil, err } session.Stdout = &s.out session.Stderr = &s.err return s, nil }
serverNetConn, clientNetConn := test_helpers.Pipe() sshd = daemon.New(logger, serverSSHConfig, nil, newChannelHandlers) connectionFinished = make(chan struct{}) go func() { sshd.HandleConnection(serverNetConn) close(connectionFinished) }() client = test_helpers.NewClient(clientNetConn, nil) }) AfterEach(func() { if client != nil { err := client.Close() Expect(err).NotTo(HaveOccurred()) } Eventually(connectionFinished).Should(BeClosed()) }) Context("when a session is opened", func() { var session *ssh.Session BeforeEach(func() { var sessionErr error session, sessionErr = client.NewSession() Expect(sessionErr).NotTo(HaveOccurred()) })
func forward(localConn net.Conn, config *ssh.ClientConfig, serverAddrString, remoteAddrString string) { defer localConn.Close() currentRetriesServer := 0 currentRetriesRemote := 0 var sshClientConnection *ssh.Client = nil // Loop for retries: for { // Try to connect to the SSH server: if sshClientConn, err := ssh.Dial(`tcp`, serverAddrString, config); err != nil { // Failed: currentRetriesServer++ log.Printf("Was not able to connect with the SSH server %s: %s\n", serverAddrString, err.Error()) // Is a retry alowed? if currentRetriesServer < maxRetriesServer { log.Println(`Retry...`) time.Sleep(1 * time.Second) } else { // After the return, this thread is closed down. The client can try it again... log.Println(`No more retries for connecting the SSH server.`) return } } else { // Success: log.Println(`Connected to the SSH server ` + serverAddrString) sshClientConnection = sshClientConn defer sshClientConnection.Close() break } } // Loop for retries: for { // Try to create the remote end-point: if sshConn, err := sshClientConnection.Dial(`tcp`, remoteAddrString); err != nil { // Failed: currentRetriesRemote++ log.Printf("Was not able to create the remote end-point %s: %s\n", remoteAddrString, err.Error()) // Is another retry allowed? if currentRetriesRemote < maxRetriesRemote { log.Println(`Retry...`) time.Sleep(1 * time.Second) } else { // After the return, this thread is closed down. The client can try it again... log.Println(`No more retries for connecting the remote end-point.`) return } } else { // Fine, the connections are up and ready :-) log.Printf("The remote end-point %s is connected.\n", remoteAddrString) defer sshConn.Close() // To be able to close down both transfer threads, we create a channel: quit := make(chan bool) // Create the transfers to/from both sides (two new threads are created for this): go transfer(localConn, sshConn, `Local => Remote`, quit) go transfer(sshConn, localConn, `Remote => Local`, quit) // Wait and look if any of the two transfer theads are down: isRunning := true for isRunning { select { case <-quit: log.Println(`At least one transfer was stopped.`) isRunning = false break } } // Now, close all the channels and therefore, force the other / second thread to go down: log.Println(`Close now all connections.`) return } } }
handler.HandleNewChannelStub = testHandler.HandleNewChannel newChannelHandlers := map[string]handlers.NewChannelHandler{ "direct-tcpip": handler, } serverNetConn, clientNetConn := test_helpers.Pipe() sshd = daemon.New(logger, serverSSHConfig, nil, newChannelHandlers) go sshd.HandleConnection(serverNetConn) client = test_helpers.NewClient(clientNetConn, nil) }) AfterEach(func() { client.Close() echoServer.Shutdown() }) Context("when a session is opened", func() { var conn net.Conn JustBeforeEach(func() { var dialErr error conn, dialErr = client.Dial("tcp", echoAddress) Expect(dialErr).NotTo(HaveOccurred()) }) AfterEach(func() { conn.Close() })
AfterEach(func() { if sshClient != nil { // restart addon_update with the default options switch framework.TestContext.OSDistro { case "debian": sshExec(sshClient, "sudo /etc/init.d/kube-addons restart") case "trusty": sshExec(sshClient, "sudo initctl restart kube-addons") case "coreos": sshExec(sshClient, "sudo systemctl unset-environment TEST_ADDON_CHECK_INTERVAL_SEC") sshExec(sshClient, "sudo systemctl restart kubernetes-addons") default: framework.Failf("Unsupported OS distro type %s", framework.TestContext.OSDistro) } sshClient.Close() } }) // WARNING: the test is not parallel-friendly! It("should propagate add-on file changes", func() { // This test requires: // - SSH // - master access // ... so the provider check should be identical to the intersection of // providers that provide those capabilities. framework.SkipUnlessProviderIs("gce") //these tests are long, so I squeezed several cases in one scenario Expect(sshClient).NotTo(BeNil()) dir = f.Namespace.Name // we use it only to give a unique string for each test execution
func (s *BotClientT) Start(botId string, botInstance int, cmdline string, cfg *ConfigT, debugLevel int) error { var err error var sshclient *ssh.Client var session *ssh.Session // var wg sync.WaitGroup var cmd string if s.Host[botInstance].Status == BotStatPaused { return nil } if s.Host[botInstance].Status == BotStatRunning { err = s.PingAt(botId, botInstance, cfg) if err == nil { Goose.Ping.Logf(2, "bot %s@%s is alive", botId, s.Host[botInstance].Name) return nil } } Goose.StartStop.Logf(2, "Starting bot %s@%s", botId, s.Host[botInstance].Name) s.Host[botInstance].Status = BotStatUnreachable if s.Host[botInstance].OnStatUpdate != nil { s.Host[botInstance].OnStatUpdate(BotStatUnreachable) } cfg.SshClientConfig.User = s.SysUser sshclient, err = ssh.Dial("tcp", s.Host[botInstance].Name+":22", cfg.SshClientConfig) if err != nil { Goose.StartStop.Logf(1, "%s (%s)", ErrDialingToBot, err) return ErrDialingToBot } defer sshclient.Close() Goose.StartStop.Logf(3, "Dialed to bot %s@%s", botId, s.Host[botInstance].Name) session, err = sshclient.NewSession() if err != nil { Goose.StartStop.Logf(1, "%s (%s)", ErrCreatingSession, err) return ErrCreatingSession } defer session.Close() Goose.StartStop.Logf(3, "Session started at bot %s@%s", botId, s.Host[botInstance].Name) /* wg.Add(1) go func() { defer wg.Done() w, _ := session.StdinPipe() defer w.Close() Goose.StartStop.Logf(2,"Closing stdin for bot %s",botId) //fmt.Fprintf(w, "%s\n", config) }() */ /* // 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 { Goose.StartStop.Fatalf(1,"request for pseudo terminal failed: %s", err) } session.Stdout = &bytes.Buffer{} session.Stderr = &bytes.Buffer{} */ cmd = fmt.Sprintf("%s%c%s -v %d %s", s.BinDir, os.PathSeparator, s.BinName, debugLevel, cmdline) Goose.StartStop.Logf(3, "Will run %s@%s using %s", botId, s.Host[botInstance].Name, cmd) err = session.Start(cmd) // err = session.Run(cmd) Goose.StartStop.Logf(2, "Running bot %s", botId) // wg.Wait() if err != nil { session.Signal(ssh.SIGKILL) Goose.StartStop.Logf(1, "%s (%s)", ErrFailedStartingBot, err) return ErrFailedStartingBot } Goose.StartStop.Logf(2, "Started bot %s with cmd:[%s]", botId, cmd) s.Host[botInstance].Status = BotStatRunning if s.Host[botInstance].OnStatUpdate != nil { s.Host[botInstance].OnStatUpdate(BotStatRunning) } return nil }
func sshExecNative(c conf.ServerInfo, cmd string, sudo bool, log ...*logrus.Entry) (result sshResult) { logger := getSSHLogger(log...) cmd = decolateCmd(c, cmd, sudo) logger.Debugf("Command: %s", strings.Replace(maskPassword(cmd, c.Password), "\n", "", -1)) var client *ssh.Client var err error client, err = sshConnect(c) defer client.Close() var session *ssh.Session if session, err = client.NewSession(); err != nil { logger.Errorf("Failed to new session. err: %s, c: %s", err, pp.Sprintf("%v", c)) 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 { logger.Errorf("Failed to request for pseudo terminal. err: %s, c: %s", err, pp.Sprintf("%v", c)) result.ExitStatus = 999 return } var stdoutBuf, stderrBuf bytes.Buffer session.Stdout = &stdoutBuf session.Stderr = &stderrBuf 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.Host = c.Host result.Port = c.Port logger.Debugf( "SSH executed. cmd: %s, err: %#v, status: %d\nstdout: \n%s\nstderr: \n%s", maskPassword(cmd, c.Password), err, result.ExitStatus, result.Stdout, result.Stderr) return }