-
Notifications
You must be signed in to change notification settings - Fork 4
/
server.go
156 lines (128 loc) · 4.49 KB
/
server.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package easyssh
import (
"net"
"golang.org/x/crypto/ssh"
)
// Server represents an SSH Server. The SSH ServerConfig must be provided
type Server struct {
Addr string
Config *ssh.ServerConfig
Handler ConnHandler
*ssh.ServerConn
}
// ListenAndServe listens on the TCP address s.Addr and then calls Serve to handle requests on incoming connections. If s.Addr is blank, ":ssh" is used
func (s *Server) ListenAndServe() error {
addr := s.Addr
if addr == "" {
addr = ":ssh"
}
ln, err := net.Listen("tcp", addr)
if err != nil {
return err
}
return s.Serve(ln.(*net.TCPListener))
}
// Serve accepts incoming connections on the provided listener.and reads global SSH Channel and Out-of-band requests and calls s,ConnHandler to handle them
func (s *Server) Serve(l net.Listener) error {
defer l.Close()
logger.Print("SSH Server started listening on: ", l.Addr())
for {
tcpConn, err := l.Accept()
if err != nil {
return err
}
c, err := s.newConn(tcpConn)
if err != nil {
continue
}
go c.serve()
}
}
// HandleOpenChannel requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler
func (s *Server) HandleOpenChannel(channelName string, handler ChannelMultipleRequestsHandler, data ...byte) error {
ch, reqs, err := s.OpenChannel(channelName, data)
if err != nil {
return err
}
handler.HandleMultipleRequests(reqs, s.ServerConn, channelName, ch)
return nil
}
// HandleOpenChannelFunc requests that the remote end accept a channel request and if accepted,
// passes the newly opened channel and requests to the provided handler function
func (s *Server) HandleOpenChannelFunc(channelName string, handler func(reqs <-chan *ssh.Request, sshConn ssh.Conn, channelType string, channel ssh.Channel), data ...byte) error {
return s.HandleOpenChannel(channelName, ChannelMultipleRequestsHandlerFunc(handler), data...)
}
type conn struct {
server *Server
remoteAddr string
conn net.Conn
}
func (c *conn) serve() {
sshConn, chans, reqs, err := ssh.NewServerConn(c.conn, c.server.Config)
if err != nil {
return
}
c.server.ServerConn = sshConn
logger.Print("New ssh connection from: ", c.conn.RemoteAddr())
go func() {
sshConn.Wait()
logger.Print("Closing ssh connection from: ", c.conn.RemoteAddr())
if c.conn != nil {
c.conn.Close()
//c.conn = nil
}
}()
// Use default ConnHandler if one isn't provided
serverHandler{c.server}.HandleSSHConn(sshConn, chans, reqs)
}
func (s *Server) newConn(netConn net.Conn) (*conn, error) {
c := new(conn)
c.remoteAddr = netConn.RemoteAddr().String()
c.server = s
c.conn = netConn
return c, nil
}
// NewSessionServerHandler creates a ConnHandler to provide a more standard SSH server providing sessions
func NewSessionServerHandler() *SSHConnHandler {
s := SSHConnHandler{}
channelHandler := NewChannelsMux()
channelHandler.HandleChannel(SessionRequest, SessionHandler())
s.MultipleChannelsHandler = channelHandler
return &s
}
// NewStandardSSHServerHandler returns a server handler that can deal with ssh sessions and both local and remote port forwarding
func NewStandardSSHServerHandler() *SSHConnHandler {
s := NewSSHConnHandler()
chHandler := NewChannelsMux()
chHandler.HandleChannel(SessionRequest, SessionHandler())
chHandler.HandleChannel(DirectForwardRequest, DirectPortForwardHandler())
s.MultipleChannelsHandler = chHandler
globalHandler := NewGlobalMultipleRequestsMux()
globalHandler.HandleRequest(RemoteForwardRequest, TCPIPForwardRequestHandler())
s.GlobalMultipleRequestsHandler = globalHandler
return s
}
// ListenAndServe listens on the given tcp address addr and then calls Serve with handler.
// If handler is nil, the DefaultServerHandler is used.
func ListenAndServe(addr string, conf *ssh.ServerConfig, handler ConnHandler) error {
s := &Server{addr, conf, handler, nil}
return s.ListenAndServe()
}
// Serve accepts incoming SSH connections on the listener l.
// If handler is nil, the DefaultServerHandler is used.
func Serve(l net.Listener, conf *ssh.ServerConfig, handler ConnHandler) error {
s := &Server{Config: conf, Handler: handler}
return s.Serve(l)
}
type serverHandler struct {
s *Server
}
// ServeSSH is a wrapper, tests if the server has a ServerHandler, and if not uses the default one
func (s serverHandler) HandleSSHConn(conn *ssh.ServerConn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) {
handler := s.s.Handler
if handler == nil {
handler = DefaultSSHConnHandler
}
handler.HandleSSHConn(conn, chans, reqs)
}