-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathclient.go
145 lines (108 loc) · 3.1 KB
/
client.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
package easyssh
import (
"net"
"golang.org/x/crypto/ssh"
)
// Client wraps an SSH Client
type Client struct {
*ssh.Client
}
// Dial starts an ssh connection to the provided server
func Dial(network, addr string, config *ssh.ClientConfig) (*Client, error) {
c, err := ssh.Dial(network, addr, config)
return &Client{c}, err
}
// NewClient returns a new SSH Client.
func NewClient(c ssh.Conn, chans <-chan ssh.NewChannel, reqs <-chan *ssh.Request) *Client {
client := ssh.NewClient(c, chans, reqs)
return &Client{client}
}
// LocalForward performs a port forwarding over the ssh connection - ssh -L. Client will bind to the local address, and will tunnel those requests to host addr
func (c *Client) LocalForward(laddr, raddr *net.TCPAddr) error {
ln, err := net.ListenTCP("tcp", laddr) //tie to the client connection
if err != nil {
println(err.Error())
return err
}
logger.Println("Listening on address: ", ln.Addr().String())
quit := make(chan bool)
go func() { // Handle incoming connections on this new listener
for {
select {
case <-quit:
return
default:
conn, err := ln.Accept()
if err != nil { // Unable to accept new connection - listener likely closed
continue
}
go func(conn net.Conn) {
conn2, err := c.DialTCP("tcp", laddr, raddr)
if err != nil {
return
}
go func(conn, conn2 net.Conn) {
close := func() {
conn.Close()
conn2.Close()
}
go CopyReadWriters(conn, conn2, close)
}(conn, conn2)
}(conn)
}
}
}()
c.Wait()
ln.Close()
quit <- true
return nil
}
// RemoteForward forwards a remote port - ssh -R
func (c *Client) RemoteForward(remote, local string) error {
ln, err := c.Listen("tcp", remote)
if err != nil {
return err
}
quit := make(chan bool)
go func() { // Handle incoming connections on this new listener
for {
select {
case <-quit:
return
default:
conn, err := ln.Accept()
if err != nil { // Unable to accept new connection - listener likely closed
continue
}
conn2, err := net.Dial("tcp", local)
if err != nil {
continue
}
close := func() {
conn.Close()
conn2.Close()
}
go CopyReadWriters(conn, conn2, close)
}
}
}()
c.Wait()
ln.Close()
quit <- true
return nil
}
// 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 (c *Client) HandleOpenChannel(channelName string, handler ChannelMultipleRequestsHandler, data ...byte) error {
ch, reqs, err := c.OpenChannel(channelName, data)
if err != nil {
return err
}
handler.HandleMultipleRequests(reqs, c.Conn, 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 (c *Client) HandleOpenChannelFunc(channelName string, handler ChannelMultipleRequestsHandlerFunc, data ...byte) error {
return c.HandleOpenChannel(channelName, ChannelMultipleRequestsHandlerFunc(handler), data...)
}