package main import ( "log" "crypto/tls" "net" ) const localAddr string = ":25500" const remoteAddr string = "127.0.0.1:25501" const MaxConn int16 = 3 func main() { log.SetFlags(log.Lshortfile) cer, err := tls.LoadX509KeyPair("server.pem", "server.key") if err != nil { log.Println(err) return } config := &tls.Config{Certificates: []tls.Certificate{cer}} ln, err := tls.Listen("tcp", localAddr, config) if err != nil { log.Println(err) return } defer ln.Close() log.Printf("Listening: %v -> %v\n\n", localAddr, remoteAddr) for { conn, err := ln.Accept() if err != nil { log.Println(err) continue } go proxyConn(conn) } } func proxyConn(conn net.Conn) { defer conn.Close() rAddr, err := net.ResolveTCPAddr("tcp", remoteAddr) if err != nil { log.Print(err) } rConn, err := net.DialTCP("tcp", nil, rAddr) if err != nil { log.Print(err) } defer rConn.Close() Pipe(conn, rConn) log.Printf("handleConnection end: %s\n", conn.RemoteAddr()) } func chanFromConn(conn net.Conn) chan []byte { c := make(chan []byte) go func() { b := make([]byte, 1024) for { n, err := conn.Read(b) if n > 0 { res := make([]byte, n) // Copy the buffer so it doesn't get changed while read by the recipient. copy(res, b[:n]) c <- res } if err != nil { c <- nil break } } }() return c } func Pipe(conn1 net.Conn, conn2 net.Conn) { chan1 := chanFromConn(conn1) chan2 := chanFromConn(conn2) for { select { case b1 := <-chan1: if b1 == nil { return } else { conn2.Write(b1) } case b2 := <-chan2: if b2 == nil { return } else { conn1.Write(b2) } } } }