Secure Client for exposing TLS (aka SSL) secured services as plain-text connections locally, and for multiplexing a single port with multiple protocols using SNI
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package sclient
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "io"
  6. "net"
  7. "os"
  8. "strconv"
  9. "strings"
  10. )
  11. // I wonder if I can get this to exactly mirror UnixAddr without passing it in
  12. type stdaddr struct {
  13. net.UnixAddr
  14. }
  15. type stdnet struct {
  16. in *os.File // os.Stdin
  17. out *os.File // os.Stdout
  18. addr *stdaddr
  19. }
  20. func (rw *stdnet) Read(buf []byte) (n int, err error) {
  21. return rw.in.Read(buf)
  22. }
  23. func (rw *stdnet) Write(buf []byte) (n int, err error) {
  24. return rw.out.Write(buf)
  25. }
  26. func (rw *stdnet) Close() error {
  27. return rw.in.Close()
  28. }
  29. func (rw *stdnet) RemoteAddr() net.Addr {
  30. return rw.addr
  31. }
  32. // not all of net.Conn, just RWC and RemoteAddr()
  33. type netReadWriteCloser interface {
  34. io.ReadWriteCloser
  35. RemoteAddr() net.Addr
  36. }
  37. type Tunnel struct {
  38. RemoteAddress string
  39. RemotePort int
  40. LocalAddress string
  41. LocalPort int
  42. InsecureSkipVerify bool
  43. ServerName string
  44. }
  45. func pipe(r netReadWriteCloser, w netReadWriteCloser, t string) {
  46. buffer := make([]byte, 2048)
  47. for {
  48. done := false
  49. // NOTE: count may be > 0 even if there's an err
  50. //fmt.Fprintf(os.Stdout, "[debug] (%s) reading\n", t)
  51. count, err := r.Read(buffer)
  52. if nil != err {
  53. //fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err)
  54. if io.EOF != err {
  55. fmt.Fprintf(os.Stderr, "[read error] (%s:%s) %s\n", t, count, err)
  56. }
  57. r.Close()
  58. //w.Close()
  59. done = true
  60. }
  61. if 0 == count {
  62. break
  63. }
  64. _, err = w.Write(buffer[:count])
  65. if nil != err {
  66. //fmt.Fprintf(os.Stdout, "[debug] %s error writing\n", t)
  67. if io.EOF != err {
  68. fmt.Fprintf(os.Stderr, "[write error] (%s) %s\n", t, err)
  69. }
  70. // TODO handle error closing?
  71. r.Close()
  72. //w.Close()
  73. done = true
  74. }
  75. if done {
  76. break
  77. }
  78. }
  79. }
  80. func (t *Tunnel) handleConnection(remote string, conn netReadWriteCloser) {
  81. sclient, err := tls.Dial("tcp", remote,
  82. &tls.Config{
  83. ServerName: t.ServerName,
  84. InsecureSkipVerify: t.InsecureSkipVerify,
  85. })
  86. if err != nil {
  87. fmt.Fprintf(os.Stderr, "[error] (remote) %s\n", err)
  88. conn.Close()
  89. return
  90. }
  91. if "stdio" == conn.RemoteAddr().Network() {
  92. fmt.Fprintf(os.Stdout, "(connected to %s:%d and reading from %s)\n",
  93. t.RemoteAddress, t.RemotePort, conn.RemoteAddr().String())
  94. } else {
  95. fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n",
  96. strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), t.RemoteAddress, t.RemotePort)
  97. }
  98. go pipe(conn, sclient, "local")
  99. pipe(sclient, conn, "remote")
  100. }
  101. func (t *Tunnel) DialAndListen() error {
  102. remote := t.RemoteAddress + ":" + strconv.Itoa(t.RemotePort)
  103. conn, err := tls.Dial("tcp", remote,
  104. &tls.Config{
  105. ServerName: t.ServerName,
  106. InsecureSkipVerify: t.InsecureSkipVerify,
  107. })
  108. if err != nil {
  109. fmt.Fprintf(os.Stderr, "[warn] '%s' may not be accepting connections: %s\n", remote, err)
  110. } else {
  111. conn.Close()
  112. }
  113. // use stdin/stdout
  114. if "-" == t.LocalAddress || "|" == t.LocalAddress {
  115. var name string
  116. network := "stdio"
  117. if "|" == t.LocalAddress {
  118. name = "pipe"
  119. } else {
  120. name = "stdin"
  121. }
  122. conn := &stdnet{os.Stdin, os.Stdout, &stdaddr{net.UnixAddr{name, network}}}
  123. t.handleConnection(remote, conn)
  124. return nil
  125. }
  126. // use net.Conn
  127. local := t.LocalAddress + ":" + strconv.Itoa(t.LocalPort)
  128. ln, err := net.Listen("tcp", local)
  129. if err != nil {
  130. return err
  131. }
  132. fmt.Fprintf(os.Stdout, "[listening] %s:%d <= %s:%d\n",
  133. t.RemoteAddress, t.RemotePort, t.LocalAddress, t.LocalPort)
  134. for {
  135. conn, err := ln.Accept()
  136. if nil != err {
  137. fmt.Fprintf(os.Stderr, "[error] %s\n", err)
  138. continue
  139. }
  140. go t.handleConnection(remote, conn)
  141. }
  142. }