From 6070aa9e80f178cbed2f0f836b5d1929569536f7 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Mon, 27 Nov 2023 21:49:48 +0800 Subject: [PATCH] feat: add tcp2tls_client.go, tls2tcp_server.go --- README.md | 11 ++++ tcp2tls_client.go | 143 ++++++++++++++++++++++++++++++++++++++++++++++ tls2tcp_server.go | 105 ++++++++++++++++++++++++++++++++++ 3 files changed, 259 insertions(+) create mode 100644 tcp2tls_client.go create mode 100644 tls2tcp_server.go diff --git a/README.md b/README.md index 44be2e7..b4247ab 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,14 @@ Config sample: } ``` + + +---- + +Codes: +* tcp2tls_client.go +* tls2tcp_server.go + +Copied from: https://gist.github.com/cs8425/a742349a55596f1b251a + + diff --git a/tcp2tls_client.go b/tcp2tls_client.go new file mode 100644 index 0000000..4ff8248 --- /dev/null +++ b/tcp2tls_client.go @@ -0,0 +1,143 @@ +package main + +import ( + "log" + "crypto/tls" + "net" +) + +const localAddr string = "127.0.0.1:9999" +const remoteAddr string = "127.0.0.1:25500" +const MaxConn int16 = 3 + +func proxyConn(conn net.Conn) { + defer conn.Close() + + rAddr, err := net.ResolveTCPAddr("tcp", remoteAddr) + if err != nil { + log.Print(err) + } + + conf := &tls.Config{ + InsecureSkipVerify: true, + } + + //rConn, err := net.DialTCP("tcp", nil, rAddr) + rConn, err := tls.Dial("tcp", rAddr.String(), conf) + if err != nil { + log.Print(err) + return + } + defer rConn.Close() + +// log.Printf("remoteAddr connected: %v\n", rAddr.String()) + + Pipe(conn, rConn) +// log.Printf("proxyConn end: %v -> %v\n", conn.RemoteAddr(), rConn.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) + } + } + } +} + +func main() { + log.SetFlags(log.Lshortfile) + + log.Printf("Listening: %v -> %v\n\n", localAddr, remoteAddr) + + addr, err := net.ResolveTCPAddr("tcp", localAddr) + if err != nil { + panic(err) + } + + listener, err := net.ListenTCP("tcp", addr) + if err != nil { + panic(err) + } + + var i int16 = 0; + count := make(chan int16, 1) + for { + log.Printf("wait accepted...\n") + conn, err := listener.AcceptTCP() + if err != nil { + log.Print(err) + } + //go proxyConn(conn); + + //log.Printf("accepted: %v\n", conn.RemoteAddr()) + select { + case t := <- count: + i += t +// print("received ", i, "\n") + + default: + + } + if i < MaxConn { + i++ + log.Printf("[%v/%v]accepted: %v\n", i, MaxConn, conn.RemoteAddr()) + + // Create a new goroutine which will call the connection handler and then free up the space. + go func(connection net.Conn) { + proxyConn(connection) +// log.Printf("[%v/%v]Closed connection from %s\r\n", i, MaxConn, connection.RemoteAddr()) + log.Printf("Closed connection from %s\r\n", connection.RemoteAddr()) + select { + case t := <- count: + count <- t-1 + + default: + count <- -1 + } + }(conn) + }else{ + conn.Close() +// log.Printf("closed: %v\n", i) + } + } + +} + diff --git a/tls2tcp_server.go b/tls2tcp_server.go new file mode 100644 index 0000000..4897b5a --- /dev/null +++ b/tls2tcp_server.go @@ -0,0 +1,105 @@ +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) + } + } + } +}