-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
114 lines (96 loc) · 2.67 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"strings"
"github.com/gliderlabs/ssh"
"github.com/ziutek/telnet"
flags "github.com/jessevdk/go-flags"
)
type options struct {
Addr string `short:"a" long:"addr" description:"Address to listen" default:"localhost:2222"`
HostKey string `short:"k" long:"key" description:"Path to the host key"`
AutoLogin bool `short:"l" long:"login" description:"Enable auto login"`
LoginPrompt string `long:"login-prompt" description:"Login prompt (default: \"login: \")" default:"login: " default-mask:"-"`
PasswordPrompt string `long:"password-prompt" description:"Password prompt (default: \"Password: \")" default:"Password: " default-mask:"-"`
}
func start(opts options) error {
server := &ssh.Server{Addr: opts.Addr}
if _, err := os.Stat(opts.HostKey); err == nil {
hostKeyFile := ssh.HostKeyFile(opts.HostKey)
server.SetOption(hostKeyFile)
}
if opts.AutoLogin {
passwordAuth := ssh.PasswordAuth(func(ctx ssh.Context, s string) bool {
ctx.SetValue("password", s)
return true
})
server.SetOption(passwordAuth)
}
server.Handle(func(s ssh.Session) {
var username, password, host string
if opts.AutoLogin {
t := strings.SplitN(s.User(), "@", 2)
if len(t) != 2 {
fmt.Fprintf(os.Stderr, "Unable to parse username from '%s'.\n", s.User())
s.Exit(1)
return
}
username, host = t[0], t[1]
password = s.Context().Value("password").(string)
} else {
host = s.User()
}
_, _, isPty := s.Pty()
if isPty {
addr := net.JoinHostPort(host, "23")
fmt.Printf("Connecting to %s\n", addr)
conn, err := telnet.Dial("tcp", addr)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to %s.\n", addr)
s.Exit(1)
return
}
defer func() {
conn.Close()
fmt.Printf("Connection to %s closed\n", addr)
}()
if opts.AutoLogin {
_, err = conn.ReadUntil(opts.LoginPrompt)
conn.Write([]byte(fmt.Sprintf("%s\n", username)))
_, err = conn.ReadUntil(opts.PasswordPrompt)
conn.Write([]byte(fmt.Sprintf("%s\n", password)))
}
sigChan := make(chan struct{}, 1)
go func() {
_, _ = io.Copy(s, conn)
sigChan <- struct{}{}
}()
go func() {
_, _ = io.Copy(conn, s)
sigChan <- struct{}{}
}()
<-sigChan
} else {
fmt.Fprintf(os.Stderr, "No PTY requested.\n")
s.Exit(1)
}
})
fmt.Printf("Starting ssh server on %s\n", opts.Addr)
return server.ListenAndServe()
}
func main() {
var opts options
if _, err := flags.Parse(&opts); err != nil {
if fe, ok := err.(*flags.Error); ok && fe.Type == flags.ErrHelp {
os.Exit(0)
}
log.Fatal(err)
}
if err := start(opts); err != nil {
log.Fatal(err)
}
}