commit bba0bb6613c703b8aa840bd67e58b8618f7a3db0 Author: Ambrose Chua Date: Thu Mar 1 20:24:15 2018 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..50a6d96 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.DS_Store +forward diff --git a/README.md b/README.md new file mode 100644 index 0000000..d5efbe8 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ + +# forward + +A simple TCP proxy. + +## Usage + +``` +$ ./forward -help +Usage of ./forward: + -connect string + forward to ip and port (default ":8080") + -listen string + listen on ip and port (default ":8081") +``` + diff --git a/main.go b/main.go new file mode 100644 index 0000000..3d8e2cc --- /dev/null +++ b/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "flag" + "io" + "log" + "net" +) + +var listen string +var connect string + +func main() { + flag.StringVar(&listen, "listen", ":8000", "listen on ip and port") + flag.StringVar(&connect, "connect", "", "forward to ip and port") + flag.Parse() + + // check and parse address + conn, err := net.ResolveTCPAddr("tcp", connect) + if err != nil { + flag.PrintDefaults() + log.Fatal(err) + } + + // listen on address + ln, err := net.Listen("tcp", listen) + if err != nil { + flag.PrintDefaults() + log.Fatal(err) + } + + log.Printf("listening on %v", ln.Addr()) + log.Printf("will connect to %v", conn) + + for i := 0; ; i++ { + // accept new connection + c, err := ln.Accept() + if err != nil { + log.Fatal(err) + } + + log.Printf("connection %v from %v", i, c.RemoteAddr()) + + cn, err := net.DialTCP("tcp", nil, conn) + if err != nil { + c.Close() + log.Print(err) + continue + } + + go pipe(c, cn, i) + go pipe(cn, c, i) + } +} + +func pipe(w io.WriteCloser, r io.ReadCloser, count int) { + n, err := io.Copy(w, r) + + r.Close() + w.Close() + + log.Printf("connection %v closed, %v bytes", count, n) + + opError, ok := err.(*net.OpError) + if err != nil && (!ok || opError.Op != "readfrom") { + log.Printf("warning! %v", err) + } +}