1
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
19
// Listen requests the remote peer open a listening socket on
20
// addr. Incoming connections will be available by calling Accept on
21
// the returned net.Listener. The listener must be serviced, or the
22
// SSH connection may hang.
23
func (c *Client) Listen(n, addr string) (net.Listener, error) {
24
laddr, err := net.ResolveTCPAddr(n, addr)
28
return c.ListenTCP(laddr)
31
// Automatic port allocation is broken with OpenSSH before 6.0. See
32
// also https://bugzilla.mindrot.org/show_bug.cgi?id=2017. In
33
// particular, OpenSSH 5.9 sends a channelOpenMsg with port number 0,
34
// rather than the actual port number. This means you can never open
35
// two different listeners with auto allocated ports. We work around
36
// this by trying explicit ports until we succeed.
38
const openSSHPrefix = "OpenSSH_"
40
var portRandomizer = rand.New(rand.NewSource(time.Now().UnixNano()))
42
// isBrokenOpenSSHVersion returns true if the given version string
43
// specifies a version of OpenSSH that is known to have a bug in port
45
func isBrokenOpenSSHVersion(versionStr string) bool {
46
i := strings.Index(versionStr, openSSHPrefix)
50
i += len(openSSHPrefix)
52
for ; j < len(versionStr); j++ {
53
if versionStr[j] < '0' || versionStr[j] > '9' {
57
version, _ := strconv.Atoi(versionStr[i:j])
61
// autoPortListenWorkaround simulates automatic port allocation by
62
// trying random ports repeatedly.
63
func (c *Client) autoPortListenWorkaround(laddr *net.TCPAddr) (net.Listener, error) {
64
var sshListener net.Listener
67
for i := 0; i < tries; i++ {
69
addr.Port = 1024 + portRandomizer.Intn(60000)
70
sshListener, err = c.ListenTCP(&addr)
72
laddr.Port = addr.Port
73
return sshListener, err
76
return nil, fmt.Errorf("ssh: listen on random port failed after %d tries: %v", tries, err)
80
type channelForwardMsg struct {
85
// ListenTCP requests the remote peer open a listening socket
86
// on laddr. Incoming connections will be available by calling
87
// Accept on the returned net.Listener.
88
func (c *Client) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
89
if laddr.Port == 0 && isBrokenOpenSSHVersion(string(c.ServerVersion())) {
90
return c.autoPortListenWorkaround(laddr)
93
m := channelForwardMsg{
98
ok, resp, err := c.SendRequest("tcpip-forward", true, Marshal(&m))
103
return nil, errors.New("ssh: tcpip-forward request denied by peer")
106
// If the original port was 0, then the remote side will
107
// supply a real port number in the response.
112
if err := Unmarshal(resp, &p); err != nil {
115
laddr.Port = int(p.Port)
118
// Register this forward, using the port number we obtained.
119
ch := c.forwards.add(*laddr)
121
return &tcpListener{laddr, c, ch}, nil
124
// forwardList stores a mapping between remote
125
// forward requests and the tcpListeners.
126
type forwardList struct {
128
entries []forwardEntry
131
// forwardEntry represents an established mapping of a laddr on a
132
// remote ssh server to a channel connected to a tcpListener.
133
type forwardEntry struct {
138
// forward represents an incoming forwarded tcpip connection. The
139
// arguments to add/remove/lookup should be address as specified in
140
// the original forward-request.
141
type forward struct {
142
newCh NewChannel // the ssh client channel underlying this forward
143
raddr *net.TCPAddr // the raddr of the incoming connection
146
func (l *forwardList) add(addr net.TCPAddr) chan forward {
151
make(chan forward, 1),
153
l.entries = append(l.entries, f)
157
// See RFC 4254, section 7.2
158
type forwardedTCPPayload struct {
165
// parseTCPAddr parses the originating address from the remote into a *net.TCPAddr.
166
func parseTCPAddr(addr string, port uint32) (*net.TCPAddr, error) {
167
if port == 0 || port > 65535 {
168
return nil, fmt.Errorf("ssh: port number out of range: %d", port)
170
ip := net.ParseIP(string(addr))
172
return nil, fmt.Errorf("ssh: cannot parse IP address %q", addr)
174
return &net.TCPAddr{IP: ip, Port: int(port)}, nil
177
func (l *forwardList) handleChannels(in <-chan NewChannel) {
179
var payload forwardedTCPPayload
180
if err := Unmarshal(ch.ExtraData(), &payload); err != nil {
181
ch.Reject(ConnectionFailed, "could not parse forwarded-tcpip payload: "+err.Error())
185
// RFC 4254 section 7.2 specifies that incoming
186
// addresses should list the address, in string
187
// format. It is implied that this should be an IP
188
// address, as it would be impossible to connect to it
190
laddr, err := parseTCPAddr(payload.Addr, payload.Port)
192
ch.Reject(ConnectionFailed, err.Error())
195
raddr, err := parseTCPAddr(payload.OriginAddr, payload.OriginPort)
197
ch.Reject(ConnectionFailed, err.Error())
201
if ok := l.forward(*laddr, *raddr, ch); !ok {
202
// Section 7.2, implementations MUST reject spurious incoming
204
ch.Reject(Prohibited, "no forward for address")
210
// remove removes the forward entry, and the channel feeding its
212
func (l *forwardList) remove(addr net.TCPAddr) {
215
for i, f := range l.entries {
216
if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
217
l.entries = append(l.entries[:i], l.entries[i+1:]...)
224
// closeAll closes and clears all forwards.
225
func (l *forwardList) closeAll() {
228
for _, f := range l.entries {
234
func (l *forwardList) forward(laddr, raddr net.TCPAddr, ch NewChannel) bool {
237
for _, f := range l.entries {
238
if laddr.IP.Equal(f.laddr.IP) && laddr.Port == f.laddr.Port {
239
f.c <- forward{ch, &raddr}
246
type tcpListener struct {
253
// Accept waits for and returns the next connection to the listener.
254
func (l *tcpListener) Accept() (net.Conn, error) {
259
ch, incoming, err := s.newCh.Accept()
263
go DiscardRequests(incoming)
272
// Close closes the listener.
273
func (l *tcpListener) Close() error {
274
m := channelForwardMsg{
276
uint32(l.laddr.Port),
279
// this also closes the listener.
280
l.conn.forwards.remove(*l.laddr)
281
ok, _, err := l.conn.SendRequest("cancel-tcpip-forward", true, Marshal(&m))
282
if err == nil && !ok {
283
err = errors.New("ssh: cancel-tcpip-forward failed")
288
// Addr returns the listener's network address.
289
func (l *tcpListener) Addr() net.Addr {
293
// Dial initiates a connection to the addr from the remote host.
294
// The resulting connection has a zero LocalAddr() and RemoteAddr().
295
func (c *Client) Dial(n, addr string) (net.Conn, error) {
296
// Parse the address into host and numeric port.
297
host, portString, err := net.SplitHostPort(addr)
301
port, err := strconv.ParseUint(portString, 10, 16)
305
// Use a zero address for local and remote address.
306
zeroAddr := &net.TCPAddr{
310
ch, err := c.dial(net.IPv4zero.String(), 0, host, int(port))
321
// DialTCP connects to the remote address raddr on the network net,
322
// which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
323
// as the local address for the connection.
324
func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
326
laddr = &net.TCPAddr{
331
ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
343
type channelOpenDirectMsg struct {
350
func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel, error) {
351
msg := channelOpenDirectMsg{
353
rport: uint32(rport),
355
lport: uint32(lport),
357
ch, in, err := c.OpenChannel("direct-tcpip", Marshal(&msg))
361
go DiscardRequests(in)
365
type tcpChan struct {
366
Channel // the backing channel
369
// tcpChanConn fulfills the net.Conn interface without
370
// the tcpChan having to hold laddr or raddr directly.
371
type tcpChanConn struct {
373
laddr, raddr net.Addr
376
// LocalAddr returns the local network address.
377
func (t *tcpChanConn) LocalAddr() net.Addr {
381
// RemoteAddr returns the remote network address.
382
func (t *tcpChanConn) RemoteAddr() net.Addr {
386
// SetDeadline sets the read and write deadlines associated
387
// with the connection.
388
func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
389
if err := t.SetReadDeadline(deadline); err != nil {
392
return t.SetWriteDeadline(deadline)
395
// SetReadDeadline sets the read deadline.
396
// A zero value for t means Read will not time out.
397
// After the deadline, the error from Read will implement net.Error
398
// with Timeout() == true.
399
func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
400
return errors.New("ssh: tcpChan: deadline not supported")
403
// SetWriteDeadline exists to satisfy the net.Conn interface
404
// but is not implemented by this type. It always returns an error.
405
func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
406
return errors.New("ssh: tcpChan: deadline not supported")