From 6b3b89f7bfdc54a7bd47b3041321a26c4bf41c06 Mon Sep 17 00:00:00 2001 From: jemmy1794 Date: Thu, 3 Jul 2025 08:54:11 +0800 Subject: [PATCH] Add EnableLogging to Stream Proxy for log control - Add `EnableLogging` to control TCP/UDP Connection logs to reduce log latency. - Add `Enable Logging` Option in Stream Proxy rule. - Update Stream Proxy UI. --- src/mod/streamproxy/handler.go | 4 +++ src/mod/streamproxy/instances.go | 13 +++++++++ src/mod/streamproxy/streamproxy.go | 5 ++++ src/mod/streamproxy/tcpprox.go | 46 ++++++++++++++++-------------- src/mod/streamproxy/udpprox.go | 4 +-- src/web/components/streamprox.html | 22 ++++++++++++++ 6 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/mod/streamproxy/handler.go b/src/mod/streamproxy/handler.go index 50a7cb4..147100e 100644 --- a/src/mod/streamproxy/handler.go +++ b/src/mod/streamproxy/handler.go @@ -48,6 +48,7 @@ func (m *Manager) HandleAddProxyConfig(w http.ResponseWriter, r *http.Request) { useTCP, _ := utils.PostBool(r, "useTCP") useUDP, _ := utils.PostBool(r, "useUDP") useProxyProtocol, _ := utils.PostBool(r, "useProxyProtocol") + enableLogging, _ := utils.PostBool(r, "enableLogging") //Create the target config newConfigUUID := m.NewConfig(&ProxyRelayOptions{ @@ -58,6 +59,7 @@ func (m *Manager) HandleAddProxyConfig(w http.ResponseWriter, r *http.Request) { UseTCP: useTCP, UseUDP: useUDP, UseProxyProtocol: useProxyProtocol, + EnableLogging: enableLogging, }) js, _ := json.Marshal(newConfigUUID) @@ -78,6 +80,7 @@ func (m *Manager) HandleEditProxyConfigs(w http.ResponseWriter, r *http.Request) useTCP, _ := utils.PostBool(r, "useTCP") useUDP, _ := utils.PostBool(r, "useUDP") useProxyProtocol, _ := utils.PostBool(r, "useProxyProtocol") + enableLogging, _ := utils.PostBool(r, "enableLogging") newTimeoutStr, _ := utils.PostPara(r, "timeout") newTimeout := -1 @@ -98,6 +101,7 @@ func (m *Manager) HandleEditProxyConfigs(w http.ResponseWriter, r *http.Request) UseTCP: useTCP, UseUDP: useUDP, UseProxyProtocol: useProxyProtocol, + EnableLogging: enableLogging, NewTimeout: newTimeout, } diff --git a/src/mod/streamproxy/instances.go b/src/mod/streamproxy/instances.go index 2447143..e7c8e49 100644 --- a/src/mod/streamproxy/instances.go +++ b/src/mod/streamproxy/instances.go @@ -9,9 +9,22 @@ package streamproxy import ( "errors" + "log" "time" ) +func (c *ProxyRelayInstance) LogMsg(message string, originalError error) { + if !c.EnableLogging { + return + } + + if originalError != nil { + log.Println(message, "error:", originalError) + } else { + log.Println(message) + } +} + // Start a proxy if stopped func (c *ProxyRelayInstance) Start() error { if c.IsRunning() { diff --git a/src/mod/streamproxy/streamproxy.go b/src/mod/streamproxy/streamproxy.go index 6804459..c473e33 100644 --- a/src/mod/streamproxy/streamproxy.go +++ b/src/mod/streamproxy/streamproxy.go @@ -30,6 +30,7 @@ type ProxyRelayOptions struct { UseTCP bool UseUDP bool UseProxyProtocol bool + EnableLogging bool } // ProxyRuleUpdateConfig is used to update the proxy rule config @@ -41,6 +42,7 @@ type ProxyRuleUpdateConfig struct { UseTCP bool //Enable TCP proxy, default to false UseUDP bool //Enable UDP proxy, default to false UseProxyProtocol bool //Enable Proxy Protocol, default to false + EnableLogging bool //Enable Logging TCP/UDP Message, default to true NewTimeout int //New timeout for the connection, leave -1 for no change } @@ -55,6 +57,7 @@ type ProxyRelayInstance struct { UseTCP bool //Enable TCP proxy UseUDP bool //Enable UDP proxy UseProxyProtocol bool //Enable Proxy Protocol + EnableLogging bool //Enable logging for ProxyInstance Timeout int //Timeout for connection in sec /* Internal */ @@ -176,6 +179,7 @@ func (m *Manager) NewConfig(config *ProxyRelayOptions) string { UseTCP: config.UseTCP, UseUDP: config.UseUDP, UseProxyProtocol: config.UseProxyProtocol, + EnableLogging: config.EnableLogging, Timeout: config.Timeout, tcpStopChan: nil, udpStopChan: nil, @@ -221,6 +225,7 @@ func (m *Manager) EditConfig(newConfig *ProxyRuleUpdateConfig) error { foundConfig.UseTCP = newConfig.UseTCP foundConfig.UseUDP = newConfig.UseUDP foundConfig.UseProxyProtocol = newConfig.UseProxyProtocol + foundConfig.EnableLogging = newConfig.EnableLogging if newConfig.NewTimeout != -1 { if newConfig.NewTimeout < 0 { diff --git a/src/mod/streamproxy/tcpprox.go b/src/mod/streamproxy/tcpprox.go index 64cf468..d16ad8d 100644 --- a/src/mod/streamproxy/tcpprox.go +++ b/src/mod/streamproxy/tcpprox.go @@ -31,16 +31,16 @@ func isValidPort(port string) bool { return true } -func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *atomic.Int64) { +func (c *ProxyRelayInstance) connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup, accumulator *atomic.Int64) { n, err := io.Copy(conn1, conn2) if err != nil { return } accumulator.Add(n) //Add to accumulator conn1.Close() - log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]") + c.LogMsg("[←] close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]", nil) //conn2.Close() - //log.Println("[←]", "close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]") + //c.LogMsg("[←] close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]", nil) wg.Done() } @@ -61,14 +61,16 @@ func writeProxyProtocolHeaderV1(dst net.Conn, src net.Conn) error { return err } -func forward(conn1 net.Conn, conn2 net.Conn, aTob *atomic.Int64, bToa *atomic.Int64) { - log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String()) +func (c *ProxyRelayInstance) forward(conn1 net.Conn, conn2 net.Conn, aTob *atomic.Int64, bToa *atomic.Int64) { + msg := fmt.Sprintf("[+] start transmit. [%s],[%s] <-> [%s],[%s]", + conn1.LocalAddr().String(), conn1.RemoteAddr().String(), + conn2.LocalAddr().String(), conn2.RemoteAddr().String()) + c.LogMsg(msg, nil) + var wg sync.WaitGroup - // wait tow goroutines wg.Add(2) - go connCopy(conn1, conn2, &wg, aTob) - go connCopy(conn2, conn1, &wg, bToa) - //blocking when the wg is locked + go c.connCopy(conn1, conn2, &wg, aTob) + go c.connCopy(conn2, conn1, &wg, bToa) wg.Wait() } @@ -78,18 +80,18 @@ func (c *ProxyRelayInstance) accept(listener net.Listener) (net.Conn, error) { return nil, err } - //Check if connection in blacklist or whitelist + // Check if connection in blacklist or whitelist if addr, ok := conn.RemoteAddr().(*net.TCPAddr); ok { if !c.parent.Options.AccessControlHandler(conn) { time.Sleep(300 * time.Millisecond) conn.Close() - log.Println("[x]", "Connection from "+addr.IP.String()+" rejected by access control policy") + c.LogMsg("[x] Connection from "+addr.IP.String()+" rejected by access control policy", nil) return nil, errors.New("Connection from " + addr.IP.String() + " rejected by access control policy") } } - log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]") - return conn, err + c.LogMsg("[√] accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]", nil) + return conn, nil } func startListener(address string) (net.Listener, error) { @@ -130,7 +132,7 @@ func (c *ProxyRelayInstance) Port2host(allowPort string, targetAddress string, s //Start stop handler go func() { <-stopChan - log.Println("[x]", "Received stop signal. Exiting Port to Host forwarder") + c.LogMsg("[x] Received stop signal. Exiting Port to Host forwarder", nil) server.Close() }() @@ -147,32 +149,32 @@ func (c *ProxyRelayInstance) Port2host(allowPort string, targetAddress string, s } go func(targetAddress string) { - log.Println("[+]", "start connect host:["+targetAddress+"]") + c.LogMsg("[+] start connect host:["+targetAddress+"]", nil) 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 ", c.Timeout, "seconds. ") + c.LogMsg("[x] connect target address ["+targetAddress+"] failed. retry in "+strconv.Itoa(c.Timeout)+" seconds.", nil) conn.Close() - log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]") + c.LogMsg("[←] close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]", nil) time.Sleep(time.Duration(c.Timeout) * time.Second) return } - log.Println("[→]", "connect target address ["+targetAddress+"] success.") + c.LogMsg("[→] connect target address ["+targetAddress+"] success.", nil) if c.UseProxyProtocol { - log.Println("[+]", "write proxy protocol header to target address ["+targetAddress+"]") + c.LogMsg("[+] write proxy protocol header to target address ["+targetAddress+"]", nil) err = writeProxyProtocolHeaderV1(target, conn) if err != nil { - log.Println("[x]", "Write proxy protocol header faild: ", err) + c.LogMsg("[x] Write proxy protocol header failed: "+err.Error(), nil) target.Close() conn.Close() - log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]") + c.LogMsg("[←] close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]", nil) time.Sleep(time.Duration(c.Timeout) * time.Second) return } } - forward(target, conn, &c.aTobAccumulatedByteTransfer, &c.bToaAccumulatedByteTransfer) + c.forward(target, conn, &c.aTobAccumulatedByteTransfer, &c.bToaAccumulatedByteTransfer) }(targetAddress) } } diff --git a/src/mod/streamproxy/udpprox.go b/src/mod/streamproxy/udpprox.go index 405739c..dc761df 100644 --- a/src/mod/streamproxy/udpprox.go +++ b/src/mod/streamproxy/udpprox.go @@ -138,12 +138,12 @@ func (c *ProxyRelayInstance) ForwardUDP(address1, address2 string, stopChan chan continue } c.udpClientMap.Store(saddr, conn) - log.Println("[UDP] Created new connection for client " + saddr) + c.LogMsg("[UDP] Created new connection for client "+saddr, nil) // Fire up routine to manage new connection go c.RunUDPConnectionRelay(conn, lisener) } else { - log.Println("[UDP] Found connection for client " + saddr) + c.LogMsg("[UDP] Found connection for client "+saddr, nil) conn = rawConn.(*udpClientServerConn) } diff --git a/src/web/components/streamprox.html b/src/web/components/streamprox.html index f1593d5..c8883bd 100644 --- a/src/web/components/streamprox.html +++ b/src/web/components/streamprox.html @@ -16,6 +16,7 @@ Target Address Mode Timeout (s) + Enable Logging Actions @@ -81,6 +82,14 @@ +
+
+ + +
+
@@ -219,6 +228,10 @@ row.append($('').text(config.ProxyTargetAddr)); row.append($('').text(modeText)); row.append($('').text(config.Timeout)); + row.append($('').html(config.EnableLogging ? + '' : + '' + )); row.append($('').html(` ${startButton} @@ -272,6 +285,14 @@ $(checkboxEle).checkbox("set unchecked"); } return; + }else if (key == "EnableLogging"){ + let checkboxEle = $("#streamProxyForm input[name=enableLogging]").parent(); + if (value === true){ + $(checkboxEle).checkbox("set checked"); + }else{ + $(checkboxEle).checkbox("set unchecked"); + } + return; }else if (key == "ListeningAddress"){ field = $("#streamProxyForm input[name=listenAddr]"); }else if (key == "ProxyTargetAddr"){ @@ -322,6 +343,7 @@ useTCP: $("#streamProxyForm input[name=useTCP]")[0].checked , useUDP: $("#streamProxyForm input[name=useUDP]")[0].checked , useProxyProtocol: $("#streamProxyForm input[name=useProxyProtocol]")[0].checked , + enableLogging: $("#streamProxyForm input[name=enableLogging]")[0].checked , timeout: parseInt($("#streamProxyForm input[name=timeout]").val().trim()), }, success: function(response) {