tcpip.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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.
  4. package ssh
  5. import (
  6. "errors"
  7. "fmt"
  8. "io"
  9. "net"
  10. "sync"
  11. "time"
  12. )
  13. // Listen requests the remote peer open a listening socket
  14. // on addr. Incoming connections will be available by calling
  15. // Accept on the returned net.Listener.
  16. func (c *ClientConn) Listen(n, addr string) (net.Listener, error) {
  17. laddr, err := net.ResolveTCPAddr(n, addr)
  18. if err != nil {
  19. return nil, err
  20. }
  21. return c.ListenTCP(laddr)
  22. }
  23. // RFC 4254 7.1
  24. type channelForwardMsg struct {
  25. Message string
  26. WantReply bool
  27. raddr string
  28. rport uint32
  29. }
  30. // ListenTCP requests the remote peer open a listening socket
  31. // on laddr. Incoming connections will be available by calling
  32. // Accept on the returned net.Listener.
  33. func (c *ClientConn) ListenTCP(laddr *net.TCPAddr) (net.Listener, error) {
  34. m := channelForwardMsg{
  35. "tcpip-forward",
  36. true, // sendGlobalRequest waits for a reply
  37. laddr.IP.String(),
  38. uint32(laddr.Port),
  39. }
  40. // send message
  41. resp, err := c.sendGlobalRequest(m)
  42. if err != nil {
  43. return nil, err
  44. }
  45. // If the original port was 0, then the remote side will
  46. // supply a real port number in the response.
  47. if laddr.Port == 0 {
  48. port, _, ok := parseUint32(resp.Data)
  49. if !ok {
  50. return nil, errors.New("unable to parse response")
  51. }
  52. laddr.Port = int(port)
  53. }
  54. // Register this forward, using the port number we obtained.
  55. //
  56. // This does not work on OpenSSH < 6.0, which will send a
  57. // channelOpenMsg with port number 0, rather than the actual
  58. // port number.
  59. ch := c.forwardList.add(*laddr)
  60. return &tcpListener{laddr, c, ch}, nil
  61. }
  62. // forwardList stores a mapping between remote
  63. // forward requests and the tcpListeners.
  64. type forwardList struct {
  65. sync.Mutex
  66. entries []forwardEntry
  67. }
  68. // forwardEntry represents an established mapping of a laddr on a
  69. // remote ssh server to a channel connected to a tcpListener.
  70. type forwardEntry struct {
  71. laddr net.TCPAddr
  72. c chan forward
  73. }
  74. // forward represents an incoming forwarded tcpip connection. The
  75. // arguments to add/remove/lookup should be address as specified in
  76. // the original forward-request.
  77. type forward struct {
  78. c *clientChan // the ssh client channel underlying this forward
  79. raddr *net.TCPAddr // the raddr of the incoming connection
  80. }
  81. func (l *forwardList) add(addr net.TCPAddr) chan forward {
  82. l.Lock()
  83. defer l.Unlock()
  84. f := forwardEntry{
  85. addr,
  86. make(chan forward, 1),
  87. }
  88. l.entries = append(l.entries, f)
  89. return f.c
  90. }
  91. func (l *forwardList) remove(addr net.TCPAddr) {
  92. l.Lock()
  93. defer l.Unlock()
  94. for i, f := range l.entries {
  95. if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
  96. l.entries = append(l.entries[:i], l.entries[i+1:]...)
  97. return
  98. }
  99. }
  100. }
  101. func (l *forwardList) lookup(addr net.TCPAddr) (chan forward, bool) {
  102. l.Lock()
  103. defer l.Unlock()
  104. for _, f := range l.entries {
  105. if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
  106. return f.c, true
  107. }
  108. }
  109. return nil, false
  110. }
  111. type tcpListener struct {
  112. laddr *net.TCPAddr
  113. conn *ClientConn
  114. in <-chan forward
  115. }
  116. // Accept waits for and returns the next connection to the listener.
  117. func (l *tcpListener) Accept() (net.Conn, error) {
  118. s, ok := <-l.in
  119. if !ok {
  120. return nil, io.EOF
  121. }
  122. return &tcpChanConn{
  123. tcpChan: &tcpChan{
  124. clientChan: s.c,
  125. Reader: s.c.stdout,
  126. Writer: s.c.stdin,
  127. },
  128. laddr: l.laddr,
  129. raddr: s.raddr,
  130. }, nil
  131. }
  132. // Close closes the listener.
  133. func (l *tcpListener) Close() error {
  134. m := channelForwardMsg{
  135. "cancel-tcpip-forward",
  136. true,
  137. l.laddr.IP.String(),
  138. uint32(l.laddr.Port),
  139. }
  140. l.conn.forwardList.remove(*l.laddr)
  141. if _, err := l.conn.sendGlobalRequest(m); err != nil {
  142. return err
  143. }
  144. return nil
  145. }
  146. // Addr returns the listener's network address.
  147. func (l *tcpListener) Addr() net.Addr {
  148. return l.laddr
  149. }
  150. // Dial initiates a connection to the addr from the remote host.
  151. // addr is resolved using net.ResolveTCPAddr before connection.
  152. // This could allow an observer to observe the DNS name of the
  153. // remote host. Consider using ssh.DialTCP to avoid this.
  154. func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
  155. raddr, err := net.ResolveTCPAddr(n, addr)
  156. if err != nil {
  157. return nil, err
  158. }
  159. return c.DialTCP(n, nil, raddr)
  160. }
  161. // DialTCP connects to the remote address raddr on the network net,
  162. // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
  163. // as the local address for the connection.
  164. func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
  165. if laddr == nil {
  166. laddr = &net.TCPAddr{
  167. IP: net.IPv4zero,
  168. Port: 0,
  169. }
  170. }
  171. ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
  172. if err != nil {
  173. return nil, err
  174. }
  175. return &tcpChanConn{
  176. tcpChan: ch,
  177. laddr: laddr,
  178. raddr: raddr,
  179. }, nil
  180. }
  181. // RFC 4254 7.2
  182. type channelOpenDirectMsg struct {
  183. ChanType string
  184. PeersId uint32
  185. PeersWindow uint32
  186. MaxPacketSize uint32
  187. raddr string
  188. rport uint32
  189. laddr string
  190. lport uint32
  191. }
  192. // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
  193. // strings and are expected to be resolveable at the remote end.
  194. func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpChan, error) {
  195. ch := c.newChan(c.transport)
  196. if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
  197. ChanType: "direct-tcpip",
  198. PeersId: ch.localId,
  199. PeersWindow: 1 << 14,
  200. MaxPacketSize: 1 << 15, // RFC 4253 6.1
  201. raddr: raddr,
  202. rport: uint32(rport),
  203. laddr: laddr,
  204. lport: uint32(lport),
  205. })); err != nil {
  206. c.chanList.remove(ch.localId)
  207. return nil, err
  208. }
  209. if err := ch.waitForChannelOpenResponse(); err != nil {
  210. c.chanList.remove(ch.localId)
  211. return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
  212. }
  213. return &tcpChan{
  214. clientChan: ch,
  215. Reader: ch.stdout,
  216. Writer: ch.stdin,
  217. }, nil
  218. }
  219. type tcpChan struct {
  220. *clientChan // the backing channel
  221. io.Reader
  222. io.Writer
  223. }
  224. // tcpChanConn fulfills the net.Conn interface without
  225. // the tcpChan having to hold laddr or raddr directly.
  226. type tcpChanConn struct {
  227. *tcpChan
  228. laddr, raddr net.Addr
  229. }
  230. // LocalAddr returns the local network address.
  231. func (t *tcpChanConn) LocalAddr() net.Addr {
  232. return t.laddr
  233. }
  234. // RemoteAddr returns the remote network address.
  235. func (t *tcpChanConn) RemoteAddr() net.Addr {
  236. return t.raddr
  237. }
  238. // SetDeadline sets the read and write deadlines associated
  239. // with the connection.
  240. func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
  241. if err := t.SetReadDeadline(deadline); err != nil {
  242. return err
  243. }
  244. return t.SetWriteDeadline(deadline)
  245. }
  246. // SetReadDeadline sets the read deadline.
  247. // A zero value for t means Read will not time out.
  248. // After the deadline, the error from Read will implement net.Error
  249. // with Timeout() == true.
  250. func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
  251. return errors.New("ssh: tcpChan: deadline not supported")
  252. }
  253. // SetWriteDeadline exists to satisfy the net.Conn interface
  254. // but is not implemented by this type. It always returns an error.
  255. func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
  256. return errors.New("ssh: tcpChan: deadline not supported")
  257. }