tcpip.go 6.9 KB

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