Guest User

Untitled

a guest
Aug 8th, 2018
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.54 KB | None | 0 0
  1. package tunnel
  2.  
  3. import (
  4. "golang.org/x/crypto/ssh"
  5.  
  6. "errors"
  7. "io"
  8. "io/ioutil"
  9. "log"
  10. "net"
  11. "net/url"
  12. "os"
  13. )
  14.  
  15. const defaultSshPort = "22"
  16.  
  17. type Tunnel struct {
  18. localAddr string
  19. remoteAddr string
  20. serverAddr string
  21. sshUser string
  22. sshPass string
  23. authByKey bool
  24.  
  25. conn *ssh.Client
  26. remote net.Conn
  27. local net.Listener
  28. }
  29.  
  30. func New(port, toPort, serverDsn string) (*Tunnel, error) {
  31. dsn, err := url.Parse(serverDsn)
  32. if err != nil {
  33. return nil, err
  34. }
  35.  
  36. sshPort := dsn.Port()
  37. if sshPort == "" {
  38. sshPort = defaultSshPort
  39. }
  40. addr := net.JoinHostPort(dsn.Hostname(), sshPort)
  41.  
  42. pass, hasPass := dsn.User.Password()
  43. byKey := !hasPass
  44. if s := dsn.Query().Get("by_key"); s != "" {
  45. byKey = true
  46. }
  47.  
  48. t := &Tunnel{
  49. remoteAddr: "127.0.0.1:" + port,
  50. localAddr: "127.0.0.1:" + toPort,
  51. serverAddr: addr,
  52. sshUser: dsn.User.Username(),
  53. sshPass: pass,
  54. authByKey: byKey,
  55. }
  56.  
  57. err = t.open()
  58. return t, err
  59. }
  60.  
  61. func (t *Tunnel) Close() error {
  62. var errStr string
  63. for _, c := range []io.Closer{t.conn, t.remote, t.local} {
  64. if c == nil {
  65. continue
  66. }
  67. err := c.Close()
  68. if err != nil {
  69. errStr += err.Error()
  70. }
  71. }
  72. if errStr != "" {
  73. return errors.New(errStr)
  74. }
  75. return nil
  76. }
  77.  
  78. func (t *Tunnel) open() error {
  79. var err error
  80. t.conn, err = ssh.Dial("tcp", t.serverAddr, &ssh.ClientConfig{
  81. User: t.sshUser,
  82. Auth: []ssh.AuthMethod{
  83. t.authBy(),
  84. },
  85. HostKeyCallback: ssh.InsecureIgnoreHostKey(),
  86. })
  87. if err != nil {
  88. return err
  89. }
  90.  
  91. // local connection
  92. t.remote, err = t.conn.Dial("tcp", t.remoteAddr)
  93. if err != nil {
  94. t.Close()
  95. return err
  96. }
  97.  
  98. t.local, err = net.Listen("tcp", t.localAddr)
  99. if err != nil {
  100. t.Close()
  101. return err
  102. }
  103. go t.transfer()
  104. return nil
  105. }
  106.  
  107. func (t *Tunnel) authBy() ssh.AuthMethod {
  108. if !t.authByKey {
  109. return ssh.Password(t.sshPass)
  110. }
  111.  
  112. return ssh.PublicKeysCallback(func() (signers []ssh.Signer, err error) {
  113. buffer, err := ioutil.ReadFile(os.Getenv("HOME") + "/.ssh/id_rsa")
  114. if err != nil {
  115. return nil, err
  116. }
  117. var key ssh.Signer
  118. if t.sshPass != "" {
  119. key, err = ssh.ParsePrivateKeyWithPassphrase(buffer, []byte(t.sshPass))
  120. } else {
  121. key, err = ssh.ParsePrivateKey(buffer)
  122. }
  123. return []ssh.Signer{key}, err
  124. })
  125. }
  126.  
  127. func (t *Tunnel) transfer() {
  128. for {
  129. l, err := t.local.Accept()
  130. if err != nil {
  131. log.Fatalf("listen Accept failed %s", err)
  132. }
  133.  
  134. go func() {
  135. _, err := io.Copy(l, t.remote)
  136. if err != nil {
  137. log.Fatalf("io.Copy failed: %v", err)
  138. }
  139. }()
  140.  
  141. go func() {
  142. _, err := io.Copy(t.remote, l)
  143. if err != nil {
  144. log.Fatalf("io.Copy failed: %v", err)
  145. }
  146. }()
  147. }
  148. }
Add Comment
Please, Sign In to add comment