package main import ( "fmt" "io" "log" "os" "os/exec" "syscall" "unsafe" "github.com/creack/pty" "github.com/gliderlabs/ssh" "github.com/pkg/sftp" ) func SftpHandler(sess ssh.Session) { debugStream := io.Discard serverOptions := []sftp.ServerOption{ sftp.WithDebug(debugStream), } server, err := sftp.NewServer( sess, serverOptions..., ) if err != nil { log.Printf("sftp tcpserver init error: %s\n", err) return } if err := server.Serve(); err == io.EOF { server.Close() fmt.Println("sftp client exited session.") } else if err != nil { fmt.Println("sftp tcpserver completed with error:", err) } } func passwordAuth(ctx ssh.Context, password string) bool { // Replace with your own logic to validate username and password return ctx.User() == "abc" && password == "123" } func setWinsize(f *os.File, w, h int) { syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&struct{ h, w, x, y uint16 }{uint16(h), uint16(w), 0, 0}))) } func main() { ssh.Handle(func(s ssh.Session) { cmd := exec.Command("bash") ptyReq, winCh, isPty := s.Pty() if isPty { cmd.Env = append(os.Environ(), fmt.Sprintf("TERM=%s", ptyReq.Term)) f, err := pty.Start(cmd) if err != nil { panic(err) } go func() { for win := range winCh { setWinsize(f, win.Width, win.Height) } }() go func() { io.Copy(f, s) // stdin }() io.Copy(s, f) // stdout cmd.Wait() } else { io.WriteString(s, "No PTY requested.\n") s.Exit(1) } }) log.Println("starting ssh tcpserver on port 2222...") server := ssh.Server{ Addr: ":2222", PasswordHandler: passwordAuth, SubsystemHandlers: map[string]ssh.SubsystemHandler{ "sftp": SftpHandler, }, } log.Fatal(server.ListenAndServe()) }