TCP Proxy
package mainimport ("io""log""net""sync"
)
type TCPProxy struct {listenAddr stringtargetAddr string
}
func NewTCPProxy(listenAddr, targetAddr string) *TCPProxy {return &TCPProxy{listenAddr: listenAddr,targetAddr: targetAddr,}
}
func (p *TCPProxy) Serve() error {listener, err := net.Listen("tcp", p.listenAddr)if err != nil {return err}defer listener.Close()log.Printf("tcp proxy listening at: %s\n", listener.Addr())for {conn, err := listener.Accept()if err != nil {log.Printf("listener accept error: %s\n", err)continue}go p.handleConnection(conn)}
}
func (p *TCPProxy) handleConnection(conn net.Conn) {defer conn.Close() log.Printf("accepted new connection %s\n", conn.RemoteAddr())targetConn, err := net.Dial("tcp", p.targetAddr)if err != nil {log.Printf("dial target addr: %s error: %s\n", p.targetAddr, err)return}defer targetConn.Close() log.Printf("tcp proxy client addr: %s\n", targetConn.LocalAddr())wg := sync.WaitGroup{}wg.Add(2)go func() {defer wg.Done()n, err := io.Copy(conn, targetConn)if err != nil {log.Printf("copy bytes from %s to %s error: %s", conn.RemoteAddr(), targetConn.RemoteAddr(), err)return}log.Printf("copied %d bytes from %s to %s", n, conn.RemoteAddr(), targetConn.RemoteAddr())}()go func() {defer wg.Done()n, err := io.Copy(targetConn, conn)if err != nil {log.Printf("copy bytes from %s to %s error: %s", targetConn.RemoteAddr(), conn.RemoteAddr(), err)return}log.Printf("copied %d bytes from %s to %s", n, targetConn.RemoteAddr(), conn.RemoteAddr())}()wg.Wait()
}func main() {proxy := NewTCPProxy("127.0.0.1:8080", "127.0.0.1:8081")if err := proxy.Serve(); err != nil {log.Fatal(err)}
}
Server
package mainimport ("bufio""log""net"
)
func handle(conn net.Conn) {defer conn.Close() reader := bufio.NewReader(conn)for {var buf [512]byten, err := reader.Read(buf[:]) if err != nil {log.Printf("read from client err: %s\n", err)break}log.Printf("read %d bytes from client\n", n)recvStr := string(buf[:n])log.Printf("received data from client: %s\n", recvStr)n, err = conn.Write([]byte(recvStr)) if err != nil {log.Printf("write data to client err: %s\n", err)return}log.Printf("write %d bytes to client\n", n)}
}func main() {listener, err := net.Listen("tcp", "127.0.0.1:8081")if err != nil {log.Fatal(err)}log.Printf("server listening at: %s\n", listener.Addr())for {conn, err := listener.Accept() if err != nil {log.Printf("listener accept error: %s\n", err)continue}go handle(conn) }
}
Client
package mainimport ("bufio""log""net""os""strings"
)
func main() {conn, err := net.Dial("tcp", "127.0.0.1:8080")if err != nil {log.Fatal(err)}log.Printf("client addr: %s\n", conn.LocalAddr())defer conn.Close() inputReader := bufio.NewReader(os.Stdin)for {input, _ := inputReader.ReadString('\n') inputInfo := strings.Trim(input, "\r\n")if strings.ToUpper(inputInfo) == "Q" { return}n, err := conn.Write([]byte(inputInfo)) if err != nil {log.Printf("write data to server err: %s\n", err)return}log.Printf("write %d bytes to server\n", n)buf := [512]byte{}n, err = conn.Read(buf[:])if err != nil {log.Printf("read data from server err: %s\n", err)return}log.Printf("read %d bytes from server\n", n)log.Printf("received data from server: %s\n", string(buf[:n]))}
}