Files
simple-go-tcp-proxy/tcp2tls_client.go

144 lines
2.5 KiB
Go

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)
}
}
}