|
@@ -1,6 +1,7 @@
|
|
|
package tcpprox
|
|
|
|
|
|
import (
|
|
|
+ "errors"
|
|
|
"io"
|
|
|
"log"
|
|
|
"net"
|
|
@@ -13,12 +14,6 @@ func isValidIP(ip string) bool {
|
|
|
return parsedIP != nil
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-Connection Copy
|
|
|
-
|
|
|
-Copy between two connections, and accumlate the copied bytes in the
|
|
|
-accumulator number
|
|
|
-*/
|
|
|
func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *int64) {
|
|
|
io.Copy(conn1, conn2)
|
|
|
conn1.Close()
|
|
@@ -28,103 +23,183 @@ func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *i
|
|
|
wg.Done()
|
|
|
}
|
|
|
|
|
|
-func forward(conn1 net.Conn, conn2 net.Conn) {
|
|
|
+func forward(conn1 net.Conn, conn2 net.Conn, accumulator *int64) {
|
|
|
log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
|
|
|
var wg sync.WaitGroup
|
|
|
// wait tow goroutines
|
|
|
wg.Add(2)
|
|
|
- go connCopy(conn1, conn2, &wg)
|
|
|
- go connCopy(conn2, conn1, &wg)
|
|
|
+ go connCopy(conn1, conn2, &wg, accumulator)
|
|
|
+ go connCopy(conn2, conn1, &wg, accumulator)
|
|
|
//blocking when the wg is locked
|
|
|
wg.Wait()
|
|
|
}
|
|
|
|
|
|
-func accept(listener net.Listener) net.Conn {
|
|
|
+func accept(listener net.Listener) (net.Conn, error) {
|
|
|
conn, err := listener.Accept()
|
|
|
if err != nil {
|
|
|
- log.Println("[x]", "accept connect ["+conn.RemoteAddr().String()+"] faild.", err.Error())
|
|
|
- return nil
|
|
|
+ return nil, err
|
|
|
}
|
|
|
log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]")
|
|
|
- return conn
|
|
|
+ return conn, err
|
|
|
}
|
|
|
|
|
|
-func start_server(address string) net.Listener {
|
|
|
+func startListener(address string) (net.Listener, error) {
|
|
|
log.Println("[+]", "try to start server on:["+address+"]")
|
|
|
server, err := net.Listen("tcp", address)
|
|
|
if err != nil {
|
|
|
- log.Fatalln("[x]", "listen address ["+address+"] faild.")
|
|
|
+ return nil, errors.New("listen address [" + address + "] faild")
|
|
|
}
|
|
|
log.Println("[√]", "start listen at address:["+address+"]")
|
|
|
- return server
|
|
|
+ return server, nil
|
|
|
}
|
|
|
|
|
|
-func port2port(port1 string, port2 string) {
|
|
|
- listen1 := start_server("0.0.0.0:" + port1)
|
|
|
- listen2 := start_server("0.0.0.0:" + port2)
|
|
|
+/*
|
|
|
+portA -> server
|
|
|
+portB -> server
|
|
|
+*/
|
|
|
+func (c *ProxyRelayConfig) Port2port(port1 string, port2 string, stopChan chan bool) error {
|
|
|
+ listen1, err := startListener("0.0.0.0:" + port1)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ listen2, err := startListener("0.0.0.0:" + port2)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
log.Println("[√]", "listen port:", port1, "and", port2, "success. waiting for client...")
|
|
|
+ c.Running = true
|
|
|
+
|
|
|
+ go func() {
|
|
|
+ <-stopChan
|
|
|
+ log.Println("[x]", "Received stop signal. Exiting Port to Port forwarder")
|
|
|
+ c.Running = false
|
|
|
+ listen1.Close()
|
|
|
+ listen2.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
for {
|
|
|
- conn1 := accept(listen1)
|
|
|
- conn2 := accept(listen2)
|
|
|
+ conn1, err := accept(listen1)
|
|
|
+ if err != nil {
|
|
|
+ if !c.Running {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ conn2, err := accept(listen2)
|
|
|
+ if err != nil {
|
|
|
+ if !c.Running {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
if conn1 == nil || conn2 == nil {
|
|
|
- log.Println("[x]", "accept client faild. retry in ", timeout, " seconds. ")
|
|
|
- time.Sleep(timeout * time.Second)
|
|
|
+ log.Println("[x]", "accept client faild. retry in ", c.Timeout, " seconds. ")
|
|
|
+ time.Sleep(time.Duration(c.Timeout) * time.Second)
|
|
|
continue
|
|
|
}
|
|
|
- forward(conn1, conn2)
|
|
|
+ forward(conn1, conn2, &c.accumulatedByteTransfered)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func port2host(allowPort string, targetAddress string) {
|
|
|
- server := start_server("0.0.0.0:" + allowPort)
|
|
|
+/*
|
|
|
+portA -> server
|
|
|
+server -> portB
|
|
|
+*/
|
|
|
+func (c *ProxyRelayConfig) Port2host(allowPort string, targetAddress string, stopChan chan bool) error {
|
|
|
+ server, err := startListener("0.0.0.0:" + allowPort)
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ //Start stop handler
|
|
|
+ go func() {
|
|
|
+ <-stopChan
|
|
|
+ log.Println("[x]", "Received stop signal. Exiting Port to Host forwarder")
|
|
|
+ c.Running = false
|
|
|
+ server.Close()
|
|
|
+ }()
|
|
|
+
|
|
|
+ //Start blocking loop for accepting connections
|
|
|
for {
|
|
|
- conn := accept(server)
|
|
|
- if conn == nil {
|
|
|
+ conn, err := accept(server)
|
|
|
+ if conn == nil || err != nil {
|
|
|
+ if !c.Running {
|
|
|
+ //Terminate by stop chan. Exit listener loop
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ //Connection error. Retry
|
|
|
continue
|
|
|
}
|
|
|
- //println(targetAddress)
|
|
|
+
|
|
|
go func(targetAddress string) {
|
|
|
log.Println("[+]", "start connect host:["+targetAddress+"]")
|
|
|
target, err := net.Dial("tcp", targetAddress)
|
|
|
if err != nil {
|
|
|
// temporarily unavailable, don't use fatal.
|
|
|
- log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", timeout, "seconds. ")
|
|
|
+ log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", c.Timeout, "seconds. ")
|
|
|
conn.Close()
|
|
|
log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]")
|
|
|
- time.Sleep(timeout * time.Second)
|
|
|
+ time.Sleep(time.Duration(c.Timeout) * time.Second)
|
|
|
return
|
|
|
}
|
|
|
log.Println("[→]", "connect target address ["+targetAddress+"] success.")
|
|
|
- forward(target, conn)
|
|
|
+ forward(target, conn, &c.accumulatedByteTransfered)
|
|
|
}(targetAddress)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func host2host(address1, address2 string) {
|
|
|
- for {
|
|
|
+/*
|
|
|
+server -> portA
|
|
|
+server -> portB
|
|
|
+*/
|
|
|
+func (c *ProxyRelayConfig) Host2host(address1, address2 string, stopChan chan bool) error {
|
|
|
+ c.Running = true
|
|
|
+ go func() {
|
|
|
+ <-stopChan
|
|
|
+ log.Println("[x]", "Received stop signal. Exiting Host to Host forwarder")
|
|
|
+ c.Running = false
|
|
|
+ }()
|
|
|
+
|
|
|
+ for c.Running {
|
|
|
log.Println("[+]", "try to connect host:["+address1+"] and ["+address2+"]")
|
|
|
var host1, host2 net.Conn
|
|
|
var err error
|
|
|
for {
|
|
|
- host1, err = net.Dial("tcp", address1)
|
|
|
+ d := net.Dialer{Timeout: time.Duration(c.Timeout)}
|
|
|
+ host1, err = d.Dial("tcp", address1)
|
|
|
if err == nil {
|
|
|
log.Println("[→]", "connect ["+address1+"] success.")
|
|
|
break
|
|
|
} else {
|
|
|
- log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", timeout, " seconds. ")
|
|
|
- time.Sleep(timeout * time.Second)
|
|
|
+ log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", c.Timeout, " seconds. ")
|
|
|
+ time.Sleep(time.Duration(c.Timeout) * time.Second)
|
|
|
+ }
|
|
|
+
|
|
|
+ if !c.Running {
|
|
|
+ return nil
|
|
|
}
|
|
|
}
|
|
|
for {
|
|
|
- host2, err = net.Dial("tcp", address2)
|
|
|
+ d := net.Dialer{Timeout: time.Duration(c.Timeout)}
|
|
|
+ host2, err = d.Dial("tcp", address2)
|
|
|
if err == nil {
|
|
|
log.Println("[→]", "connect ["+address2+"] success.")
|
|
|
break
|
|
|
} else {
|
|
|
- log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", timeout, " seconds. ")
|
|
|
- time.Sleep(timeout * time.Second)
|
|
|
+ log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", c.Timeout, " seconds. ")
|
|
|
+ time.Sleep(time.Duration(c.Timeout) * time.Second)
|
|
|
+ }
|
|
|
+
|
|
|
+ if !c.Running {
|
|
|
+ return nil
|
|
|
}
|
|
|
}
|
|
|
- forward(host1, host2)
|
|
|
+ forward(host1, host2, &c.accumulatedByteTransfered)
|
|
|
}
|
|
|
+
|
|
|
+ return nil
|
|
|
}
|