tcpip.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. // remove removes the forward entry, and the channel feeding its
  92. // listener.
  93. func (l *forwardList) remove(addr net.TCPAddr) {
  94. l.Lock()
  95. defer l.Unlock()
  96. for i, f := range l.entries {
  97. if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
  98. l.entries = append(l.entries[:i], l.entries[i+1:]...)
  99. close(f.c)
  100. return
  101. }
  102. }
  103. }
  104. // closeAll closes and clears all forwards.
  105. func (l *forwardList) closeAll() {
  106. l.Lock()
  107. defer l.Unlock()
  108. for _, f := range l.entries {
  109. close(f.c)
  110. }
  111. l.entries = nil
  112. }
  113. func (l *forwardList) lookup(addr net.TCPAddr) (chan forward, bool) {
  114. l.Lock()
  115. defer l.Unlock()
  116. for _, f := range l.entries {
  117. if addr.IP.Equal(f.laddr.IP) && addr.Port == f.laddr.Port {
  118. return f.c, true
  119. }
  120. }
  121. return nil, false
  122. }
  123. type tcpListener struct {
  124. laddr *net.TCPAddr
  125. conn *ClientConn
  126. in <-chan forward
  127. }
  128. // Accept waits for and returns the next connection to the listener.
  129. func (l *tcpListener) Accept() (net.Conn, error) {
  130. s, ok := <-l.in
  131. if !ok {
  132. return nil, io.EOF
  133. }
  134. return &tcpChanConn{
  135. tcpChan: &tcpChan{
  136. clientChan: s.c,
  137. Reader: s.c.stdout,
  138. Writer: s.c.stdin,
  139. },
  140. laddr: l.laddr,
  141. raddr: s.raddr,
  142. }, nil
  143. }
  144. // Close closes the listener.
  145. func (l *tcpListener) Close() error {
  146. m := channelForwardMsg{
  147. "cancel-tcpip-forward",
  148. true,
  149. l.laddr.IP.String(),
  150. uint32(l.laddr.Port),
  151. }
  152. l.conn.forwardList.remove(*l.laddr)
  153. if _, err := l.conn.sendGlobalRequest(m); err != nil {
  154. return err
  155. }
  156. return nil
  157. }
  158. // Addr returns the listener's network address.
  159. func (l *tcpListener) Addr() net.Addr {
  160. return l.laddr
  161. }
  162. // Dial initiates a connection to the addr from the remote host.
  163. // addr is resolved using net.ResolveTCPAddr before connection.
  164. // This could allow an observer to observe the DNS name of the
  165. // remote host. Consider using ssh.DialTCP to avoid this.
  166. func (c *ClientConn) Dial(n, addr string) (net.Conn, error) {
  167. raddr, err := net.ResolveTCPAddr(n, addr)
  168. if err != nil {
  169. return nil, err
  170. }
  171. return c.DialTCP(n, nil, raddr)
  172. }
  173. // DialTCP connects to the remote address raddr on the network net,
  174. // which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used
  175. // as the local address for the connection.
  176. func (c *ClientConn) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error) {
  177. if laddr == nil {
  178. laddr = &net.TCPAddr{
  179. IP: net.IPv4zero,
  180. Port: 0,
  181. }
  182. }
  183. ch, err := c.dial(laddr.IP.String(), laddr.Port, raddr.IP.String(), raddr.Port)
  184. if err != nil {
  185. return nil, err
  186. }
  187. return &tcpChanConn{
  188. tcpChan: ch,
  189. laddr: laddr,
  190. raddr: raddr,
  191. }, nil
  192. }
  193. // RFC 4254 7.2
  194. type channelOpenDirectMsg struct {
  195. ChanType string
  196. PeersId uint32
  197. PeersWindow uint32
  198. MaxPacketSize uint32
  199. raddr string
  200. rport uint32
  201. laddr string
  202. lport uint32
  203. }
  204. // dial opens a direct-tcpip connection to the remote server. laddr and raddr are passed as
  205. // strings and are expected to be resolveable at the remote end.
  206. func (c *ClientConn) dial(laddr string, lport int, raddr string, rport int) (*tcpChan, error) {
  207. ch := c.newChan(c.transport)
  208. if err := c.writePacket(marshal(msgChannelOpen, channelOpenDirectMsg{
  209. ChanType: "direct-tcpip",
  210. PeersId: ch.localId,
  211. PeersWindow: 1 << 14,
  212. MaxPacketSize: 1 << 15, // RFC 4253 6.1
  213. raddr: raddr,
  214. rport: uint32(rport),
  215. laddr: laddr,
  216. lport: uint32(lport),
  217. })); err != nil {
  218. c.chanList.remove(ch.localId)
  219. return nil, err
  220. }
  221. if err := ch.waitForChannelOpenResponse(); err != nil {
  222. c.chanList.remove(ch.localId)
  223. return nil, fmt.Errorf("ssh: unable to open direct tcpip connection: %v", err)
  224. }
  225. return &tcpChan{
  226. clientChan: ch,
  227. Reader: ch.stdout,
  228. Writer: ch.stdin,
  229. }, nil
  230. }
  231. type tcpChan struct {
  232. *clientChan // the backing channel
  233. io.Reader
  234. io.Writer
  235. }
  236. // tcpChanConn fulfills the net.Conn interface without
  237. // the tcpChan having to hold laddr or raddr directly.
  238. type tcpChanConn struct {
  239. *tcpChan
  240. laddr, raddr net.Addr
  241. }
  242. // LocalAddr returns the local network address.
  243. func (t *tcpChanConn) LocalAddr() net.Addr {
  244. return t.laddr
  245. }
  246. // RemoteAddr returns the remote network address.
  247. func (t *tcpChanConn) RemoteAddr() net.Addr {
  248. return t.raddr
  249. }
  250. // SetDeadline sets the read and write deadlines associated
  251. // with the connection.
  252. func (t *tcpChanConn) SetDeadline(deadline time.Time) error {
  253. if err := t.SetReadDeadline(deadline); err != nil {
  254. return err
  255. }
  256. return t.SetWriteDeadline(deadline)
  257. }
  258. // SetReadDeadline sets the read deadline.
  259. // A zero value for t means Read will not time out.
  260. // After the deadline, the error from Read will implement net.Error
  261. // with Timeout() == true.
  262. func (t *tcpChanConn) SetReadDeadline(deadline time.Time) error {
  263. return errors.New("ssh: tcpChan: deadline not supported")
  264. }
  265. // SetWriteDeadline exists to satisfy the net.Conn interface
  266. // but is not implemented by this type. It always returns an error.
  267. func (t *tcpChanConn) SetWriteDeadline(deadline time.Time) error {
  268. return errors.New("ssh: tcpChan: deadline not supported")
  269. }