tcpip.go 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. // Register this forward, using the port number we requested.
  46. // If we requested port 0 (auto allocated port), we have to
  47. // register under 0, since the channelOpenMsg will list 0
  48. // rather than the allocated port number.
  49. ch := c.forwardList.add(*laddr)
  50. // If the original port was 0, then the remote side will
  51. // supply a real port number in the response.
  52. origPort := uint32(laddr.Port)
  53. if laddr.Port == 0 {
  54. port, _, ok := parseUint32(resp.Data)
  55. if !ok {
  56. return nil, errors.New("unable to parse response")
  57. }
  58. laddr.Port = int(port)
  59. }
  60. return &tcpListener{laddr, origPort, 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. // The port with which we made the request, which can be 0.
  114. origPort uint32
  115. conn *ClientConn
  116. in <-chan forward
  117. }
  118. // Accept waits for and returns the next connection to the listener.
  119. func (l *tcpListener) Accept() (net.Conn, error) {
  120. s, ok := <-l.in
  121. if !ok {
  122. return nil, io.EOF
  123. }
  124. return &tcpChanConn{
  125. tcpChan: &tcpChan{
  126. clientChan: s.c,
  127. Reader: s.c.stdout,
  128. Writer: s.c.stdin,
  129. },
  130. laddr: l.laddr,
  131. raddr: s.raddr,
  132. }, nil
  133. }
  134. // Close closes the listener.
  135. func (l *tcpListener) Close() error {
  136. m := channelForwardMsg{
  137. "cancel-tcpip-forward",
  138. true,
  139. l.laddr.IP.String(),
  140. l.origPort,
  141. }
  142. origAddr := net.TCPAddr{
  143. IP: l.laddr.IP,
  144. Port: int(l.origPort),
  145. }
  146. l.conn.forwardList.remove(origAddr)
  147. if _, err := l.conn.sendGlobalRequest(m); err != nil {
  148. return err
  149. }
  150. return nil
  151. }
  152. // Addr returns the listener's network address.
  153. func (l *tcpListener) Addr() net.Addr {
  154. return l.laddr
  155. }
  156. // Dial initiates a connection to the addr from the remote host.
  157. // addr is resolved using net.ResolveTCPAddr before connection.
  158. // This could allow an observer to observe the DNS name of the
  159. // remote host. Consider using ssh.DialTCP to avoid this.
  160. func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
  161. raddr, err := net.ResolveTCPAddr(n, addr)
  162. if err != nil {
  163. return nil, err
  164. }
  165. return c.DialTCP(n, nil, raddr)
  166. }
  167. // DialTCP connects to the remote address raddr on the network net,
  168. // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
  169. // as the local address for the connection.
  170. func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
  171. if laddr == nil {
  172. laddr = &net.TCPAddr{
  173. IP: net.IPv4zero,
  174. Port: 0,
  175. }
  176. }
  177. ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
  178. if err != nil {
  179. return nil, err
  180. }
  181. return &tcpChanConn{
  182. tcpChan: ch,
  183. laddr: laddr,
  184. raddr: raddr,
  185. }, nil
  186. }
  187. // RFC 4254 7.2
  188. type channelOpenDirectMsg struct {
  189. ChanType string
  190. PeersId uint32
  191. PeersWindow uint32
  192. MaxPacketSize uint32
  193. raddr string
  194. rport uint32
  195. laddr string
  196. lport uint32
  197. }
  198. // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
  199. // strings and are expected to be resolveable at the remote end.
  200. func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpChan, error) {
  201. ch := c.newChan(c.transport)
  202. if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
  203. ChanType: "direct-tcpip",
  204. PeersId: ch.localId,
  205. PeersWindow: 1 << 14,
  206. MaxPacketSize: 1 << 15, // RFC 4253 6.1
  207. raddr: raddr,
  208. rport: uint32(rport),
  209. laddr: laddr,
  210. lport: uint32(lport),
  211. })); err != nil {
  212. c.chanList.remove(ch.localId)
  213. return nil, err
  214. }
  215. if err := ch.waitForChannelOpenResponse(); err != nil {
  216. c.chanList.remove(ch.localId)
  217. return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
  218. }
  219. return &tcpChan{
  220. clientChan: ch,
  221. Reader: ch.stdout,
  222. Writer: ch.stdin,
  223. }, nil
  224. }
  225. type tcpChan struct {
  226. *clientChan // the backing channel
  227. io.Reader
  228. io.Writer
  229. }
  230. // tcpChanConn fulfills the net.Conn interface without
  231. // the tcpChan having to hold laddr or raddr directly.
  232. type tcpChanConn struct {
  233. *tcpChan
  234. laddr, raddr net.Addr
  235. }
  236. // LocalAddr returns the local network address.
  237. func (t *tcpChanConn) LocalAddr() net.Addr {
  238. return t.laddr
  239. }
  240. // RemoteAddr returns the remote network address.
  241. func (t *tcpChanConn) RemoteAddr() net.Addr {
  242. return t.raddr
  243. }
  244. // SetDeadline sets the read and write deadlines associated
  245. // with the connection.
  246. func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
  247. if err := t.SetReadDeadline(deadline); err != nil {
  248. return err
  249. }
  250. return t.SetWriteDeadline(deadline)
  251. }
  252. // SetReadDeadline sets the read deadline.
  253. // A zero value for t means Read will not time out.
  254. // After the deadline, the error from Read will implement net.Error
  255. // with Timeout() == true.
  256. func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
  257. return errors.New("ssh: tcpChan: deadline not supported")
  258. }
  259. // SetWriteDeadline exists to satisfy the net.Conn interface
  260. // but is not implemented by this type. It always returns an error.
  261. func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
  262. return errors.New("ssh: tcpChan: deadline not supported")
  263. }