From e1a0e5bb150a5d117b5b4ff055fe2fa809489d9e Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:55:33 +0300 Subject: [PATCH 1/2] fixed connections leaks, now debug mode of arpspoffing is correctly separated from main app --- README.md | 2 +- go.mod | 2 +- go.sum | 4 ++-- gohpts.go | 38 ++++++++++++++++++++++++++++++-------- tproxy_linux.go | 4 ++-- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index eb4828d..6737a95 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ You can download the binary for your platform from [Releases](https://github.com Example: ```shell -HPTS_RELEASE=v1.9.0; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$HPTS_RELEASE/gohpts-$HPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$HPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h +HPTS_RELEASE=v1.9.1; wget -v https://github.com/shadowy-pycoder/go-http-proxy-to-socks/releases/download/$HPTS_RELEASE/gohpts-$HPTS_RELEASE-linux-amd64.tar.gz -O gohpts && tar xvzf gohpts && mv -f gohpts-$HPTS_RELEASE-linux-amd64 gohpts && ./gohpts -h ``` Alternatively, you can install it using `go install` command (requires Go [1.24](https://go.dev/doc/install) or later): diff --git a/go.mod b/go.mod index d0c5ea3..b27dfec 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/google/uuid v1.6.0 github.com/rs/zerolog v1.34.0 github.com/shadowy-pycoder/colors v0.0.1 - github.com/shadowy-pycoder/mshark v0.0.7 + github.com/shadowy-pycoder/mshark v0.0.8 golang.org/x/net v0.40.0 golang.org/x/sys v0.33.0 golang.org/x/term v0.32.0 diff --git a/go.sum b/go.sum index 1f7e8dd..ff783d4 100644 --- a/go.sum +++ b/go.sum @@ -30,8 +30,8 @@ github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= github.com/shadowy-pycoder/colors v0.0.1 h1:weCj/YIOupqy4BSP8KuVzr20fC+cuAv/tArz7bhhkP4= github.com/shadowy-pycoder/colors v0.0.1/go.mod h1:lkrJS1PY2oVigNLTT6pkbF7B/v0YcU2LD5PZnss1Q4U= -github.com/shadowy-pycoder/mshark v0.0.7 h1:iuCLxKXh0HhukrZOQIbXjGneTTOZSPIS0mkIBSJm/4U= -github.com/shadowy-pycoder/mshark v0.0.7/go.mod h1:FqbHFdsx0zMnrZZH0+oPzaFcleP4O+tUWv8i5gxo87k= +github.com/shadowy-pycoder/mshark v0.0.8 h1:7kuVgX9Qp4Q9nGl9Gi7UOaNFUnOF0I2Vpfmc4X3GLug= +github.com/shadowy-pycoder/mshark v0.0.8/go.mod h1:FqbHFdsx0zMnrZZH0+oPzaFcleP4O+tUWv8i5gxo87k= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= diff --git a/gohpts.go b/gohpts.go index 195d6c4..4dc6d6d 100644 --- a/gohpts.go +++ b/gohpts.go @@ -40,9 +40,10 @@ import ( ) const ( - readTimeout time.Duration = 3 * time.Second - writeTimeout time.Duration = 3 * time.Second + readTimeout time.Duration = 30 * time.Second + writeTimeout time.Duration = 30 * time.Second timeout time.Duration = 10 * time.Second + shutdownTimeout time.Duration = 30 * time.Second hopTimeout time.Duration = 3 * time.Second flushTimeout time.Duration = 10 * time.Millisecond availProxyUpdateInterval time.Duration = 30 * time.Second @@ -589,12 +590,15 @@ func (p *proxyapp) updateSocksList() { if err != nil && !errors.Is(err, io.EOF) { // check for EOF to include localhost SOCKS5 in the chain p.logger.Error().Err(err).Msgf("%s Unable to connect to %s", ctl, pr.Address) failed++ + if conn != nil { + conn.Close() + } continue } else { + p.availProxyList = append(p.availProxyList, proxyEntry{Address: pr.Address, Username: pr.Username, Password: pr.Password}) if conn != nil { conn.Close() } - p.availProxyList = append(p.availProxyList, proxyEntry{Address: pr.Address, Username: pr.Username, Password: pr.Password}) break } } @@ -619,6 +623,9 @@ func (p *proxyapp) updateSocksList() { conn, err := dialer.(proxy.ContextDialer).DialContext(ctx, "tcp", pr.Address) if err != nil { p.logger.Error().Err(err).Msgf("%s Unable to connect to %s", ctl, pr.Address) + if conn != nil { + conn.Close() + } continue } conn.Close() @@ -1094,6 +1101,9 @@ readLoop: default: er := src.SetReadDeadline(time.Now().Add(readTimeout)) if er != nil { + if errors.Is(er, net.ErrClosed) { + break readLoop + } err = er break readLoop } @@ -1101,6 +1111,9 @@ readLoop: if nr > 0 { er := dst.SetWriteDeadline(time.Now().Add(writeTimeout)) if er != nil { + if errors.Is(er, net.ErrClosed) { + break readLoop + } err = er break readLoop } @@ -1120,7 +1133,9 @@ readLoop: written += int64(nw) if ew != nil { if ne, ok := ew.(net.Error); ok && ne.Timeout() { - err = ne + break readLoop + } + if errors.Is(ew, net.ErrClosed) { break readLoop } } @@ -1130,13 +1145,17 @@ readLoop: } } if er != nil { - if ne, ok := err.(net.Error); ok && ne.Timeout() { - err = er + if ne, ok := er.(net.Error); ok && ne.Timeout() { + break readLoop + } + if errors.Is(er, net.ErrClosed) { break readLoop } if er == io.EOF { break readLoop } + err = er + break readLoop } } } @@ -1158,7 +1177,10 @@ func (p *proxyapp) transfer( if err != nil { p.logger.Error().Err(err).Msgf("Error during copy from %s to %s: %v", srcName, destName, err) } - p.logger.Debug().Msgf("copied %s from %s to %s", prettifyBytes(n), srcName, destName) + if n > 0 { + p.logger.Debug().Msgf("copied %s from %s to %s", prettifyBytes(n), srcName, destName) + } + src.Close() } func parseProxyAuth(auth string) (username, password string, ok bool) { @@ -1527,7 +1549,7 @@ func (p *proxyapp) Run() { tproxyServer.Shutdown() } p.logger.Info().Msg("Server is shutting down...") - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) defer cancel() p.httpServer.SetKeepAlivesEnabled(false) diff --git a/tproxy_linux.go b/tproxy_linux.go index 1caaa31..542aa46 100644 --- a/tproxy_linux.go +++ b/tproxy_linux.go @@ -79,7 +79,7 @@ func (ts *tproxyServer) serve() { case <-ts.quit: return default: - ts.pa.logger.Error().Err(err).Msg("") + ts.pa.logger.Error().Err(err).Msg("Failed accepting connection") } } else { ts.wg.Add(1) @@ -237,7 +237,7 @@ func (ts *tproxyServer) Shutdown() { case <-done: ts.pa.logger.Info().Msgf("[%s] Server gracefully shutdown", ts.pa.tproxyMode) return - case <-time.After(timeout): + case <-time.After(shutdownTimeout): ts.pa.logger.Error().Msgf("[%s] Server timed out waiting for connections to finish", ts.pa.tproxyMode) return } From 0d9c25bbb6017d54126f679f350b957832fdadeb Mon Sep 17 00:00:00 2001 From: shadowy-pycoder <35629483+shadowy-pycoder@users.noreply.github.com> Date: Tue, 22 Jul 2025 10:56:25 +0300 Subject: [PATCH 2/2] bumped to v1.9.1 --- version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.go b/version.go index 1edd6b6..1d0f968 100644 --- a/version.go +++ b/version.go @@ -1,3 +1,3 @@ package gohpts -const Version string = "gohpts v1.9.0" +const Version string = "gohpts v1.9.1"