@@ -33,8 +33,8 @@ import (
3333)
3434
3535const (
36- readTimeout time.Duration = 10 * time .Second
37- writeTimeout time.Duration = 10 * time .Second
36+ readTimeout time.Duration = 3 * time .Second
37+ writeTimeout time.Duration = 3 * time .Second
3838 timeout time.Duration = 10 * time .Second
3939 hopTimeout time.Duration = 3 * time .Second
4040 flushTimeout time.Duration = 10 * time .Millisecond
@@ -46,6 +46,7 @@ const (
4646var (
4747 supportedChainTypes = []string {"strict" , "dynamic" , "random" , "round_robin" }
4848 SupportedTProxyModes = []string {"redirect" , "tproxy" }
49+ errInvalidWrite = errors .New ("invalid write result" )
4950)
5051
5152// Hop-by-hop headers
@@ -476,7 +477,9 @@ func (p *proxyapp) handleTunnel(w http.ResponseWriter, r *http.Request) {
476477 w .WriteHeader (http .StatusServiceUnavailable )
477478 return
478479 }
479- dstConn , err = sockDialer .Dial ("tcp" , r .Host )
480+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
481+ defer cancel ()
482+ dstConn , err = sockDialer .(proxy.ContextDialer ).DialContext (ctx , "tcp" , r .Host )
480483 if err != nil {
481484 p .logger .Error ().Err (err ).Msgf ("Failed connecting to %s" , r .Host )
482485 http .Error (w , err .Error (), http .StatusServiceUnavailable )
@@ -513,9 +516,56 @@ func (p *proxyapp) handleTunnel(w http.ResponseWriter, r *http.Request) {
513516 wg .Wait ()
514517}
515518
516- func (p * proxyapp ) transfer (wg * sync.WaitGroup , destination io.Writer , source io.Reader , destName , srcName string ) {
519+ func (p * proxyapp ) copyWithTimeout (dst net.Conn , src net.Conn ) (written int64 , err error ) {
520+ buf := make ([]byte , 32 * 1024 )
521+ for {
522+ er := src .SetReadDeadline (time .Now ().Add (readTimeout ))
523+ if er != nil {
524+ err = er
525+ break
526+ }
527+ nr , er := src .Read (buf )
528+ if nr > 0 {
529+ er := dst .SetWriteDeadline (time .Now ().Add (writeTimeout ))
530+ if er != nil {
531+ err = er
532+ break
533+ }
534+ nw , ew := dst .Write (buf [0 :nr ])
535+ if nw < 0 || nr < nw {
536+ nw = 0
537+ if ew == nil {
538+ ew = errInvalidWrite
539+ }
540+ }
541+ written += int64 (nw )
542+ if ew != nil {
543+ if ne , ok := ew .(net.Error ); ok && ne .Timeout () {
544+ err = ne
545+ break
546+ }
547+ }
548+ if nr != nw {
549+ err = io .ErrShortWrite
550+ break
551+ }
552+ }
553+ if er != nil {
554+ if ne , ok := err .(net.Error ); ok && ne .Timeout () {
555+ err = er
556+ break
557+ }
558+ if er == io .EOF {
559+ break
560+ }
561+ }
562+ }
563+ return written , err
564+ }
565+
566+ func (p * proxyapp ) transfer (wg * sync.WaitGroup , dst net.Conn , src net.Conn , destName , srcName string ) {
517567 defer wg .Done ()
518- n , err := io . Copy ( destination , source )
568+ n , err := p . copyWithTimeout ( dst , src )
519569 if err != nil {
520570 p .logger .Error ().Err (err ).Msgf ("Error during copy from %s to %s: %v" , srcName , destName , err )
521571 }
@@ -718,7 +768,9 @@ func (ts *tproxyServer) handleConnection(srcConn net.Conn) {
718768 ts .pa .logger .Error ().Err (err ).Msg ("[tproxy] Failed getting SOCKS5 client" )
719769 return
720770 }
721- dstConn , err = sockDialer .Dial ("tcp" , dst )
771+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
772+ defer cancel ()
773+ dstConn , err = sockDialer .(proxy.ContextDialer ).DialContext (ctx , "tcp" , dst )
722774 if err != nil {
723775 ts .pa .logger .Error ().Err (err ).Msgf ("[tproxy] Failed connecting to %s" , dst )
724776 return
@@ -835,6 +887,7 @@ type Config struct {
835887 TProxyOnly string
836888 TProxyMode string
837889}
890+
838891type logWriter struct {
839892}
840893
0 commit comments