1. package main
    2. import (
    3. "flag"
    4. "github.com/rs/zerolog"
    5. "net"
    6. "os"
    7. )
    8. var logger = zerolog.New(os.Stdout).With().Timestamp().Logger()
    9. func main() {
    10. help := flag.Bool("help", false, "print usage")
    11. bind := flag.String("bind", "127.0.0.1:6000", "The address to bind to")
    12. backend := flag.String("backend", "", "The backend server address")
    13. flag.Parse()
    14. logger.Level(zerolog.DebugLevel)
    15. if *help {
    16. flag.Usage()
    17. return
    18. }
    19. if *backend == "" {
    20. flag.Usage()
    21. return
    22. }
    23. if *bind == "" {
    24. //use default bind
    25. logger.Info().Str("bind", *bind).Msg("use default bind")
    26. }
    27. success, err := RunProxy(*bind, *backend)
    28. if !success {
    29. logger.Error().Err(err).Send()
    30. os.Exit(1)
    31. }
    32. }
    33. func RunProxy(bind, backend string) (bool, error) {
    34. listener, err := net.Listen("tcp", bind)
    35. if err != nil {
    36. return false, err
    37. }
    38. defer listener.Close()
    39. logger.Info().Str("bind", bind).Str("backend", backend).Msg("tcp-proxy started.")
    40. for {
    41. conn, err := listener.Accept()
    42. if err != nil {
    43. logger.Error().Err(err).Send()
    44. } else {
    45. go ConnectionHandler(conn, backend)
    46. }
    47. }
    48. }
    49. func ConnectionHandler(conn net.Conn, backend string) {
    50. logger.Info().Str("conn", conn.RemoteAddr().String()).Msg("client connected.")
    51. target, err := net.Dial("tcp", backend)
    52. defer conn.Close()
    53. if err != nil {
    54. logger.Error().Err(err).Send()
    55. } else {
    56. defer target.Close()
    57. logger.Info().Str("conn", conn.RemoteAddr().String()).Str("backend", target.LocalAddr().String()).Msg("backend connected.")
    58. closed := make(chan bool, 2)
    59. go Proxy(conn, target, closed)
    60. go Proxy(target, conn, closed)
    61. <-closed
    62. logger.Info().Str("conn", conn.RemoteAddr().String()).Msg("Connection closed.")
    63. }
    64. }
    65. func Proxy(from net.Conn, to net.Conn, closed chan bool) {
    66. buffer := make([]byte, 4096)
    67. for {
    68. n1, err := from.Read(buffer)
    69. if err != nil {
    70. closed <- true
    71. return
    72. }
    73. n2, err := to.Write(buffer[:n1])
    74. logger.Debug().Str("from", from.RemoteAddr().String()).Int("recv", n1).Str("to", to.RemoteAddr().String()).Int("send", n2).Send()
    75. if err != nil {
    76. closed <- true
    77. return
    78. }
    79. }
    80. }

    使用方法 ./proxy —bind 0.0.0.0:6379 —backend 10.0.1.15:6379