diff --git a/golang/tcpproxy.go b/golang/tcpproxy.go new file mode 100644 index 0000000..8674145 --- /dev/null +++ b/golang/tcpproxy.go @@ -0,0 +1,60 @@ +// Example usage: +// Terminal 1: python -m http.server 8000 +// Terminal 2: go run tcpproxy.go 9000 localhost:8000 +// Terminal 3: curl localhost:9000 +package main + +import ( + "fmt" + "io" + "net" + "os" +) + +func main() { + if len(os.Args) != 3 { + fmt.Println("Usage: go run tcpproxy.go ") + os.Exit(1) + } + + listenPort := os.Args[1] // port to listen on + targetAddr := os.Args[2] // target server address + + // create TCP listener on specified port + listener, err := net.Listen("tcp", ":"+listenPort) + if err != nil { + fmt.Printf("Failed to listen on port %s: %v\n", listenPort, err) + os.Exit(1) + } + defer listener.Close() + + fmt.Printf("TCP proxy listening on port %s, forwarding to %s\n", listenPort, targetAddr) + + // accept incoming connections + for { + clientConn, err := listener.Accept() + if err != nil { + fmt.Printf("Failed to accept connection: %v\n", err) + continue + } + + // handle each client connection concurrently + go handleConnection(clientConn, targetAddr) + } +} + +func handleConnection(clientConn net.Conn, targetAddr string) { + defer clientConn.Close() // ensure client connection is closed + + // connect to target server + serverConn, err := net.Dial("tcp", targetAddr) + if err != nil { + fmt.Printf("Failed to connect to target %s: %v\n", targetAddr, err) + return + } + defer serverConn.Close() // ensure server connection is closed + + // start bidirectional data copying + go io.Copy(serverConn, clientConn) // client -> server + io.Copy(clientConn, serverConn) // server -> client (blocks until done) +}