tcpip.go 6.9 KB

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