diff --git a/utils/3rdparty/go_tcp_proxy/go_tcp_proxy.go b/utils/3rdparty/go_tcp_proxy/go_tcp_proxy.go new file mode 100644 index 00000000..8bc98d01 --- /dev/null +++ b/utils/3rdparty/go_tcp_proxy/go_tcp_proxy.go @@ -0,0 +1,72 @@ +package go_tcp_proxy + +import ( + "fmt" + "net" + "os" + + proxy "github.com/jpillora/go-tcp-proxy" +) + +func RunProxy(localAddr string, remoteAddr string) { + logger := proxy.ColorLogger{ + Verbose: *verbose, + Color: *colors, + } + + logger.Info("go-tcp-proxy (%s) proxing from %v to %v ", version, localAddr, remoteAddr) + + laddr, err := net.ResolveTCPAddr("tcp", localAddr) + if err != nil { + logger.Warn("Failed to resolve local address: %s", err) + os.Exit(1) + } + raddr, err := net.ResolveTCPAddr("tcp", remoteAddr) + if err != nil { + logger.Warn("Failed to resolve remote address: %s", err) + os.Exit(1) + } + listener, err := net.ListenTCP("tcp", laddr) + if err != nil { + logger.Warn("Failed to open local port to listen: %s", err) + os.Exit(1) + } + + matcher := createMatcher(*match) + replacer := createReplacer(*replace) + + if *veryverbose { + *verbose = true + } + + for { + conn, err := listener.AcceptTCP() + if err != nil { + logger.Warn("Failed to accept connection '%s'", err) + continue + } + connid++ + + var p *proxy.Proxy + if *unwrapTLS { + logger.Info("Unwrapping TLS") + p = proxy.NewTLSUnwrapped(conn, laddr, raddr, remoteAddr) + } else { + p = proxy.New(conn, laddr, raddr) + } + + p.Matcher = matcher + p.Replacer = replacer + + p.Nagles = *nagles + p.OutputHex = *hex + p.Log = proxy.ColorLogger{ + Verbose: *verbose, + VeryVerbose: *veryverbose, + Prefix: fmt.Sprintf("Connection #%03d ", connid), + Color: *colors, + } + + go p.Start() + } +} diff --git a/utils/3rdparty/go_tcp_proxy/main.go b/utils/3rdparty/go_tcp_proxy/main.go new file mode 100644 index 00000000..f59bb094 --- /dev/null +++ b/utils/3rdparty/go_tcp_proxy/main.go @@ -0,0 +1,72 @@ +package go_tcp_proxy + +// From: https://github.com/jpillora/go-tcp-proxy/blob/master/cmd/tcp-proxy/main.go + +import ( + "flag" + "regexp" + "strings" + + proxy "github.com/jpillora/go-tcp-proxy" +) + +var ( + version = "0.0.0-src" + matchid = uint64(0) + connid = uint64(0) + logger proxy.ColorLogger + + verbose = flag.Bool("v", false, "display server actions") + veryverbose = flag.Bool("vv", false, "display server actions and all tcp data") + nagles = flag.Bool("n", false, "disable nagles algorithm") + hex = flag.Bool("h", false, "output hex") + colors = flag.Bool("c", false, "output ansi colors") + unwrapTLS = flag.Bool("unwrap-tls", false, "remote connection with TLS exposed unencrypted locally") + match = flag.String("match", "", "match regex (in the form 'regex')") + replace = flag.String("replace", "", "replace regex (in the form 'regex~replacer')") +) + +func createMatcher(match string) func([]byte) { + if match == "" { + return nil + } + re, err := regexp.Compile(match) + if err != nil { + logger.Warn("Invalid match regex: %s", err) + return nil + } + + logger.Info("Matching %s", re.String()) + return func(input []byte) { + ms := re.FindAll(input, -1) + for _, m := range ms { + matchid++ + logger.Info("Match #%d: %s", matchid, string(m)) + } + } +} + +func createReplacer(replace string) func([]byte) []byte { + if replace == "" { + return nil + } + //split by / (TODO: allow slash escapes) + parts := strings.Split(replace, "~") + if len(parts) != 2 { + logger.Warn("Invalid replace option") + return nil + } + + re, err := regexp.Compile(string(parts[0])) + if err != nil { + logger.Warn("Invalid replace regex: %s", err) + return nil + } + + repl := []byte(parts[1]) + + logger.Info("Replacing %s with %s", re.String(), repl) + return func(input []byte) []byte { + return re.ReplaceAll(input, repl) + } +}