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
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

105 lignes
2.3 KiB

  1. package main
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "io"
  6. "net"
  7. "os"
  8. "strconv"
  9. "strings"
  10. )
  11. type SclientOpts struct {
  12. RemoteAddress string
  13. RemotePort int
  14. LocalAddress string
  15. LocalPort int
  16. InsecureSkipVerify bool
  17. }
  18. type Sclient struct{}
  19. func pipe(r net.Conn, w net.Conn, t string) {
  20. buffer := make([]byte, 2048)
  21. for {
  22. done := false
  23. // NOTE: count may be > 0 even if there's an err
  24. count, err := r.Read(buffer)
  25. //fmt.Fprintf(os.Stdout, "[debug] (%s) reading\n", t)
  26. if nil != err {
  27. //fmt.Fprintf(os.Stdout, "[debug] (%s:%d) error reading %s\n", t, count, err)
  28. if io.EOF != err {
  29. fmt.Fprintf(os.Stderr, "[read error] (%s:%s) %s\n", t, count, err)
  30. }
  31. r.Close()
  32. //w.Close()
  33. done = true
  34. }
  35. if 0 == count {
  36. break
  37. }
  38. _, err = w.Write(buffer[:count])
  39. if nil != err {
  40. //fmt.Fprintf(os.Stdout, "[debug] %s error writing\n", t)
  41. if io.EOF != err {
  42. fmt.Fprintf(os.Stderr, "[write error] (%s) %s\n", t, err)
  43. }
  44. // TODO handle error closing?
  45. r.Close()
  46. //w.Close()
  47. done = true
  48. }
  49. if done {
  50. break
  51. }
  52. }
  53. }
  54. func handleConnection(remote string, conn net.Conn, opts *SclientOpts) {
  55. sclient, err := tls.Dial("tcp", remote,
  56. &tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify})
  57. if err != nil {
  58. fmt.Fprintf(os.Stderr, "[error] (remote) %s\n", err)
  59. conn.Close()
  60. return
  61. }
  62. fmt.Fprintf(os.Stdout, "[connect] %s => %s:%d\n",
  63. strings.Replace(conn.RemoteAddr().String(), "[::1]:", "localhost:", 1), opts.RemoteAddress, opts.RemotePort)
  64. go pipe(conn, sclient, "local")
  65. pipe(sclient, conn, "remote")
  66. }
  67. func (*Sclient) DialAndListen(opts *SclientOpts) error {
  68. remote := opts.RemoteAddress + ":" + strconv.Itoa(opts.RemotePort)
  69. conn, err := tls.Dial("tcp", remote,
  70. &tls.Config{InsecureSkipVerify: opts.InsecureSkipVerify})
  71. if err != nil {
  72. fmt.Fprintf(os.Stderr, "[warn] '%s' may not be accepting connections: %s\n", remote, err)
  73. } else {
  74. conn.Close()
  75. }
  76. local := opts.LocalAddress + ":" + strconv.Itoa(opts.LocalPort)
  77. ln, err := net.Listen("tcp", local)
  78. if err != nil {
  79. return err
  80. }
  81. fmt.Fprintf(os.Stdout, "[listening] %s:%d <= %s:%d\n",
  82. opts.RemoteAddress, opts.RemotePort, opts.LocalAddress, opts.LocalPort)
  83. for {
  84. conn, err := ln.Accept()
  85. if nil != err {
  86. fmt.Fprintf(os.Stderr, "[error] %s\n", err)
  87. continue
  88. }
  89. go handleConnection(remote, conn, opts)
  90. }
  91. }